Code archives/Miscellaneous/Object-Oriented MaxGUI Wrapper

This code has been declared by its author to be Public Domain code.

Download source code

Object-Oriented MaxGUI Wrapper by Nilium
(Posted 21 years ago)
I'm sure the majority of people who have worked with MaxGUI have noticed that its base class (and what seems to be its only class, which is just plain bad design since the base class is obscenely top-heavy) is extremely bloated and a huge pain to work with the vast majority of the time.

So, basically, what I did was write a bunch of gadget classes that are vaguely similar to .NET (unfortunately, there was a loss of true event handlers, but you can override the OnPaint/OnMove/OnResize/etc. methods the classes provide or set the On*Handler callbacks). I find it easier to work with, some of you may prefer the more procedural public interface of MaxGUI. Personally, I don't.

Standard sample:
Strict

Import "engine/guiwrap.bmx"

Global Running% = True

Type extWindow Extends IWindow
    Method OnClose( evt:TEvent )
        Super.OnClose( evt )
        Running = False
        Hide( )
    End Method
End Type

Local window:extWindow = New extWindow
window.Create( Null, 64, 64, 512, 512, "matEdit" )

window.Show( )

Local tree:ITreeView = New ITreeView
tree.Create( window, 24, 24, 190, 480 )
Local node:ITreeNode = tree.AddNode( "Blah" )
node.AddNode( "Foo" )
node.AddNode( "Bar" )

While Not AppTerminate( ) And Running
    WaitEvent( )
Wend

End


So here's the code...
SuperStrict

Import "collections.bmx"

Import Brl.Event
Import Brl.EventQueue
Import MaxGui.MaxGui
?Win32
Import MaxGui.Win32MaxGui
?MacOS
Import MaxGui.CocoaMaxGui
?Linux
Import MaxGui.FLTKMaxGui
?

Private
Function _gadUpdate:Object( id%, obj:Object, ctx:Object )
    Local gad:IGadget = IGadget(ctx)
    Local evt:TEvent = TEvent(obj)
    If Not gad Or Not evt Then Return obj
    Local m:IMenu = IMenu(gad)
    If (evt.id = EVENT_MENUACTION And m = Null) Or gad.gad = Null Then Return obj
    If evt.source <> gad.gad And m = Null Then Return obj
    If gad._freed Then Return obj
    Select evt.id
        Case EVENT_MOUSEENTER
            gad.OnEnter( evt )
        Case EVENT_MOUSELEAVE
            gad.OnLeave( evt )
        Case EVENT_KEYDOWN
            gad.OnKeyDown( evt )
        Case EVENT_KEYUP
            gad.OnKeyUp( evt )
        Case EVENT_KEYCHAR
            gad.OnKeyChar( evt )
        Case EVENT_MOUSEMOVE
            gad.OnMouseMove( evt )
        Case EVENT_MOUSEWHEEL
            gad.OnMouseWheel( evt )
        Case EVENT_MOUSEDOWN
            gad.OnMouseDown( evt )
        Case EVENT_MENUACTION
            If m.id = evt.data Then m.OnAction( evt )
        Case EVENT_WINDOWMOVE
            If IWindow(gad) Then IWindow(gad).OnMove( evt )
        Case EVENT_WINDOWACTIVATE
            If IWindow(gad) Then IWindow(gad).OnFocus( evt )
        Case EVENT_WINDOWSIZE
            If IWindow(gad) Then IWindow(gad).OnResize( evt )
        Case EVENT_WINDOWACCEPT
            If IWindow(gad) Then IWindow(gad).OnDragDrop( evt )
        Case EVENT_WINDOWCLOSE
            If IWindow(gad) Then IWindow(gad).OnClose( evt )
        Case EVENT_GADGETOPEN
            If ITreeView(gad) Then ITreeView(gad).OnExpand( evt )
        Case EVENT_GADGETCLOSE
            If ITreeView(gad) Then ITreeView(gad).OnCollapse( evt )
        Case EVENT_GADGETSELECT
            If ITreeView(gad) Then ITreeView(gad).OnSelect( evt )
        Case EVENT_GADGETMENU
            Local txt:ITextbox = ITextbox( gad )
            Local tv:ITreeView = ITreeView( gad )
            If txt Then
                txt.OnMenu( evt )
            ElseIf tv Then
                tv.OnMenu( evt )
            EndIf
        Case EVENT_GADGETDONE
            If IHTMLView(gad) Then IHTMLView( gad ).OnLoaded( evt )
        Case EVENT_GADGETACTION
            gad.OnAction( evt )
        Case EVENT_GADGETPAINT
            If ICanvas(gad) Then ICanvas(gad).OnPaint( evt )
    End Select
    Return obj
End Function

Public
Type IGadget Abstract
    Field _freed:Int = 0
    Field gad:TGadget
    Field _children:IList = New IList
    Field _parent:IGadget
    Field _link:ILink
    Field OnActionHandler(sender:IGadget, event:TEvent)
    Field OnEnterHandler(sender:IGadget, event:TEvent)
    Field OnLeaveHandler(sender:IGadget, event:TEvent)
    Field OnKeyUpHandler(sender:IGadget, event:TEvent)
    Field OnKeyDownHandler(sender:IGadget, event:TEvent)
    Field OnKeyCharHandler(sender:IGadget, event:TEvent)
    Field OnMouseWheelHandler(sender:IGadget, event:TEvent)
    Field OnMouseUpHandler(sender:IGadget, event:TEvent)
    Field OnMouseDownHandler(sender:IGadget, event:TEvent)
    Field OnMouseMoveHandler(sender:IGadget, event:TEvent)
    Field OnPaintHandler(sender:IGadget, event:TEvent)
    Field OnHotKeyHitHandler(sender:IGadget, event:TEvent)
    Field OnInitHandler(sender:IGadget, event:TEvent)'event should always be null for OnInitHandler
    
    Method Init:TGadget( parent:IGadget )
        If _freed Then Return Null
        _parent = parent
        If _parent Then _link = _parent._children.AddLast( Self )
        Local par:TGadget = Null
        If _parent Then par = _parent.gad
        Return par
    End Method
    
    Method OnInit( evt:TEvent )
        If OnInitHandler Then OnInitHandler(Self, evt)
    End Method
    
    Method OnAction( evt:TEvent )
        If OnActionHandler Then OnActionHandler(Self, evt)
    End Method
    
    Method OnEnter( evt:TEvent )
        If _freed Then Return
        If OnEnterHandler Then OnEnterHandler(Self, evt)
    End Method
    
    Method OnLeave( evt:TEvent )
        If _freed Then Return
        If OnLeaveHandler Then OnLeaveHandler(Self, evt)
    End Method
    
    Method OnKeyDown( evt:TEvent )
        If _freed Then Return
        If OnKeyDownHandler Then OnKeyDownHandler(Self, evt)
    End Method
    
    Method OnKeyUp( evt:TEvent )
        If _freed Then Return
        If OnKeyUpHandler Then OnKeyUpHandler(Self, evt)
    End Method
    
    Method OnKeyChar( evt:TEvent )
        If _freed Then Return
        If OnKeyCharHandler Then OnKeyCharHandler(Self, evt)
    End Method
    
    Method OnMouseWheel( evt:TEvent )
        If _freed Then Return
        If OnMouseWheelHandler Then OnMouseWheelHandler(Self, evt)
    End Method
    
    Method OnMouseDown( evt:TEvent )
        If _freed Then Return
        If OnMouseDownHandler Then OnMouseDownHandler(Self, evt)
    End Method
    
    Method OnMouseUp( evt:TEvent )
        If _freed Then Return
        If OnMouseUpHandler Then OnMouseUpHandler(Self, evt)
    End Method
    
    Method OnMouseMove( evt:TEvent )
        If _freed Then Return
        If OnMouseMoveHandler Then OnMouseMoveHandler(Self, evt)
    End Method
    
    Method OnHotkeyHit( evt:TEvent )
        If _freed Then Return
        If OnHotkeyHitHandler Then OnHotkeyHitHandler(Self, evt)
    End Method
    
    Method New( )
        AddHook( EmitEventHook, _gadUpdate, Self )
    End Method
    
    Method Delete( )
        Free( )
    End Method
    
    Method Free( )
        If _freed Then Return
        RemoveHook( EmitEventHook, _gadUpdate, Self )
        For Local i:IGadget = EachIn _children
            i.Free( )
        Next
        gad.Free( )
        gad = Null
        OnActionHandler = Null
        OnEnterHandler = Null
        OnLeaveHandler = Null
        OnKeyUpHandler = Null
        OnKeyDownHandler = Null
        OnKeyCharHandler = Null
        OnMouseWheelHandler = Null
        OnMouseUpHandler = Null
        OnMouseDownHandler = Null
        OnMouseMoveHandler = Null
        OnHotKeyHitHandler = Null
        OnInitHandler = Null
        _freed = True
    End Method
        
    Method GetState%( )
        If _freed Then Return 0
        Return gad.State( )
    End Method
        
    ' Layout
    Method Layout( l%, r%, t%, b% )
        If _freed Then Return
        gad.SetLayout( l, r, t, b )
    End Method
    
    ' parenting
    Method GetParent:IGadget( )
        If _freed Then Return Null
        Return _parent
    End Method
    
    Method GetChild:IGadget( idx% )
        If _freed Then Return Null
        Return IGadget(_children.ValueAtIndex(idx))
    End Method
    
    ' position
    Method SetPosition( x%, y% )
        If _freed Then Return
        gad.SetShape( x, y, gad.width, gad.height )
    End Method
    
    Method SetSize( w%, h% )
        If _freed Then Return
        gad.SetShape( gad.xpos, gad.ypos, w, h )
    End Method
    
    Method GetPosition( x% Var, y% Var )
        If _freed Then Return
        x = gad.xpos
        y = gad.ypos
    End Method
    
    Method GetSize( x% Var, y% Var )
        If _freed Then Return
        x = gad.width
        y = gad.height
    End Method
    
    Method GetClientSize( x% Var, y% Var )
        If _freed Then Return
        x = gad.ClientWidth( )
        y = gad.ClientHeight( )
    End Method
    
    Method GetClientWidth%( )
        If _freed Then Return 0
        Local x%,y%
        GetClientSize( x, y )
        Return x
    End Method
    
    Method GetClientHeight%( )
        If _freed Then Return 0
        Local x%,y%
        GetClientSize( x, y )
        Return y
    End Method
    
    Method GetX%( )
        If _freed Then Return 0
        Local x%,y%
        GetPosition( x, y )
        Return x
    End Method
    
    Method GetY%( )
        If _freed Then Return 0
        Local x%,y%
        GetPosition( x, y )
        Return y
    End Method
    
    Method GetWidth%( )
        If _freed Then Return 0
        Local x%,y%
        GetSize( x, y )
        Return x
    End Method
    
    Method GetHeight%( )
        If _freed Then Return 0
        Local x%,y%
        GetSize( x, y )
        Return y
    End Method
    
    ' Enabled
    Method Disable( )
        If _freed Then Return
        gad.SetEnabled( False )
    End Method
    
    Method Enable( )
        If _freed Then Return
        gad.SetEnabled( True )
    End Method
    
    ' Hidden
    Method Hide( )
        If _freed Then Return
        gad.SetShow( False )
    End Method
    
    Method Show( )
        If _freed Then Return
        gad.SetShow( True )
    End Method
    
    ' Active
    Method Activate( cmd% = ACTIVATE_FOCUS )
        If _freed Then Return
        gad.Activate( cmd )
    End Method
    
    ' Focus
    Method Focus( )
        If _freed Then Return
        Activate( ACTIVATE_FOCUS )
    End Method
    
    ' Redraw
    Method Redraw( )
        If _freed Then Return
        Activate( ACTIVATE_REDRAW )
    End Method
    
    ' Alpha
    Method SetAlpha( a# )
        If _freed Then Return
        gad.SetAlpha( a )
    End Method
    
    ' Color
    Method SetTextColor( r%, g%, b% )
        If _freed Then Return
        gad.SetTextColor( r, g, b )
    End Method
    
    Method SetBackColor( r%, g%, b% )
        If _freed Then Return
        gad.SetColor( r, g, b )
    End Method
    
    ' Font
    Method SetFont( font:TGuiFont )
        If _freed Then Return
        gad.SetFont( font )
    End Method
    
    Method SetCaption( text$ )
        If _freed Then Return
        gad.SetText( text )
    End Method
    
    ' Text
    Method GetText$( )
        If _freed then Return ""
        Return gad.GetText( )
    End Method
    
    Method SetText( t$ )
        If _freed Then Return
        gad.SetText( t )
    End Method
    
    ' Query
    Method Query%( q% )
        If _freed Then Return 0
        Return gad.Query( q )
    End Method
End Type

Type IDesktop Extends IGadget
    Method New( )
        gad = Desktop( )
    End Method
End Type

Type IWindow Extends IGadget
    Field rootMenu:IMenu
    Field OnFocusHandler(sender:IGadget, e:TEvent)
    Field OnCloseHandler(sender:IGadget, e:TEvent)
    Field OnMoveHandler(sender:IGadget, e:TEvent)
    Field OnResizeHandler(sender:IGadget, e:TEvent)
    Field OnDragDropHandler(sender:IGadget, e:TEvent)
    
    Method OnFocus( evt:TEvent )
        If _freed Then Return
        If OnFocusHandler Then OnFocusHandler(Self, evt)
    End Method
    
    Method OnClose( evt:TEvent )
        If _freed Then Return
        If OnCloseHandler Then OnCloseHandler(Self, evt)
    End Method
    
    Method OnMove( evt:TEvent )
        If _freed Then Return
        If OnMoveHandler Then OnMoveHandler(Self, evt)
    End Method
    
    Method OnResize( evt:TEvent )
        If _freed Then Return
        If OnResizeHandler Then OnResizeHandler(Self, evt)
    End Method
    
    Method OnDragDrop( evt:TEvent )
        If _freed Then Return
        If OnDragDropHandler Then OnDragDropHandler(Self, evt)
    End Method
    
    Method Free( )
        If _freed Then Return
        For Local i:IGadget = eachIn rootmenu._children
            i.Free( )
        Next
        rootmenu._children.Clear( )
        rootmenu._children = Null
        rootmenu._parent = Null
        rootmenu.gad = Null
        rootmenu = Null
        OnFocusHandler = Null
        OnCloseHandler = Null
        OnMoveHandler = Null
        OnResizeHandler = Null
        OnDragDropHandler = Null
        Super.Free( )
    End Method
    
    Method Create( parent:IGadget, x%, y%, w%, h%, caption$, titlebar%=1, sizable%=1, menu%=1, statusbar%=1, hidden%=1, dragdrop%=0, tool%=0 )
        If _freed Then Return
        Local f:Int = WINDOW_CLIENTCOORDS
        If titlebar>0 Then f :| WINDOW_TITLEBAR
        If sizable>0 Then f :| WINDOW_RESIZABLE
        If menu>0 Then f:| WINDOW_MENU
        If statusbar>0 Then f :| WINDOW_STATUS
        If hidden>0 Then f :| WINDOW_HIDDEN
        If dragdrop>0 Then f:| WINDOW_ACCEPTFILES
        If tool>0 Then f :| WINDOW_TOOL
        gad = CreateWindow( caption, x, y, w, h, Init( parent ), f )
        rootmenu = New IMenu
        rootmenu.gad = gad.GetMenu( )
        rootmenu._parent = Self
        OnInit( Null )
    End Method
    
    Method AddMenu:IMenu( caption$, tag%, hotkey%=0, modifier%=0 )
        If _freed Then Return Null
        Local menu:IMenu = New IMenu
        menu.Create( rootmenu, caption, tag, hotkey, modifier )
        Return menu
    End Method
    
    Method UpdateMenu( )
        If _freed then Return
        gad.UpdateMenu( )
    End Method
    
    Method Maximized%( )
        If _freed Then Return 0
        Return GetState( ) & STATE_MAXIMIZED
    End Method
    
    Method Maximize( )
        If _freed Then Return
        Activate( ACTIVATE_MAXIMIZE )
    End Method
    
    Method Minimized%( )
        If _freed Then Return 0
        Return GetState( ) & STATE_MINIMIZED
    End Method
    
    Method Minimize( )
        If _freed Then Return
        Activate( ACTIVATE_MINIMIZE )
    End Method
    
    Method Restore( )
        If _freed Then Return
        Activate( ACTIVATE_RESTORE )
    End Method
    
    Method SetMinimumSize( w%, h% )
        If _freed Then Return
        gad.SetMinimumSize( w, h )
    End Method
    
    Method SetStatusText( text$ )
        If _freed Then Return
        gad.SetStatus( text )
    End Method
    
    Method Hwnd%( )
        Return Query( QUERY_HWND )
    End Method
End Type

Const BUTTON_NORMAL%=0
Type IButton Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h%, caption$, type_%=BUTTON_NORMAL ) 'type_ can be BUTTON_OK, BUTTON_CANCEL, or BUTTON_NORMAL
        If _freed Then Return
        Local f% = BUTTON_PUSH | type_
        gad = CreateButton( caption, x, y, w, h, Init( parent ), f )
        OnInit( Null )
    End Method
End Type

Type ICheckbox Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h%, caption$, checked%=0 )
        If _freed Then Return
        Local f% = BUTTON_CHECKBOX
        gad = CreateButton( caption, x, y, w, h, Init( parent ), f )
        If checked>0 Then Check( )
        OnInit( Null )
    End Method
    
    Field chk:Int = 0
    
    Method Check( )
        If _freed Then Return
        gad.SetSelected( True )
        chk = True
    End Method
    
    Method Uncheck( )
        If _freed Then Return
        gad.SetSelected( False )
        chk = False
    End Method
    
    Method Checked%( )
        If _freed Then Return -1
        Return chk
    End Method
End Type

Type IRadioGroup
    Field _link:ILink
    Field group%
    Field tickers:IList = New IList
    
    Method New( )
        _link = radioGroups.AddLast( Self )
    End Method
    
    Method Remove( gad:IRadiobox )
        gad._glink.Remove( )
        gad._glink = Null
        If tickers.Count( ) = 0 Then
            _link.Remove( )
            _link = Null
            tickers = Null
        EndIf
    End Method
End Type
Private
Global radioGroups:IList = New IList
Public

Type IRadiobox Extends IGadget
    Field group:Object
    Field _glink:ILink
    Field chk%=0
    
    Method Free( )
        If _freed then Return
        IRadioGroup(group).Remove( Self )
        Super.Free( )
    End Method
    
    Method Create( parent:IGadget, x%, y%, w%, h%, caption$, group%, ticked%=0 )
        If _freed Then Return
        Local f% = BUTTON_RADIO
        gad = CreateButton( caption, x, y, w, h, Init( parent ), f )
        
        Local g:IRadioGroup = Null
        For Local i:IRadioGroup = EachIn radioGroups
            If i.group = group Then
                g = i
                Exit
            EndIf
        Next
        
        If Not g Then
            g = New IRadioGroup
            g.group = group
        EndIf
        
        _glink = g.tickers.AddLast( Self )
        
        OnInit( Null )
    End Method
    
    Method Check( )
        If _freed Then Return
        gad.SetSelected( True )
        chk = True
        For Local i:IRadiobox = EachIn IRadioGroup(group).tickers
            If i <> Self Then i.Uncheck( )
        Next
    End Method
    
    Method Uncheck( )
        If _freed Then Return
        gad.SetSelected( False )
        chk = False
    End Method
    
    Method Checked%( )
        If _freed Then Return -1
        Return chk
    End Method
    
    Method OnAction( evt:TEvent )
        Check( )
        Super.OnAction( evt )
    End Method
End Type

Type ICanvas Extends IGadget
    Field gfx:TGraphics
    Field OnPaintHandler( s:IGadget, e:TEvent )
    
    Method OnPaint( evt:TEvent )
        If _freed Then Return
        If OnPaintHandler Then OnPaintHandler(Self, evt)
    End Method
    
    Method Free( )
        If _freed Then Return
        OnPaintHandler = Null
        Super.Free( )
    End Method
    
    Method Create( parent:IGadget, x%, y%, w%, h%, border%=0 )
        If _freed Then Return
        Local f% = (border>0)*PANEL_BORDER
        gad = CreateCanvas( x, y, w, h, Init( parent ), f )
        gfx = gad.CanvasGraphics( )
        OnInit( Null )
    End Method
End Type

Type IPanel Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h%, border%=0, moveEvent%=0 )
        If _freed Then Return
        Local f% = (border>0)*PANEL_BORDER|((moveEvent>0)*PANEL_ACTIVE)
        gad = CreatePanel( x, y, w, h, Init( parent ), f, "" )
        OnInit( Null )
    End Method
    
    Method SetPixmap( pix:TPixmap, flags%=PANELPIXMAP_TILE )
        If _freed Then Return
        gad.SetPixmap( pix, flags )
    End Method
End Type

Type IGroupbox Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h%, caption$, moveEvent%=0 )
        If _freed Then Return
        Local f% = PANEL_GROUP|((moveEvent>0)*PANEL_ACTIVE)
        gad = CreatePanel( x, y, w, h, Init( parent ), f, caption )
        OnInit( Null )
    End Method
End Type

Type IComboBox Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h%, editable%=0 )
        If _freed Then Return
        Local f% = (editable>0)*COMBOBOX_EDITABLE
        gad = CreateComboBox( x, y, w, h, Init( parent ), f )
        OnInit( Null )
    End Method
    
    Method SelectedItem%( )
        If _freed Then Return 0
        Return gad.SelectedItem( )
    End Method
    
    Method SelectItem( idx% )
        If _freed Then Return
        gad.SelectItem( idx, 1 )
    End Method
    
    Method AddItem%( caption$, icon%=-1, isDefault%=0, tip$="", extra:Object=Null )
        If _freed Then Return 0
        AddGadgetItem( gad, caption, (isDefault>0)*GADGETITEM_DEFAULT, icon, tip, extra )
        Return gad.ItemCount( ) - 1
    End Method
    
    Method RemoveItem( idx% )
        If _freed Then Return
        RemoveGadgetItem( gad, idx )
    End Method
    
    Method GetItemCaption$( idx% )
        If _freed Then Return ""
        Return GadgetItemText( gad, idx )
    End Method
    
    Method GetItemExtra:Object( idx% )
        If _freed Then Return Null
        Return GadgetItemExtra( gad, idx )
    End Method
End Type

Type IHTMLView Extends IGadget
    Field OnLoadedHandler(sender:IGadget, e:TEvent)
    
    Method Create( parent:IGadget, x%, y%, w%, h%, nonav%=0, noctx%=0 )
        If _freed Then Return
        Local f% = 0
        If nonav>0 Then f :| HTMLVIEW_NONAVIGATE
        If noctx>0 Then f :| HTMLVIEW_NOCONTEXTMENU
        gad = CreateHTMLView( x, y, w, h, Init( parent ), f )
        OnInit( Null )
    End Method
    
    Method GetURL$( )
        If _freed Then Return ""
        Return gad.GetText( )
    End Method
    
    Method SetURL( url$ )
        If _freed Then Return
        gad.SetText( url )
    End Method
    
    Method Back( )
        If _freed Then Return
        Activate( ACTIVATE_BACK )
    End Method
    
    Method Forward( )
        If _freed Then Return
        Activate( ACTIVATE_FORWARD )
    End Method
    
    Method RunScript$( script$ )
        If _freed Then Return ""
        Return gad.Run( script )
    End Method
    
    Method OnLoaded( evt:TEvent )
        If OnLoadedHandler Then OnLoadedHandler(Self, evt)
    End Method
End Type

Const LABEL_LEFT% = 0
Const LABEL_NOFRAME% = 0
Type ILabel Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h%, text$, frameType%=LABEL_NOFRAME, align%=LABEL_LEFT )
        If _freed Then Return
        Local f% = frameType|align
        If text="--" Then f :| LABEL_SEPARATOR
        gad = CreateLabel( text, x, y, w, h, Init( parent ), f )
        OnInit( Null )
    End Method
End Type

Type IListBox Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h% )
        If _freed Then Return
        Local f% = 0
        gad = CreateListBox( x, y, w, h, Init( parent ), f )
        OnInit( Null )
    End Method
    
    Method AddItem%( caption$, icon%=-1, isDefault%=0, tip$="", extra:Object=Null )
        If _freed Then Return 0
        AddGadgetItem( gad, caption, (isDefault>0)*GADGETITEM_DEFAULT, icon, tip, extra )
        Return gad.ItemCount( ) - 1
    End Method
    
    Method SelectItem( idx% )
        If _freed Then Return
        gad.SelectItem( idx, 1 )
    End Method
    
    Method RemoveItem( idx% )
        If _freed Then Return
        RemoveGadgetItem( gad, idx )
    End Method
    
    Method SelectedItem%( )
        If _freed Then Return 0
        Return gad.SelectedItem( )
    End Method
    
    Method SelectedItems%[]( )
        If _freed Then Return Null
        Return gad.SelectedItems( )
    End Method
    
    Method GetItemCaption$( idx% )
        If _freed Then Return ""
        Return GadgetItemText( gad, idx )
    End Method
    
    Method GetItemExtra:Object( idx% )
        If _freed Then Return Null
        Return GadgetItemExtra( gad, idx )
    End Method
End Type

Type IMenu Extends IGadget
    Field OnSelectHandler(sender:IGadget, e:TEvent)
    Field id:Int
    Field chk:Int=0
    
    Method Free( )
        If _freed Then Return
        OnSelectHandler = Null
        Super.Free( )
    End Method
    
    Method Create( parent:IGadget, caption$, tag%, hotkey%=0, modifier%=0 )
        If _freed Then Return
        gad = CreateMenu( caption, tag, Init(parent), hotkey, modifier )
        id = tag
        OnInit( Null )
    End Method
    
    Method AddMenu:IMenu( caption$, tag%, hotkey%=0, modifier%=0 )
        If _freed Then Return Null
        Local menu:IMenu = New IMenu
        menu.Create( Self, caption, tag, hotkey, modifier )
        Return menu
    End Method
    
    Method OnSelect( evt:TEvent )
        If OnSelectHandler Then OnSelectHandler(Self, evt)
    End Method
    
    Method Popup( on:IGadget )
        If _freed Then Return
        on.gad.PopupMenu( gad )
    End Method
    
    Method Check( )
        If _freed Then Return
        gad.SetSelected( True )
        chk = True
    End Method
    
    Method Uncheck( )
        If _freed Then Return
        gad.SetSelected( False )
        chk = False
    End Method
    
    Method Checked%( )
        If _freed Then Return -1
        Return chk
    End Method
End Type

Type IProgressBar Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h% )
        If _freed Then Return
        gad = CreateProgBar( x, y, w, h, Init(parent), 0 )
        OnInit( Null )
    End Method
    
    Method SetValue( progress# )
        If _freed Then Return
        gad.SetValue( progress )
    End Method
End Type

Type ISlider Extends IGadget
    Method SetRange( min_%, max_% )
        If _freed Then Return
        gad.SetRange( min_, max_ )
    End Method
    
    Method SetValue( value% )
        If _freed Then Return
        gad.SetProp( value )
    End Method
    
    Method GetValue%( )
        If _freed Then Return 0
        Return gad.GetProp( )
    End Method
End Type

Type IScrollbar Extends ISlider
    Const _flags%=SLIDER_SCROLLBAR
    
    Method Create( parent:IGadget, x%, y%, w%, h%, vertical%=0, range_min%=1, range_max%=10 )
        If _freed Then Return
        Local f% = SLIDER_HORIZONTAL
        If vertical>0 Then f = SLIDER_VERTICAL
        f :| _flags
        gad = CreateSlider( x, y, w, h, Init(parent), f )
        SetRange( range_min, range_max )
        OnInit( Null )
    End Method
End Type

Type ITracker Extends ISlider
    Const _flags%=SLIDER_TRACKBAR
    
    Method Create( parent:IGadget, x%, y%, w%, h%, vertical%=0, range_min%=1, range_max%=10 )
        If _freed Then Return
        Local f% = SLIDER_HORIZONTAL
        If vertical>0 Then f = SLIDER_VERTICAL
        f :| _flags
        gad = CreateSlider( x, y, w, h, Init(parent), f )
        SetRange( range_min, range_max )
        OnInit( Null )
    End Method
End Type

Type IStepper Extends ISlider
    Const _flags%=SLIDER_STEPPER
    
    Method Create( parent:IGadget, x%, y%, w%, h%, vertical%=0, range_min%=1, range_max%=10 )
        If _freed Then Return
        Local f% = SLIDER_HORIZONTAL
        If vertical>0 Then f = SLIDER_VERTICAL
        f :| _flags
        gad = CreateSlider( x, y, w, h, Init(parent), f )
        SetRange( range_min, range_max )
        OnInit( Null )
    End Method
End Type

' Dial slider apparently isn't supported by Win32MaxGUI?

Type ITabStrip Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h% )
        If _freed Then Return
        gad = CreateTabber( x, y, w, h, Init(parent), 0 )
        OnInit( Null )
    End Method
    
    Method AddPage%( caption$, icon%=-1, tip$="", extra:Object=Null )
        If _freed Then Return -1
        AddGadgetItem( gad, caption, False, icon, tip, extra )
        Return gad.ItemCount( ) - 1
    End Method
    
    Method RemovePage( idx% )
        RemoveGadgetItem( gad, idx )
    End Method
    
    Method SelectPage( page% )
        If _freed Then Return
        gad.SelectItem( page, 1 )
    End MEthod
    
    Method SelectedPage%( )
        If _freed Then Return 0
        Return gad.SelectedItem( )
    End Method
End Type

Type ITextBox Extends IGadget
    Field _area:Int=0
    Field OnMenuHandler(sender:IGadget, e:TEvent)
    
    Method Free( )
        If _freed Then Return
        OnMenuHandler = Null
        Super.Free( )
    End Method
    
    Method Create( parent:IGadget, x%, y%, w%, h%, text$="", multiline%=0, readonly%=0, wordwrap%=0, password%=0 )
        If _freed Then Return
        Local par:TGadget = Init(parent)
        Local f% = 0
        If multiline>0 Then
            _area = True
            If readonly>0 Then f :| TEXTAREA_READONLY
            If wordwrap>0 Then f :| TEXTAREA_WORDWRAP
            gad = CreateTextArea( x, y, w, h, par, f )
        Else
            If password>0 Then f :| TEXTFIELD_PASSWORD
            gad = CreateTextField( x, y, w, h, par, f )
        EndIf
        OnInit( Null )
    End Method
    
    Method OnMenu( evt:TEvent )
        If OnMenuHandler Then OnMenuHandler(Self, evt)
    End Method
    
    Field _fbuf$=""
    Field _lock%=0
    
    Method SelectText$( from%=0, length%=-1, selectLines%=0 )
        If _freed Then Return ""
        If _area Then
            Local f% = TEXTAREA_CHARS
            If selectLines>0 Then f = TEXTAREA_LINES
            If length = -1 Then length = TEXTAREA_ALL
            Return gad.AreaText( from, length, f% )
        Else
            Local s$
            If Not _lock Then
                s = gad.GetText( )
            Else
                s = _fbuf
            EndIf
            If (length = -1 Or length=s.Length) And from = 0 Then Return s
            If length = -1 Then length = s.Length-from
            Return s[from..from+length]
        EndIf
    End Method
    
    Method GetText$( )
        If _freed Then Return ""
        Return SelectText( )
    End Method
    
    Method SetText( t$ )
        If _freed then Return
        ReplaceText( t )
    End Method
    
    Method ReplaceText( t$, pos%=0, length%=-1, lines%=0 )
        If _freed Then Return
        If _area Then
            If length = -1 Then length = TEXTAREA_ALL
            If lines>0 Then
                lines = TEXTAREA_LINES
            Else
                lines = TEXTAREA_CHARS
            EndIf
            gad.ReplaceText( pos, length, t, lines )
        Else
            If _lock Then
                If pos = 0 And (length = -1 Or length=_fbuf.Length) Then
                    _fbuf = t
                    Return
                EndIf
                
                If length = -1 Then length = _fbuf.Length-pos
                
                If pos=_fbuf.Length Then
                    _fbuf :+ t
                ElseIf pos=0 And length=0 Then
                    _fbuf = t+_fbuf
                ElseIf pos+length = _fbuf.Length Then
                    _fbuf = t+_fbuf[..pos]
                ElseIf pos=0 Then
                    _fbuf = _fbuf[length..]+t
                Else
                    _fbuf = _fbuf[0..pos]+t+_fbuf[pos+length..]
                EndIf
            Else
                Local s$
                If pos = 0 And (length = -1 Or length=_fbuf.Length) Then
                    s = t
                Else
                    If length = -1 Then length = _fbuf.Length-pos
                    s = GetText( )
                    
                    If pos=_fbuf.Length Then
                        s :+ t
                    ElseIf pos=0 And length=0 Then
                        s = t+s
                    ElseIf pos+length = s.Length Then
                        s = s[..pos]+t
                    ElseIf pos=0 Then
                        s = t+s[length..]
                    Else
                        s = s[..pos]+t+s[pos+length..]
                    EndIf
                EndIf
                gad.SetText( s )
            EndIf
        EndIf
    End Method
    
    Method GetPos%( lines%=False )
        If _freed Then Return 0
        If Not _area Then Return 0
        Local f% = TEXTAREA_CHARS
        If lines>0 Then f = TEXTAREA_LINES
        Return gad.GetCursorPos( f )
    End Method
    
    Method Lock( )
        If _freed Then Return
        _lock :+ 1
        If _lock = 1 And _area Then
            gad.LockText( )
        ElseIf _lock = 1 Then
            _fbuf = GetText( )
        EndIf
    End Method
    
    Method Unlock( )
        If _freed Then Return
        Assert _lock>0, "Text box not locked"
        _lock :- 1
        If _lock = 0 And _area Then
            gad.UnlockText( )
        ElseIf _lock = 0 Then
            SetText( _fbuf )
        EndIf
    End Method
End Type

Type IToolbar Extends IGadget
    Method Create( parent:IGadget, x%, y%, w%, h%, source:Object )
        If _freed Then Return
        gad = CreateToolbar( source, x, y, w, h, Init(parent), 0 )
        OnInit( Null )
    End Method
    
    Method SetTips( tips$[] )
        For Local i:Int = 0 To tips.Length-1
            SetItem( i, "", 0, i, tips[i] )
        Next
    End Method
    
    Method SetItem( idx%, caption$, toggle%=0, icon%=-1, tip$="", extra:Object=Null )
        ModifyGadgetItem( gad, idx, caption, (toggle>0)*GADGETITEM_TOGGLE, icon, tip, extra )
    End Method
    
    Method AddItem( caption$, toggle%=0, icon%=-1, tip$="", extra:Object=Null )
        If _freed Then Return
        AddGadgetItem( gad, caption, (toggle>0)*GADGETITEM_TOGGLE, icon, tip, extra )
    End Method
    
    Method RemoveItem( idx% )
        If _freed Then Return
        RemoveGadgetItem( gad, idx )
    End Method
    
    Method GetItemCaption$( idx% )
        If _freed Then Return ""
        Return GadgetItemText( gad, idx )
    End Method
    
    Method GetItemExtra:Object( idx% )
        If _freed Then Return Null
        Return GadgetItemExtra( gad, idx )
    End Method
End Type

Type ITreeView Extends IGadget
    Field OnMenuHandler(sender:IGadget, e:TEvent)
    Field OnSelectHandler(sender:IGadget, e:TEvent)
    Field OnExpandHandler(sender:IGadget, e:TEvent)
    Field OnCollapseHandler(sender:IGadget, e:TEvent)
    Field root:ITreeNode
    
    Method Free( )
        If _freed = True Then Return
        For Local i:IGadget = EachIn root._children
            i.Free( )
        Next
        root._children.Clear( )
        root._children = Null
        root._parent = Null
        root.gad = Null
        root = Null
        OnMenuHandler = Null
        OnSelectHandler = Null
        OnExpandHandler = Null
        OnCollapseHandler = Null
        Super.Free( )
    End Method
    
    Method Create( parent:IGadget, x%, y%, w%, h% )
        If _freed Then Return
        gad = CreateTreeView( x,y,w,h,Init(parent),0 )
        root = New ITreeNode
        root._parent = Self
        root.gad = TreeViewRoot( gad )
        OnInit( Null )
    End Method
    
    Method AddNode:ITreeNode( text$, icon%=-1 )
        If _freed Then Return Null
        Local node:ITreeNode = New ITreeNode
        node.Create( root, text, icon )
        Return node
    End Method
    
    Method OnMenu( evt:TEvent )
        If OnMenuHandler Then OnMenuHandler(Self, evt)
    End Method
    
    Method OnSelect( evt:TEvent )
        If OnSelectHandler Then OnSelectHandler(Self, evt)
    End Method
    
    Method OnExpand( evt:TEvent )
        If OnExpandHandler Then OnExpandHandler(Self, evt)
    End Method
    
    Method OnCollapse( evt:TEvent )
        If OnCollapseHandler Then OnCollapseHandler(Self, evt)
    End Method
    
    Method Clear( )
        If _freed Then Return
        For Local i:IGadget = EachIn root._children
            i.Free( )
        Next
    End Method
    
    Method GetRoot:ITreeNode( )
        If _freed Then Return Null
        Return root
    End Method
    
    Method GetSelected:ITreeNode( )
        If _freed Then Return Null
        Local sel:TGadget = gad.SelectedNode( )
        If sel = Null Then Return Null
        Return root.FindByGad( sel )
    End Method
End Type

Type ITreeNode Extends IGadget
    Method Create( parent:IGadget, text$, icon%=-1 )
        If _freed Then Return
        gad = AddTreeViewNode( text, Init(parent), icon )
        OnInit( Null )
    End Method
    
    Method Clear( )
        If _freed Then Return
        For Local i:IGadget = EachIn _children
            i.Free( )
        Next
    End Method
    
    Method AddNode:ITreeNode( text$, icon%=-1 )
        If _freed Then Return Null
        Local node:ITreeNode = New ITreeNode
        node.Create( Self, text, icon )
        Return node
    End Method
    
    Method SelectNode( )
        If _freed Then Return
        gad.Activate( ACTIVATE_SELECT )
    End Method
    
    Method Expand( )
        If _freed Then Return
        gad.Activate( ACTIVATE_EXPAND )
    End Method
    
    Method Collapse( )
        If _freed Then Return
        gad.Activate( ACTIVATE_COLLAPSE )
    End Method
    
    Method FindByGad:ITreeNode( g:TGadget )
        If _freed Then Return Null
        If gad = g Then Return Self
        For Local i:ITreeNode = EachIn _children
            Local o:ITreeNode = i.FindByGad( g )
            If o Then Return o
        Next
        Return Null
    End Method
End Type

Comments

OJay
(Posted 21 years ago)
cool thx, but PLEASE use the [codebox]-tags rather then the [code] ones! thx

Perturbatio
(Posted 21 years ago)
cool thx, but PLEASE use the codebox-tags rather then the [code] ones! thx


you can't when posting to the archives.

Nilium
(Posted 21 years ago)
What Pert said.

Nilium
(Posted 21 years ago)
Just added a new version that's 1) SuperStrict'd and 2) got callback functions for events. So now you can either a) override the On*(evt:TEvent) methods in an extended class or set the On*Handler(sender:IGadget, event:TEvent) callback fields and the gadget will handle calling them.

altitudems
(Posted 21 years ago)
Nice work, I'll have to try this.

Nilium
(Posted 21 years ago)
Added a lot more auxiliary functions. I'm happy with it now.

computercoder
(Posted 20 years ago)
Cool! THANK YOU for this code :)

I was gonna do something along this line, but since you so generously posted... :)

Blueapples
(Posted 20 years ago)
This is some sweet stuff, man. You have made the GUI portion of my project much easier to write. I was contemplating creating another massive Select Case tree to handle GUI events from multiple windows, this is going to make things way easier. Thank you!

Nilium
(Posted 20 years ago)
I've updated this to include some changes I've made since I actually wrote it a year ago. There's also a couple examples of custom gadgets at the bottom of the code (one of a rollout, although it's nearly impossible to get any decent functionality of that sort in MaxGUI).

Dreamora
(Posted 19 years ago)
Great wrapper

Highly suggested for all those not willing to hack around in stone age C style any further :)

Otus
(Posted 18 years ago)
Here's a module version with (mostly auto-generated) bbdoc comments for help and highlighting. I also fixed a couple of bugs; and added GetExtra and SetExtra methods, and ICheckButton and IRadioButton types. The only functional changes are moving radioGroups to IRadioGroup.list and adding a couple of default values for parameters.

SuperStrict

Rem
bbdoc: MaxGUI/Interface
End Rem
Module MaxGUI.Interface

Import MaxGUI.MaxGUI

Rem
bbdoc: Gadget base type
End Rem
Type IGadget Abstract
	
	Field _freed:Int = 0
	
	Field gad:TGadget
	
	Field _children:TList = New TList
	
	Field _parent:IGadget
	
	Field _link:TLink
	
Rem
bbdoc: OnAction event handler
End Rem
	Field OnActionHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnEnter event handler
End Rem
	Field OnEnterHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnLeave event handler
End Rem
	Field OnLeaveHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnKeyUp event handler
End Rem
	Field OnKeyUpHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnKeyDown event handler
End Rem
	Field OnKeyDownHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnKeyChar event handler
End Rem
	Field OnKeyCharHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnMouseWheel event handler
End Rem
	Field OnMouseWheelHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnMouseUp event handler
End Rem
	Field OnMouseUpHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnMouseDown event handler
End Rem
	Field OnMouseDownHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnMouseMove event handler
End Rem
	Field OnMouseMoveHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnPaint event handler
End Rem
	Field OnPaintHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnHotKeyHit event handler
End Rem
	Field OnHotKeyHitHandler(sender:IGadget, event:TEvent)
	
Rem
bbdoc: OnInit event handler
End Rem
	Field OnInitHandler(sender:IGadget, event:TEvent)
	
	'event should always be null for OnInitHandler
Rem
bbdoc: AddChild method
returns: TLink
End Rem
	Method AddChild:TLink(c:IGadget, x:Int, y:Int, w:Int, h:Int)
		Return _children.AddLast(c)
	End Method
	
Rem
bbdoc: GetParentingTGadget method
returns: TGadget
End Rem
	Method GetParentingTGadget:TGadget()
		Return gad
	End Method
	
Rem
bbdoc: Get wrapped TGadget
returns: TGadget
End Rem
	Method GetTGadget:TGadget()
		Return gad
	End Method
	
Rem
bbdoc: Init method
returns: TGadget
End Rem
	Method Init:TGadget(parent:IGadget, x:Int, y:Int, w:Int, h:Int)
		If _freed
			Return Null
		End If
		_parent = parent
		If _parent
			_link = _parent.AddChild(Self, x, y, w, h)
		End If
		Local par:TGadget = Null
		
		If _parent
			par = _parent.GetParentingTGadget()
		End If
		Return par
	End Method
	
Rem
bbdoc: OnInit event handler method
End Rem
	Method OnInit(evt:TEvent)
		If OnInitHandler
			OnInitHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnAction event handler method
End Rem
	Method OnAction(evt:TEvent)
		If OnActionHandler
			OnActionHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnEnter event handler method
End Rem
	Method OnEnter(evt:TEvent)
		If OnEnterHandler
			OnEnterHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnLeave event handler method
End Rem
	Method OnLeave(evt:TEvent)
		If OnLeaveHandler
			OnLeaveHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnKeyDown event handler method
End Rem
	Method OnKeyDown(evt:TEvent)
		If OnKeyDownHandler
			OnKeyDownHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnKeyUp event handler method
End Rem
	Method OnKeyUp(evt:TEvent)
		If OnKeyUpHandler
			OnKeyUpHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnKeyChar event handler method
End Rem
	Method OnKeyChar(evt:TEvent)
		If OnKeyCharHandler
			OnKeyCharHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnMouseWheel event handler method
End Rem
	Method OnMouseWheel(evt:TEvent)
		If OnMouseWheelHandler
			OnMouseWheelHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnMouseDown event handler method
End Rem
	Method OnMouseDown(evt:TEvent)
		If OnMouseDownHandler
			OnMouseDownHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnMouseUp event handler method
End Rem
	Method OnMouseUp(evt:TEvent)
		If OnMouseUpHandler
			OnMouseUpHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnMouseMove event handler method
End Rem
	Method OnMouseMove(evt:TEvent)
		If OnMouseMoveHandler
			OnMouseMoveHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnHotkeyHit event handler method
End Rem
	Method OnHotkeyHit(evt:TEvent)
		If OnHotKeyHitHandler
			OnHotKeyHitHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnPaint event handler method
End Rem
	Method OnPaint(evt:TEvent)
		If OnPaintHandler
			OnPaintHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: New method
End Rem
	Method New()
		AddHook EmitEventHook, _gadUpdate, Self
	End Method
	
Rem
bbdoc: Delete method
End Rem
	Method Delete()
		Free
	End Method
	
Rem
bbdoc: Free method
End Rem
	Method Free()
		If _freed
			Return
		End If
	RemoveHook EmitEventHook, _gadUpdate, Self
		For Local i:IGadget = EachIn _children
			i.Free
		Next
		gad.Free
		gad = Null
		OnActionHandler = Null
		OnEnterHandler = Null
		OnLeaveHandler = Null
		OnKeyUpHandler = Null
		OnKeyDownHandler = Null
		OnKeyCharHandler = Null
		OnMouseWheelHandler = Null
		OnMouseUpHandler = Null
		OnMouseDownHandler = Null
		OnMouseMoveHandler = Null
		OnPaintHandler = Null
		OnHotKeyHitHandler = Null
		OnInitHandler = Null
		_freed = True
	End Method
	
Rem
bbdoc: GetState method
returns: Int
End Rem
	Method GetState:Int()
		Return gad.State()
	End Method
	
	' Layout
Rem
bbdoc: Layout method
End Rem
	Method Layout(l:Int, r:Int, t:Int, b:Int)
		If _freed
			Return
		End If
		gad.SetLayout l, r, t, b
	End Method
	
	' parenting
Rem
bbdoc: GetParent method
returns: IGadget
End Rem
	Method GetParent:IGadget()
		If _freed
			Return Null
		End If
		Return _parent
	End Method
	
Rem
bbdoc: GetChild method
returns: IGadget
End Rem
	Method GetChild:IGadget(idx:Int)
		If _freed
			Return Null
		End If
		Return IGadget(_children.ValueAtIndex(idx))
	End Method
	
Rem
bbdoc: Set gadget extra data
End Rem
	Method SetExtra(extra:Object) 
		If _freed
			Return
		End If
		gad.extra = extra
	End Method
	
Rem
bbdoc: Get gadget extra data
returns: Object
End Rem
	Method GetExtra:Object()
		If _freed
			Return Null
		End If
		Return gad.extra
	End Method
	
Rem
bbdoc: SetPosition method
End Rem
	Method SetPosition(x:Int, y:Int)
		If _freed
			Return
		End If
		gad.SetShape x, y, gad.width, gad.height
	End Method
	
Rem
bbdoc: SetSize method
End Rem
	Method SetSize(w:Int, h:Int)
		If _freed
			Return
		End If
		gad.SetShape gad.xpos, gad.ypos, w, h
	End Method
	
Rem
bbdoc: GetPosition method
End Rem
	Method GetPosition(x:Int Var, y:Int Var)
		If _freed
			Return
		End If
		x = gad.xpos
		y = gad.ypos
	End Method
	
Rem
bbdoc: GetSize method
End Rem
	Method GetSize(x:Int Var, y:Int Var)
		If _freed
			Return
		End If
		x = gad.width
		y = gad.height
	End Method
	
Rem
bbdoc: GetX method
returns: Int
End Rem
	Method GetX:Int()
		If _freed
			Return 0
		End If
		Local x:Int
		Local y:Int
		
		GetPosition x, y
		Return x
	End Method
	
Rem
bbdoc: GetY method
returns: Int
End Rem
	Method GetY:Int()
		If _freed
			Return 0
		End If
		Local x:Int
		Local y:Int
		
		GetPosition x, y
		Return y
	End Method
	
Rem
bbdoc: GetWidth method
returns: Int
End Rem
	Method GetWidth:Int()
		If _freed
			Return 0
		End If
		Local x:Int
		Local y:Int
		
		GetSize x, y
		Return x
	End Method
	
Rem
bbdoc: GetHeight method
returns: Int
End Rem
	Method GetHeight:Int()
		If _freed
			Return 0
		End If
		Local x:Int
		Local y:Int
		
		GetSize x, y
		Return y
	End Method
	
	' Enabled
Rem
bbdoc: Disable method
End Rem
	Method Disable()
		If _freed
			Return
		End If
		gad.SetEnabled False
	End Method
	
Rem
bbdoc: Enable method
End Rem
	Method Enable()
		If _freed
			Return
		End If
		gad.SetEnabled True
	End Method
	
	' Hidden
Rem
bbdoc: Hide method
End Rem
	Method Hide()
		If _freed
			Return
		End If
		gad.SetShow False
	End Method
	
Rem
bbdoc: Show method
End Rem
	Method Show()
		If _freed
			Return
		End If
		gad.SetShow True
	End Method
	
	' Active
Rem
bbdoc: Activate method
End Rem
	Method Activate(cmd:Int)
		If _freed
			Return
		End If
		gad.Activate cmd
	End Method
	
	' Focus
Rem
bbdoc: Focus method
End Rem
	Method Focus()
		If _freed
			Return
		End If
		Activate ACTIVATE_FOCUS
	End Method
	
	' Redraw
Rem
bbdoc: Redraw method
End Rem
	Method Redraw()
		If _freed
			Return
		End If
		Activate ACTIVATE_REDRAW
	End Method
	
	' Alpha
Rem
bbdoc: SetAlpha method
End Rem
	Method SetAlpha(a:Float)
		If _freed
			Return
		End If
		gad.SetAlpha a
	End Method
	
	' Color
Rem
bbdoc: SetTextColor method
End Rem
	Method SetTextColor(r:Int, g:Int, b:Int)
		If _freed
			Return
		End If
		gad.SetTextColor r, g, b
	End Method
	
Rem
bbdoc: SetBackColor method
End Rem
	Method SetBackColor(r:Int, g:Int, b:Int)
		If _freed
			Return
		End If
		gad.SetColor r, g, b
	End Method
	
	' Font
Rem
bbdoc: SetFont method
End Rem
	Method SetFont(font:TGuiFont)
		If _freed
			Return
		End If
		gad.SetFont font
	End Method
	
Rem
bbdoc: SetCaption method
End Rem
	Method SetCaption(text:String)
		If _freed
			Return
		End If
		gad.SetText text
	End Method
	
	' Text
Rem
bbdoc: GetText method
returns: String
End Rem
	Method GetText:String()
		If _freed
			Return ""
		End If
		Return gad.GetText()
	End Method
	
Rem
bbdoc: SetText method
End Rem
	Method SetText(t:String)
		If _freed
			Return
		End If
		gad.SetText t
	End Method
	
End Type

Rem
bbdoc: Desktop gadget type
End Rem
Type IDesktop Extends IGadget
Rem
bbdoc: New method
End Rem
	Method New()
		gad = Desktop()
	End Method
	
End Type

Rem
bbdoc: Window gadget type
End Rem
Type IWindow Extends IGadget
Rem
bbdoc: rootMenu field
End Rem
	Field rootMenu:IMenu
	
Rem
bbdoc: OnFocus event handler
End Rem
	Field OnFocusHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: OnClose event handler
End Rem
	Field OnCloseHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: OnMove event handler
End Rem
	Field OnMoveHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: OnResize event handler
End Rem
	Field OnResizeHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: OnDragDrop event handler
End Rem
	Field OnDragDropHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: OnFocus event handler method
End Rem
	Method OnFocus(evt:TEvent)
		If OnFocusHandler
			OnFocusHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnClose event handler method
End Rem
	Method OnClose(evt:TEvent)
		If OnCloseHandler
			OnCloseHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnMove event handler method
End Rem
	Method OnMove(evt:TEvent)
		If OnMoveHandler
			OnMoveHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnResize event handler method
End Rem
	Method OnResize(evt:TEvent)
		If OnResizeHandler
			OnResizeHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnDragDrop event handler method
End Rem
	Method OnDragDrop(evt:TEvent)
		If OnDragDropHandler
			OnDragDropHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: Free method
End Rem
	Method Free()
		If _freed
			Return
		End If
		For Local i:IGadget = EachIn rootMenu._children
			i.Free
		Next
		rootMenu._children.Clear
		rootMenu._children = Null
		rootMenu._parent = Null
		rootMenu.gad = Null
		rootMenu = Null
		OnFocusHandler = Null
		OnCloseHandler = Null
		OnMoveHandler = Null
		OnResizeHandler = Null
		OnDragDropHandler = Null
		Super.Free
	End Method
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, caption:String, titlebar:Int = 1, sizable:Int = 1, menu:Int = 1, statusbar:Int = 1, hidden:Int = 1, dragdrop:Int = 0, tool:Int = 0)
		If _freed
			Return
		End If
		Local f:Int = WINDOW_CLIENTCOORDS
		
		If (titlebar > 0)
			f :| WINDOW_TITLEBAR
		End If
		If (sizable > 0)
			f :| WINDOW_RESIZABLE
		End If
		If (menu > 0)
			f :| WINDOW_MENU
		End If
		If (statusbar > 0)
			f :| WINDOW_STATUS
		End If
		If (hidden > 0)
			f :| WINDOW_HIDDEN
		End If
		If (dragdrop > 0)
			f :| WINDOW_ACCEPTFILES
		End If
		If (tool > 0)
			f :| WINDOW_TOOL
		End If
		gad = CreateWindow(caption, x, y, w, h, Init(parent, x, y, w, h), f)
		rootMenu = New IMenu
		rootMenu.gad = gad.GetMenu()
		rootMenu._parent = Self
		OnInit Null
	End Method
	
Rem
bbdoc: AddMenu method
returns: IMenu
End Rem
	Method AddMenu:IMenu(caption:String, tag:Int, hotkey:Int = 0, modifier:Int = 0)
		If _freed
			Return Null
		End If
		Local menu:IMenu = New IMenu
		
		menu.Create rootMenu, caption, tag, hotkey, modifier
		Return menu
	End Method
	
Rem
bbdoc: UpdateMenu method
End Rem
	Method UpdateMenu()
		If _freed
			Return
		End If
		gad.UpdateMenu
	End Method
	
Rem
bbdoc: Maximized method
returns: Int
End Rem
	Method Maximized:Int()
		If _freed
			Return 0
		End If
		Return (GetState() & STATE_MAXIMIZED)
	End Method
	
Rem
bbdoc: Maximize method
End Rem
	Method Maximize()
		If _freed
			Return
		End If
		Activate ACTIVATE_MAXIMIZE
	End Method
	
Rem
bbdoc: Minimized method
returns: Int
End Rem
	Method Minimized:Int()
		If _freed
			Return 0
		End If
		Return (GetState() & STATE_MINIMIZED)
	End Method
	
Rem
bbdoc: Minimize method
End Rem
	Method Minimize()
		If _freed
			Return
		End If
		Activate ACTIVATE_MINIMIZE
	End Method
	
Rem
bbdoc: Restore method
End Rem
	Method Restore()
		If _freed
			Return
		End If
		Activate ACTIVATE_RESTORE
	End Method
	
Rem
bbdoc: SetMinimumSize method
End Rem
	Method SetMinimumSize(w:Int, h:Int)
		If _freed
			Return
		End If
		gad.SetMinimumSize w, h
	End Method
	
Rem
bbdoc: SetStatusText method
End Rem
	Method SetStatusText(text:String)
		If _freed
			Return
		End If
		gad.SetStatus text
	End Method
	
End Type

Rem
bbdoc: Button gadget type
End Rem
Type IButton Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, caption:String, type_:Int=BUTTON_NORMAL)
		If _freed
			Return
		End If
		Local f:Int = (BUTTON_PUSH | type_)
		
		gad = CreateButton(caption, x, y, w, h, Init(parent, x, y, w, h), f)
		OnInit Null
	End Method
	
End Type

Const BUTTON_NORMAL:Int = 0

Rem
bbdoc: Checkbox gadget type
End Rem
Type ICheckbox Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, caption:String, checked:Int = False)
		If _freed
			Return
		End If
		Local f:Int = BUTTON_CHECKBOX
		
		gad = CreateButton(caption, x, y, w, h, Init(parent, x, y, w, h), f)
		If (checked > 0)
			Check
		End If
		OnInit Null
	End Method
	
Rem
bbdoc: chk field
End Rem
	Field chk:Int = 0
	
Rem
bbdoc: Check method
End Rem
	Method Check()
		If _freed
			Return
		End If
		gad.SetSelected True
		chk = True
	End Method
	
Rem
bbdoc: Uncheck method
End Rem
	Method Uncheck()
		If _freed
			Return
		End If
		gad.SetSelected False
		chk = False
	End Method
	
Rem
bbdoc: Checked method
returns: Int
End Rem
	Method Checked:Int()
		If _freed
			Return - 1
		End If
		Return chk
	End Method
	
End Type

Rem
bbdoc: A checkbutton is a button that functions as a checkbox. It may not be available on all platforms.
End Rem
Type ICheckButton Extends ICheckbox
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, caption:String, checked:Int = False)
		If _freed
			Return
		End If
		Local f:Int = BUTTON_CHECKBOX | BUTTON_PUSH
		
		gad = CreateButton(caption, x, y, w, h, Init(parent, x, y, w, h), f)
		If (checked > 0)
			Check
		End If
		OnInit Null
	End Method
	
End Type

Rem
bbdoc: RadioGroup gadget type
End Rem
Type IRadioGroup
	
	Global list:TList = New TList
	
	Field _link:TLink
	
Rem
bbdoc: Group id field
End Rem
	Field group:Int
	
Rem
bbdoc: List of radioboxes
End Rem
	Field tickers:TList = New TList
	
	Method New()
		_link = list.AddLast(Self)
	End Method
	
Rem
bbdoc: Remove a radiobox from its group, deleting group if empty.
End Rem
	Method Remove(gad:IRadiobox)
		gad._glink.Remove
		gad._glink = Null
		If (tickers.Count() = 0)
			_link.Remove
			_link = Null
			tickers = Null
		End If
	End Method
	
End Type

Rem
bbdoc: Radiobox gadget type
End Rem
Type IRadiobox Extends IGadget
Rem
bbdoc: The group this belongs to
End Rem
	Field group:IRadioGroup
	
	Field _glink:TLink
	
Rem
bbdoc: Checked of not
End Rem
	Field chk:Int = 0
	
Rem
bbdoc: Free method
End Rem
	Method Free()
		If _freed
			Return
		End If
		group.Remove Self
		Super.Free
	End Method
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, caption:String, groupid:Int, ticked:Int = False)
		If _freed
			Return
		End If
		Local f:Int = BUTTON_RADIO
		
		gad = CreateButton(caption, x, y, w, h, Init(parent, x, y, w, h), f)
		Local g:IRadioGroup = Null
		
		For Local i:IRadioGroup = EachIn IRadioGroup.list
			If (i.group = groupid)
				g = i
				Exit
			End If
		Next
		If Not g
			g = New IRadioGroup
			g.group = groupid
		End If
		group = g
		_glink = g.tickers.AddLast(Self)
		OnInit Null
	End Method
	
Rem
bbdoc: Check method
End Rem
	Method Check()
		If _freed
			Return
		End If
		gad.SetSelected True
		chk = True
		For Local i:IRadiobox = EachIn group.tickers
			If (i <> Self)
				i.Uncheck
			End If
		Next
	End Method
	
Rem
bbdoc: Uncheck method
End Rem
	Method Uncheck()
		If _freed
			Return
		End If
		gad.SetSelected False
		chk = False
	End Method
	
Rem
bbdoc: Checked method
returns: Int
End Rem
	Method Checked:Int()
		If _freed
			Return - 1
		End If
		Return chk
	End Method
	
Rem
bbdoc: OnAction event handler method
End Rem
	Method OnAction(evt:TEvent)
		Check
		Super.OnAction evt
	End Method
	
End Type

Rem
bbdoc: A radiobutton is a button functioning as a radio box. It may not be available on all platforms.
End Rem
Type IRadioButton Extends IRadiobox
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, caption:String, groupid:Int, ticked:Int = False)
		If _freed
			Return
		End If
		Local f:Int = BUTTON_RADIO | BUTTON_PUSH
		
		gad = CreateButton(caption, x, y, w, h, Init(parent, x, y, w, h), f)
		Local g:IRadioGroup = Null
		
		For Local i:IRadioGroup = EachIn IRadioGroup.list
			If (i.group = groupid)
				g = i
				Exit
			End If
		Next
		If Not g
			g = New IRadioGroup
			g.group = groupid
		End If
		group = g
		_glink = g.tickers.AddLast(Self)
		OnInit Null
	End Method
	
End Type

Rem
bbdoc: Canvas gadget type
End Rem
Type ICanvas Extends IGadget
Rem
bbdoc: Graphics object
End Rem
	Field gfx:TGraphics
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, border:Int = 0)
		If _freed
			Return
		End If
		Local f:Int = ((border > 0) * PANEL_BORDER)
		
		gad = CreateCanvas(x, y, w, h, Init(parent, x, y, w, h), f)
		gfx = gad.CanvasGraphics()
		OnInit Null
	End Method
	
End Type

Rem
bbdoc: Panel gadget type
End Rem
Type IPanel Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, border:Int = 0, moveEvent:Int = 0)
		If _freed
			Return
		End If
		Local f:Int = (((border > 0) * PANEL_BORDER) | ((moveEvent > 0) * PANEL_ACTIVE))
		
		gad = CreatePanel(x, y, w, h, Init(parent, x, y, w, h), f, "")
		OnInit Null
	End Method
	
Rem
bbdoc: SetPixmap method
End Rem
	Method SetPixmap(pix:TPixmap, flags:Int)
		If _freed
			Return
		End If
		gad.SetPixmap pix, flags
	End Method
	
End Type

Rem
bbdoc: Groupbox gadget type
End Rem
Type IGroupbox Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, caption:String, moveEvent:Int = 0)
		If _freed
			Return
		End If
		Local f:Int = (PANEL_GROUP | ((moveEvent > 0) * PANEL_ACTIVE))
		
		gad = CreatePanel(x, y, w, h, Init(parent, x, y, w, h), f, caption)
		OnInit Null
	End Method
	
End Type

Rem
bbdoc: ComboBox gadget type
End Rem
Type IComboBox Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, editable:Int = 0)
		If _freed
			Return
		End If
		Local f:Int = ((editable > 0) * COMBOBOX_EDITABLE)
		
		gad = CreateComboBox(x, y, w, h, Init(parent, x, y, w, h), f)
		OnInit Null
	End Method
	
Rem
bbdoc: SelectedItem method
returns: Int
End Rem
	Method SelectedItem:Int()
		If _freed
			Return 0
		End If
		Return gad.SelectedItem()
	End Method
	
Rem
bbdoc: SelectItem method
End Rem
	Method SelectItem(idx:Int)
		If _freed
			Return
		End If
		gad.SelectItem idx, 1
	End Method
	
Rem
bbdoc: AddItem method
returns: Int
End Rem
	Method AddItem:Int(caption:String, icon:Int = - 1, isDefault:Int = 0, tip:String = "", extra:Object = Null)
		If _freed
			Return 0
		End If
		AddGadgetItem gad, caption, ((isDefault > 0) * GADGETITEM_DEFAULT), icon, tip, extra
		Return (gad.ItemCount() - 1)
	End Method
	
Rem
bbdoc: RemoveItem method
End Rem
	Method RemoveItem(idx:Int)
		If _freed
			Return
		End If
	RemoveGadgetItem gad, idx
	End Method
	
Rem
bbdoc: GetItemCaption method
returns: String
End Rem
	Method GetItemCaption:String(idx:Int)
		If _freed
			Return ""
		End If
		Return GadgetItemText(gad, idx)
	End Method
	
Rem
bbdoc: GetItemExtra method
returns: Object
End Rem
	Method GetItemExtra:Object(idx:Int)
		If _freed
			Return Null
		End If
		Return GadgetItemExtra(gad, idx)
	End Method
	
End Type

Rem
bbdoc: HTMLView gadget type
End Rem
Type IHTMLView Extends IGadget
Rem
bbdoc: OnLoaded event handler
End Rem
	Field OnLoadedHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, nonav:Int = 0, noctx:Int = 0)
		If _freed
			Return
		End If
		Local f:Int = 0
		
		If (nonav > 0)
			f :| HTMLVIEW_NONAVIGATE
		End If
		If (noctx > 0)
			f :| HTMLVIEW_NOCONTEXTMENU
		End If
		gad = CreateHTMLView(x, y, w, h, Init(parent, x, y, w, h), f)
		OnInit Null
	End Method
	
Rem
bbdoc: GetURL method
returns: String
End Rem
	Method GetURL:String()
		If _freed
			Return ""
		End If
		Return gad.GetText()
	End Method
	
Rem
bbdoc: SetURL method
End Rem
	Method SetURL(url:String)
		If _freed
			Return
		End If
		gad.SetText url
	End Method
	
Rem
bbdoc: Back method
End Rem
	Method Back()
		If _freed
			Return
		End If
		Activate ACTIVATE_BACK
	End Method
	
Rem
bbdoc: Forward method
End Rem
	Method Forward()
		If _freed
			Return
		End If
		Activate ACTIVATE_FORWARD
	End Method
	
Rem
bbdoc: RunScript method
returns: String
End Rem
	Method RunScript:String(script:String)
		If _freed
			Return ""
		End If
		Return gad.Run(script)
	End Method
	
Rem
bbdoc: OnLoaded method
End Rem
	Method OnLoaded(evt:TEvent)
		If OnLoadedHandler
			OnLoadedHandler Self, evt
		End If
	End Method
	
End Type

Rem
bbdoc: Label gadget type
End Rem
Type ILabel Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, text:String, frameType:Int=LABEL_NOFRAME, align:Int=LABEL_LEFT)
		If _freed
			Return
		End If
		Local f:Int = (frameType | align)
		
		If (text = "--")
			f :| LABEL_SEPARATOR
		End If
		gad = CreateLabel(text, x, y, w, h, Init(parent, x, y, w, h), f)
		OnInit Null
	End Method
	
End Type

Const LABEL_NOFRAME:Int = 0

Rem
bbdoc: ListBox gadget type
End Rem
Type IListBox Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int)
		If _freed
			Return
		End If
		Local f:Int = 0
		
		gad = CreateListBox(x, y, w, h, Init(parent, x, y, w, h), f)
		OnInit Null
	End Method
	
Rem
bbdoc: AddItem method
returns: Int
End Rem
	Method AddItem:Int(caption:String, icon:Int = - 1, isDefault:Int = 0, tip:String = "", extra:Object = Null)
		If _freed
			Return 0
		End If
		AddGadgetItem gad, caption, ((isDefault > 0) * GADGETITEM_DEFAULT), icon, tip, extra
		Return (gad.ItemCount() - 1)
	End Method
	
Rem
bbdoc: SelectItem method
End Rem
	Method SelectItem(idx:Int)
		If _freed
			Return
		End If
		gad.SelectItem idx, 1
	End Method
	
Rem
bbdoc: RemoveItem method
End Rem
	Method RemoveItem(idx:Int)
		If _freed
			Return
		End If
	RemoveGadgetItem gad, idx
	End Method
	
Rem
bbdoc: SelectedItem method
returns: Int
End Rem
	Method SelectedItem:Int()
		If _freed
			Return 0
		End If
		Return gad.SelectedItem()
	End Method
	
Rem
bbdoc: SelectedItems method
returns: 
End Rem
	Method SelectedItems:Int[]()
		If _freed
			Return Null
		End If
		Return gad.SelectedItems()
	End Method
	
Rem
bbdoc: GetItemCaption method
returns: String
End Rem
	Method GetItemCaption:String(idx:Int)
		If _freed
			Return ""
		End If
		Return GadgetItemText(gad, idx)
	End Method
	
Rem
bbdoc: GetItemExtra method
returns: Object
End Rem
	Method GetItemExtra:Object(idx:Int)
		If _freed
			Return Null
		End If
		Return GadgetItemExtra(gad, idx)
	End Method
	
End Type

Rem
bbdoc: Menu gadget type
End Rem
Type IMenu Extends IGadget
Rem
bbdoc: OnSelect event handler
End Rem
	Field OnSelectHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: id field
End Rem
	Field id:Int
	
Rem
bbdoc: chk field
End Rem
	Field chk:Int = 0
	
Rem
bbdoc: Free method
End Rem
	Method Free()
		If _freed
			Return
		End If
		OnSelectHandler = Null
		Super.Free
	End Method
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, caption:String, tag:Int, hotkey:Int = 0, modifier:Int = 0)
		If _freed
			Return
		End If
		gad = CreateMenu(caption, tag, Init(parent, 0, 0, 0, 0), hotkey, modifier)
		id = tag
		OnInit Null
	End Method
	
Rem
bbdoc: AddMenu method
returns: IMenu
End Rem
	Method AddMenu:IMenu(caption:String, tag:Int, hotkey:Int = 0, modifier:Int = 0)
		If _freed
			Return Null
		End If
		Local menu:IMenu = New IMenu
		
		menu.Create Self, caption, tag, hotkey, modifier
		Return menu
	End Method
	
Rem
bbdoc: OnSelect event handler method
End Rem
	Method OnSelect(evt:TEvent)
		If OnSelectHandler
			OnSelectHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: Popup method
End Rem
	Method Popup(on:IGadget)
		If _freed
			Return
		End If
		on.gad.PopupMenu gad
	End Method
	
Rem
bbdoc: Check method
End Rem
	Method Check()
		If _freed
			Return
		End If
		gad.SetSelected True
		chk = True
	End Method
	
Rem
bbdoc: Uncheck method
End Rem
	Method Uncheck()
		If _freed
			Return
		End If
		gad.SetSelected False
		chk = False
	End Method
	
Rem
bbdoc: Checked method
returns: Int
End Rem
	Method Checked:Int()
		If _freed
			Return - 1
		End If
		Return chk
	End Method
	
End Type

Rem
bbdoc: ProgressBar gadget type
End Rem
Type IProgressBar Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int)
		If _freed
			Return
		End If
		gad = CreateProgBar(x, y, w, h, Init(parent, x, y, w, h), 0)
		OnInit Null
	End Method
	
Rem
bbdoc: SetValue method
End Rem
	Method SetValue(progress:Float)
		If _freed
			Return
		End If
		gad.SetValue progress
	End Method
	
End Type

Rem
bbdoc: Slider gadget type
End Rem
Type ISlider Extends IGadget
Rem
bbdoc: SetRange method
End Rem
	Method SetRange(min_:Int, max_:Int)
		If _freed
			Return
		End If
		gad.SetRange min_, max_
	End Method
	
Rem
bbdoc: SetValue method
End Rem
	Method SetValue(value:Int)
		If _freed
			Return
		End If
		gad.SetProp value
	End Method
	
Rem
bbdoc: GetValue method
returns: Int
End Rem
	Method GetValue:Int()
		If _freed
			Return 0
		End If
		Return gad.GetProp()
	End Method
	
End Type

Rem
bbdoc: Scrollbar gadget type
End Rem
Type IScrollbar Extends ISlider
	Const _flags:Int = SLIDER_SCROLLBAR
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, vertical:Int = 0, range_min:Int = 1, range_max:Int = 10)
		If _freed
			Return
		End If
		Local f:Int = SLIDER_HORIZONTAL
		
		If (vertical > 0)
			f = SLIDER_VERTICAL
		End If
		f :| _flags
		gad = CreateSlider(x, y, w, h, Init(parent, x, y, w, h), f)
		SetRange range_min, range_max
		OnInit Null
	End Method
	
End Type

Rem
bbdoc: Tracker gadget type
End Rem
Type ITracker Extends ISlider
	Const _flags:Int = SLIDER_TRACKBAR
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, vertical:Int = 0, range_min:Int = 1, range_max:Int = 10)
		If _freed
			Return
		End If
		Local f:Int = SLIDER_HORIZONTAL
		
		If (vertical > 0)
			f = SLIDER_VERTICAL
		End If
		f :| _flags
		gad = CreateSlider(x, y, w, h, Init(parent, x, y, w, h), f)
		SetRange range_min, range_max
		OnInit Null
	End Method
	
End Type

Rem
bbdoc: Stepper gadget type
End Rem
Type IStepper Extends ISlider
	Const _flags:Int = SLIDER_STEPPER
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, vertical:Int = 0, range_min:Int = 1, range_max:Int = 10)
		If _freed
			Return
		End If
		Local f:Int = SLIDER_HORIZONTAL
		
		If (vertical > 0)
			f = SLIDER_VERTICAL
		End If
		f :| _flags
		gad = CreateSlider(x, y, w, h, Init(parent, x, y, w, h), f)
		SetRange range_min, range_max
		OnInit Null
	End Method
	
End Type

Rem
bbdoc: TabStrip gadget type
End Rem
Type ITabStrip Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int)
		If _freed
			Return
		End If
		gad = CreateTabber(x, y, w, h, Init(parent, x, y, w, h), 0)
		OnInit Null
	End Method
	
Rem
bbdoc: AddPage method
returns: Int
End Rem
	Method AddPage:Int(caption:String, icon:Int = - 1, tip:String = "", extra:Object = Null)
		If _freed
			Return - 1
		End If
		AddGadgetItem gad, caption, False, icon, tip, extra
		Return (gad.ItemCount() - 1)
	End Method
	
Rem
bbdoc: RemovePage method
End Rem
	Method RemovePage(idx:Int)
	RemoveGadgetItem gad, idx
	End Method
	
Rem
bbdoc: SelectPage method
End Rem
	Method SelectPage(page:Int)
		If _freed
			Return
		End If
		gad.SelectItem page, 1
	End Method
	
Rem
bbdoc: SelectedPage method
returns: Int
End Rem
	Method SelectedPage:Int()
		If _freed
			Return 0
		End If
		Return gad.SelectedItem()
	End Method
	
End Type

Rem
bbdoc: TextBox gadget type
End Rem
Type ITextBox Extends IGadget
	Field _area:Int = 0
	
Rem
bbdoc: OnMenu event handler
End Rem
	Field OnMenuHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: Free method
End Rem
	Method Free()
		If _freed
			Return
		End If
		OnMenuHandler = Null
		Super.Free
	End Method
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, text:String = "", multiline:Int = 0, readonly:Int = 0, wordwrap:Int = 0, password:Int = 0)
		If _freed
			Return
		End If
		Local par:TGadget = Init(parent, x, y, w, h)
		
		Local f:Int = 0
		
		If (multiline > 0)
			_area = True
			If (readonly > 0)
				f :| TEXTAREA_READONLY
			End If
			If (wordwrap > 0)
				f :| TEXTAREA_WORDWRAP
			End If
			gad = CreateTextArea(x, y, w, h, par, f)
			If (password > 0)
				f :| TEXTFIELD_PASSWORD
			End If
			gad = CreateTextField(x, y, w, h, par, f)
		End If
		OnInit Null
	End Method
	
Rem
bbdoc: OnMenu event handler method
End Rem
	Method OnMenu(evt:TEvent)
		If OnMenuHandler
			OnMenuHandler Self, evt
		End If
	End Method
	
	Field _fbuf:String = ""
	
	Field _lock:Int = 0
	
Rem
bbdoc: SelectText method
returns: String
End Rem
	Method SelectText:String(from:Int = 0, length:Int = - 1, selectLines:Int = 0)
		If _freed
			Return ""
		End If
		If _area
			Local f:Int = TEXTAREA_CHARS
			
			If (selectLines > 0)
				f = TEXTAREA_LINES
			End If
			If (length = - 1)
				length = TEXTAREA_ALL
			End If
			Return gad.AreaText(from, length, f)
			Local s:String
			
			If Not _lock
				s = gad.GetText()
				s = _fbuf
			End If
			If (((length = - 1) Or (length = s.length)) And (from = 0))
				Return s
			End If
			If (length = - 1)
				length = (s.length - from)
			End If
			Return s[from..(from + length)]
		End If
	End Method
	
Rem
bbdoc: GetText method
returns: String
End Rem
	Method GetText:String()
		If _freed
			Return ""
		End If
		Return SelectText()
	End Method
	
Rem
bbdoc: SetText method
End Rem
	Method SetText(t:String)
		If _freed
			Return
		End If
		ReplaceText t
	End Method
	
Rem
bbdoc: ReplaceText method
End Rem
	Method ReplaceText(t:String, pos:Int = 0, length:Int = - 1, lines:Int = 0)
		If _freed
			Return
		End If
		If _area
			If (length = - 1)
				length = TEXTAREA_ALL
			End If
			If (lines > 0)
				lines = TEXTAREA_LINES
				lines = TEXTAREA_CHARS
			End If
			gad.ReplaceText pos, length, t, lines
			If _lock
				If ((pos = 0) And ((length = - 1) Or (length = _fbuf.length)))
					_fbuf = t
					Return
				End If
				If (length = - 1)
					length = (_fbuf.length - pos)
				End If
				If (pos = _fbuf.length)
					_fbuf :+ t
				Else If ((pos = 0) And (length = 0))
					_fbuf = (t + _fbuf)
				End If
				Local s:String
				
				If ((pos = 0) And ((length = - 1) Or (length = _fbuf.length)))
					s = t
					If (length = - 1)
						length = (_fbuf.length - pos)
					End If
					s = GetText()
					If (pos = _fbuf.length)
						s :+ t
					Else If ((pos = 0) And (length = 0))
						s = (t + s)
					End If
				End If
				gad.SetText s
			End If
		End If
	End Method
	
Rem
bbdoc: GetPos method
returns: Int
End Rem
	Method GetPos:Int(lines:Int = False)
		If _freed
			Return 0
		End If
		If Not _area
			Return 0
		End If
		Local f:Int = TEXTAREA_CHARS
		
		If (lines > 0)
			f = TEXTAREA_LINES
		End If
		Return gad.GetCursorPos(f)
	End Method
	
Rem
bbdoc: Lock method
End Rem
	Method Lock()
		If _freed
			Return
		End If
		_lock :+ 1
		If ((_lock = 1) And _area)
			gad.LockText
		Else If (_lock = 1)
			_fbuf = GetText()
		End If
	End Method
	
Rem
bbdoc: Unlock method
End Rem
	Method Unlock()
		If _freed
			Return
		End If
		Assert (_lock > 0), "Text box not locked"
		_lock :- 1
		If ((_lock = 0) And _area)
			gad.UnlockText
		Else If (_lock = 0)
			SetText _fbuf
		End If
	End Method
	
End Type

Rem
bbdoc: Toolbar gadget type
End Rem
Type IToolbar Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int, source:Object)
		If _freed
			Return
		End If
		gad = CreateToolBar(source, x, y, w, h, Init(parent, x, y, w, h), 0)
		OnInit Null
	End Method
	
Rem
bbdoc: SetTips method
End Rem
	Method SetTips(tips:String[])
		For Local i:Int = 0 To (tips.length - 1)
			SetItem i, "", 0, i, tips[i]
		Next
	End Method
	
Rem
bbdoc: SetItem method
End Rem
	Method SetItem(idx:Int, caption:String, toggle:Int = 0, icon:Int = - 1, tip:String = "", extra:Object = Null)
		ModifyGadgetItem gad, idx, caption, ((toggle > 0) * GADGETITEM_TOGGLE), icon, tip, extra
	End Method
	
Rem
bbdoc: AddItem method
End Rem
	Method AddItem(caption:String, toggle:Int = 0, icon:Int = - 1, tip:String = "", extra:Object = Null)
		If _freed
			Return
		End If
		AddGadgetItem gad, caption, ((toggle > 0) * GADGETITEM_TOGGLE), icon, tip, extra
	End Method
	
Rem
bbdoc: RemoveItem method
End Rem
	Method RemoveItem(idx:Int)
		If _freed
			Return
		End If
	RemoveGadgetItem gad, idx
	End Method
	
Rem
bbdoc: GetItemCaption method
returns: String
End Rem
	Method GetItemCaption:String(idx:Int)
		If _freed
			Return ""
		End If
		Return GadgetItemText(gad, idx)
	End Method
	
Rem
bbdoc: GetItemExtra method
returns: Object
End Rem
	Method GetItemExtra:Object(idx:Int)
		If _freed
			Return Null
		End If
		Return GadgetItemExtra(gad, idx)
	End Method
	
End Type

Rem
bbdoc: TreeView gadget type
End Rem
Type ITreeView Extends IGadget
Rem
bbdoc: OnMenu event handler
End Rem
	Field OnMenuHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: OnSelect event handler
End Rem
	Field OnSelectHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: OnExpand event handler
End Rem
	Field OnExpandHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: OnCollapse event handler
End Rem
	Field OnCollapseHandler(sender:IGadget, e:TEvent)
	
Rem
bbdoc: Root node
End Rem
	Field root:ITreeNode
	
Rem
bbdoc: Free method
End Rem
	Method Free()
		If (_freed = True)
			Return
		End If
		For Local i:IGadget = EachIn root._children
			i.Free
		Next
		root._children.Clear
		root._children = Null
		root._parent = Null
		root.gad = Null
		root = Null
		OnMenuHandler = Null
		OnSelectHandler = Null
		OnExpandHandler = Null
		OnCollapseHandler = Null
		Super.Free
	End Method
	
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, x:Int, y:Int, w:Int, h:Int)
		If _freed
			Return
		End If
		gad = CreateTreeView(x, y, w, h, Init(parent, x, y, w, h), 0)
		root = New ITreeNode
		root._parent = Self
		root.gad = TreeViewRoot(gad)
		OnInit Null
	End Method
	
Rem
bbdoc: AddNode method
returns: ITreeNode
End Rem
	Method AddNode:ITreeNode(text:String, icon:Int = - 1)
		If _freed
			Return Null
		End If
		Local node:ITreeNode = New ITreeNode
		
		node.Create root, text, icon
		Return node
	End Method
	
Rem
bbdoc: OnMenu event handler method
End Rem
	Method OnMenu(evt:TEvent)
		If OnMenuHandler
			OnMenuHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnSelect event handler method
End Rem
	Method OnSelect(evt:TEvent)
		If OnSelectHandler
			OnSelectHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnExpand event handler method
End Rem
	Method OnExpand(evt:TEvent)
		If OnExpandHandler
			OnExpandHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: OnCollapse event handler method
End Rem
	Method OnCollapse(evt:TEvent)
		If OnCollapseHandler
			OnCollapseHandler Self, evt
		End If
	End Method
	
Rem
bbdoc: Clear method
End Rem
	Method Clear()
		If _freed
			Return
		End If
		For Local i:IGadget = EachIn root._children
			i.Free
		Next
	End Method
	
Rem
bbdoc: GetRoot method
returns: ITreeNode
End Rem
	Method GetRoot:ITreeNode()
		If _freed
			Return Null
		End If
		Return root
	End Method
	
Rem
bbdoc: GetSelected method
returns: ITreeNode
End Rem
	Method GetSelected:ITreeNode()
		If _freed
			Return Null
		End If
		Local sel:TGadget = gad.SelectedNode()
		
		If (sel = Null)
			Return Null
		End If
		Return root.FindByGad(sel)
	End Method
	
End Type

Rem
bbdoc: TreeNode gadget type
End Rem
Type ITreeNode Extends IGadget
Rem
bbdoc: Create method
End Rem
	Method Create(parent:IGadget, text:String, icon:Int = - 1)
		If _freed
			Return
		End If
		gad = AddTreeViewNode(text, Init(parent, 0, 0, 0, 0), icon)
		OnInit Null
	End Method
	
Rem
bbdoc: Clear method
End Rem
	Method Clear()
		If _freed
			Return
		End If
		For Local i:IGadget = EachIn _children
			i.Free
		Next
	End Method
	
Rem
bbdoc: AddNode method
returns: ITreeNode
End Rem
	Method AddNode:ITreeNode(text:String, icon:Int = - 1)
		If _freed
			Return Null
		End If
		Local node:ITreeNode = New ITreeNode
		
		node.Create Self, text, icon
		Return node
	End Method
	
Rem
bbdoc: SelectNode method
End Rem
	Method SelectNode()
		If _freed
			Return
		End If
		gad.Activate ACTIVATE_SELECT
	End Method
	
Rem
bbdoc: Expand method
End Rem
	Method Expand()
		If _freed
			Return
		End If
		gad.Activate ACTIVATE_EXPAND
	End Method
	
Rem
bbdoc: Collapse method
End Rem
	Method Collapse()
		If _freed
			Return
		End If
		gad.Activate ACTIVATE_COLLAPSE
	End Method
	
Rem
bbdoc: FindByGad method
returns: ITreeNode
End Rem
	Method FindByGad:ITreeNode(g:TGadget)
		If _freed
			Return Null
		End If
		If (gad = g)
			Return Self
		End If
		For Local i:ITreeNode = EachIn _children
			Local o:ITreeNode = i.FindByGad(g)
			
			If o
				Return o
			End If
		Next
		Return Null
	End Method
	
End Type

Private

Function _gadUpdate:Object(id:Int, obj:Object, ctx:Object) 
	Local gad:IGadget = IGadget(ctx)
	
	Local evt:TEvent = TEvent(obj)
	
	If (Not gad Or Not evt)
		Return obj
	End If
	Local m:IMenu = IMenu(gad)
	
	If (((evt.id = EVENT_MENUACTION) And (m = Null)) Or (gad.gad = Null))
		Return obj
	End If
	If ((evt.source <> gad.gad) And (m = Null))
		Return obj
	End If
	If gad._freed
		Return obj
	End If
	Select evt.id
	Case EVENT_MOUSEENTER
		gad.OnEnter evt
	Case EVENT_MOUSELEAVE
		gad.OnLeave evt
	Case EVENT_KEYDOWN
		gad.OnKeyDown evt
	Case EVENT_KEYUP
		gad.OnKeyUp evt
	Case EVENT_KEYCHAR
		gad.OnKeyChar evt
	Case EVENT_MOUSEMOVE
		gad.OnMouseMove evt
	Case EVENT_MOUSEWHEEL
		gad.OnMouseWheel evt
	Case EVENT_MOUSEDOWN
		gad.OnMouseDown evt
	Case EVENT_MENUACTION
		If (m.id = evt.data)
			m.OnAction evt
		End If
	Case EVENT_WINDOWMOVE
		If IWindow(gad)
			IWindow(gad).OnMove evt
		End If
	Case EVENT_WINDOWACTIVATE
		If IWindow(gad)
			IWindow(gad).OnFocus evt
		End If
	Case EVENT_WINDOWSIZE
		If IWindow(gad)
			IWindow(gad).OnResize evt
		End If
	Case EVENT_WINDOWACCEPT
		If IWindow(gad)
			IWindow(gad).OnDragDrop evt
		End If
	Case EVENT_WINDOWCLOSE
		If IWindow(gad)
			IWindow(gad).OnClose evt
		End If
	Case EVENT_GADGETOPEN
		If ITreeView(gad)
			ITreeView(gad).OnExpand evt
		End If
	Case EVENT_GADGETCLOSE
		If ITreeView(gad)
			ITreeView(gad).OnCollapse evt
		End If
	Case EVENT_GADGETSELECT
		If ITreeView(gad)
			ITreeView(gad).OnSelect evt
		End If
	Case EVENT_GADGETMENU
		Local txt:ITextBox = ITextBox(gad)
		
		Local tv:ITreeView = ITreeView(gad)
		
		If txt
			txt.OnMenu evt
		Else If tv
			tv.OnMenu evt
		End If
	Case EVENT_GADGETDONE
		If IHTMLView(gad)
			IHTMLView(gad).OnLoaded evt
		End If
	Case EVENT_GADGETACTION
		gad.OnAction evt
	Case EVENT_GADGETPAINT
		gad.OnPaint evt
	End Select
	Return obj
End Function


Demo:
SuperStrict

Framework MaxGUI.Interface

Import MaxGUI.Drivers


Global win:IWindow = New IWindow
win.Create Null , 300 , 200 , 300 , 130 , "MaxGUI Interface Demo", True, False, False
win.OnCloseHandler = close

'Radio buttons

Local r1:IRadioButton = New IRadioButton
r1.Create win , 10 , 10 , 80 , 25 , "Option 1" , 1

Local r2:IRadioButton = New IRadioButton
r2.Create win , 110 , 10 , 80 , 25 , "Option 2" , 1

Local r3:IRadioButton = New IRadioButton
r3.Create win , 210 , 10 , 80 , 25 , "Option 3" , 1

'Check buttons

Local c1:ICheckButton = New ICheckButton
c1.Create win , 10 , 50 , 80 , 25 , "Choice 1"

Local c2:ICheckButton = New ICheckButton
c2.Create win , 110 , 50 , 80 , 25 , "Choice 2"

Local c3:ICheckButton = New ICheckButton
c3.Create win , 210 , 50 , 80 , 25 , "Choice 3"

'Push buttons

Local p1:IButton = New IButton
p1.Create win , 10 , 90 , 80 , 25 , "Button 1"
p1.OnActionHandler = ButtonPush

Local p2:IButton = New IButton
p2.Create win , 110 , 90 , 80 , 25 , "Button 2"
p2.OnActionHandler = ButtonPush

Local p3:IButton = New IButton
p3.Create win , 210 , 90 , 80 , 25 , "Button 3"
p3.OnActionHandler = ButtonPush

win.Show()

While win
	PollSystem
Wend

Function ButtonPush(sender:IGadget , e:TEvent) 
	win.SetStatusText sender.GetText() 
End Function

Function Close(sender:IGadget , e:TEvent) 
	If sender = win Then win = Null
End Function


Nilium
(Posted 18 years ago)
Also: main code updated to include changes since the initial posting. Doesn't include any of Otus's changes, as there is no explanation of what logic he's changed and why.

Code Archives Forum