diff options
-rw-r--r-- | gfxmenu.mod/gfxmenu.bmx | 372 | ||||
-rw-r--r-- | simplegui.mod/simplegui.bmx | 3325 |
2 files changed, 1848 insertions, 1849 deletions
diff --git a/gfxmenu.mod/gfxmenu.bmx b/gfxmenu.mod/gfxmenu.bmx index bc51f9d..921ebc7 100644 --- a/gfxmenu.mod/gfxmenu.bmx +++ b/gfxmenu.mod/gfxmenu.bmx @@ -1,186 +1,186 @@ -Rem
-bbdoc: noddybox.gfxmenu
-EndRem
-Module noddybox.gfxmenu
-
-ModuleInfo "Framework: Simple Graphical Menu"
-ModuleInfo "Copyright: Public Domain"
-ModuleInfo "Author: Ian Cowburn"
-ModuleInfo "Version: $Revision$"
-
-' $Id$
-
-Strict
-Import brl.linkedlist
-Import brl.max2d
-
-Rem
-bbdoc: Allows a menu backdrop to be automatically processed. Derive a class from this to use.
-EndRem
-Type TGfxMenuBackdrop Abstract
- Rem
- bbdoc: Create a menu backdrop element.
- returns: The created elemnt.
- about: Notice that this is a method, rather than the usual function creator.
- EndRem
- Method Create:TGfxMenuBackdrop() Abstract
- Rem
- bbdoc: Called by the menu to update the backdrop.
- EndRem
- Method Update() Abstract
-End Type
-
-Rem
-bbdoc: Defines a graphical menu.
-EndRem
-Type TGfxMenu
- Field list:TList
- Field bdrop:TList
- Field mbdown:Int
- Field r:Int
- Field g:Int
- Field b:Int
- Field over_r:Int
- Field over_g:Int
- Field over_b:Int
- Field fade:Int
-
- Rem
- bbdoc: Create a menu.
- returns: The created menu.
- about: @backdrop is the backdrop to create (null for no backdrop). @num is the number of backdrop items to create.
- about: SetColor() is called with @r, @g and @b when the mouse is not over an item, overwise SetColor() is
- about: called with @over_r, @over_g and @over_b when the item is active. @fade is the amount colours will alter as the
- about: mouse hovers over buttons. Set this to 255 to make colour changes instant.
- EndRem
- Function Create:TGfxMenu(r:Int=164, g:Int=164, b:Int=164, over_r:Int=255, over_g:Int=255, over_b:Int=255, fade:Int=5, backdrop:TGfxMenuBackdrop=Null, num:Int=0)
- Local menu:TGfxMenu=New TGfxMenu
-
- menu.list=New TList
- menu.bdrop=New TList
- menu.mbdown=False
-
- menu.r=r
- menu.g=g
- menu.b=b
- menu.over_r=over_r
- menu.over_g=over_g
- menu.over_b=over_b
- menu.fade=fade
-
- If backdrop
- For Local f:Int=0 Until num
- menu.bdrop.AddLast(backdrop.Create())
- Next
- EndIf
-
- Return menu
- End Function
-
- Rem
- bbdoc: Adds a menu item.
- returns: The created menu.
- about: @x and @y are the position to draw the image at. If @x is -1 then the image is centred. @i is the image.
- about: @id is the value returned from @Render() for this menu item. Don't use -1 for this!
- EndRem
- Method Add(x:Int, y:Int, i:TImage, id:Int)
- list.AddLast(TGfxMenuOpt.Create(x,y,i,id,r,g,b))
- End Method
-
- Rem
- bbdoc: Renders and updates the menu.
- returns: The selected item, or -1 if nothing clicked.
- about: Set @hide to True to hide the menu (the backdrop is still updated). SetColor() may have changed when this routine exits.
- EndRem
- Method Render:Int(hide:Int)
- For Local p:TGfxMenuBackdrop=EachIn bdrop
- p.Update()
- Next
-
- If hide
- Return -1
- EndIf
-
- Local in:Int=-1
- Local mx:Int=MouseX()
- Local my:Int=MouseY()
- Local any:Int=False
-
- For Local opt:TGfxMenuOpt=EachIn list
- If opt.InBox(mx,my)
- opt.r=Towards(over_r,opt.r)
- opt.g=Towards(over_g,opt.g)
- opt.b=Towards(over_b,opt.b)
- SetColor(opt.r,opt.g,opt.b)
-
- If MouseDown(1)
- mbdown=True
- DrawImage(opt.i,opt.x,opt.y+2)
- any=True
- Else
- DrawImage(opt.i,opt.x,opt.y)
- If mbdown
- in=opt.id
- EndIf
- mbdown=False
- EndIf
- Else
- opt.r=Towards(r,opt.r)
- opt.g=Towards(g,opt.g)
- opt.b=Towards(b,opt.b)
- SetColor(opt.r,opt.g,opt.b)
- DrawImage(opt.i,opt.x,opt.y)
- EndIf
- Next
-
- If Not any
- mbdown=False
- EndIf
-
- Return in
- End Method
-
- Method Towards:Int(dest:Int, val:Int)
- If val<dest
- Return Min(dest,val+fade)
- ElseIf val>dest
- Return Max(dest,val-fade)
- EndIf
-
- Return val
- End Method
-End Type
-
-Private
-
-Type TGfxMenuOpt
- Field x:Int
- Field y:Int
- Field i:TImage
- Field id:Int
- Field r:Int
- Field g:Int
- Field b:Int
-
- Function Create:TGfxMenuOpt(x:Int, y:Int, i:TImage, id:Int, r:Int, g:Int, b:Int)
- Local o:TGfxMenuOpt=New TGfxMenuOpt
-
- If x=-1
- x=(GraphicsWidth()-ImageWidth(i))/2
- EndIf
-
- o.x=x
- o.y=y
- o.i=i
- o.id=id
- o.r=r
- o.g=g
- o.b=b
-
- Return o
- End Function
-
- Method InBox:Int(mx:Int, my:Int)
- Return mx>=x And my>=y And mx<=x+ImageWidth(i) And my<=y+ImageHeight(i)
- End Method
-End Type
+Rem +bbdoc: noddybox.gfxmenu +EndRem +Module noddybox.gfxmenu + +ModuleInfo "Framework: Simple Graphical Menu" +ModuleInfo "Copyright: Public Domain" +ModuleInfo "Author: Ian Cowburn" +ModuleInfo "Version: $Revision$" + +' $Id$ + +Strict +Import brl.linkedlist +Import brl.max2d + +Rem +bbdoc: Allows a menu backdrop to be automatically processed. Derive a class from this to use. +EndRem +Type TGfxMenuBackdrop Abstract + Rem + bbdoc: Create a menu backdrop element. + returns: The created elemnt. + about: Notice that this is a method, rather than the usual function creator. + EndRem + Method Create:TGfxMenuBackdrop() Abstract + Rem + bbdoc: Called by the menu to update the backdrop. + EndRem + Method Update() Abstract +End Type + +Rem +bbdoc: Defines a graphical menu. +EndRem +Type TGfxMenu + Field list:TList + Field bdrop:TList + Field mbdown:Int + Field r:Int + Field g:Int + Field b:Int + Field over_r:Int + Field over_g:Int + Field over_b:Int + Field fade:Int + + Rem + bbdoc: Create a menu. + returns: The created menu. + about: @backdrop is the backdrop to create (null for no backdrop). @num is the number of backdrop items to create. + SetColor() is called with @r, @g and @b when the mouse is not over an item, overwise SetColor() is + called with @over_r, @over_g and @over_b when the item is active. @fade is the amount colours will alter as the + mouse hovers over buttons. Set this to 255 to make colour changes instant. + EndRem + Function Create:TGfxMenu(r:Int=164, g:Int=164, b:Int=164, over_r:Int=255, over_g:Int=255, over_b:Int=255, fade:Int=5, backdrop:TGfxMenuBackdrop=Null, num:Int=0) + Local menu:TGfxMenu=New TGfxMenu + + menu.list=New TList + menu.bdrop=New TList + menu.mbdown=False + + menu.r=r + menu.g=g + menu.b=b + menu.over_r=over_r + menu.over_g=over_g + menu.over_b=over_b + menu.fade=fade + + If backdrop + For Local f:Int=0 Until num + menu.bdrop.AddLast(backdrop.Create()) + Next + EndIf + + Return menu + End Function + + Rem + bbdoc: Adds a menu item. + returns: The created menu. + about: @x and @y are the position to draw the image at. If @x is -1 then the image is centred. @i is the image. + @id is the value returned from @Render() for this menu item. Don't use -1 for this! + EndRem + Method Add(x:Int, y:Int, i:TImage, id:Int) + list.AddLast(TGfxMenuOpt.Create(x,y,i,id,r,g,b)) + End Method + + Rem + bbdoc: Renders and updates the menu. + returns: The selected item, or -1 if nothing clicked. + about: Set @hide to True to hide the menu (the backdrop is still updated). SetColor() may have changed when this routine exits. + EndRem + Method Render:Int(hide:Int) + For Local p:TGfxMenuBackdrop=EachIn bdrop + p.Update() + Next + + If hide + Return -1 + EndIf + + Local in:Int=-1 + Local mx:Int=MouseX() + Local my:Int=MouseY() + Local any:Int=False + + For Local opt:TGfxMenuOpt=EachIn list + If opt.InBox(mx,my) + opt.r=Towards(over_r,opt.r) + opt.g=Towards(over_g,opt.g) + opt.b=Towards(over_b,opt.b) + SetColor(opt.r,opt.g,opt.b) + + If MouseDown(1) + mbdown=True + DrawImage(opt.i,opt.x,opt.y+2) + any=True + Else + DrawImage(opt.i,opt.x,opt.y) + If mbdown + in=opt.id + EndIf + mbdown=False + EndIf + Else + opt.r=Towards(r,opt.r) + opt.g=Towards(g,opt.g) + opt.b=Towards(b,opt.b) + SetColor(opt.r,opt.g,opt.b) + DrawImage(opt.i,opt.x,opt.y) + EndIf + Next + + If Not any + mbdown=False + EndIf + + Return in + End Method + + Method Towards:Int(dest:Int, val:Int) + If val<dest + Return Min(dest,val+fade) + ElseIf val>dest + Return Max(dest,val-fade) + EndIf + + Return val + End Method +End Type + +Private + +Type TGfxMenuOpt + Field x:Int + Field y:Int + Field i:TImage + Field id:Int + Field r:Int + Field g:Int + Field b:Int + + Function Create:TGfxMenuOpt(x:Int, y:Int, i:TImage, id:Int, r:Int, g:Int, b:Int) + Local o:TGfxMenuOpt=New TGfxMenuOpt + + If x=-1 + x=(GraphicsWidth()-ImageWidth(i))/2 + EndIf + + o.x=x + o.y=y + o.i=i + o.id=id + o.r=r + o.g=g + o.b=b + + Return o + End Function + + Method InBox:Int(mx:Int, my:Int) + Return mx>=x And my>=y And mx<=x+ImageWidth(i) And my<=y+ImageHeight(i) + End Method +End Type diff --git a/simplegui.mod/simplegui.bmx b/simplegui.mod/simplegui.bmx index f49c8dc..1f2742a 100644 --- a/simplegui.mod/simplegui.bmx +++ b/simplegui.mod/simplegui.bmx @@ -1,1663 +1,1662 @@ -Rem
-bbdoc: noddybox.simplegui
-EndRem
-Module noddybox.simplegui
-
-ModuleInfo "Framework: (Very) Simple GUI"
-ModuleInfo "Copyright: Public Domain"
-ModuleInfo "Author: Ian Cowburn"
-ModuleInfo "Version: $Revision$"
-
-' $Id$
-
-Strict
-Import brl.max2d
-Import brl.filesystem
-Import brl.basic
-Import noddybox.bitmapfont
-
-Rem
-bbdoc: Defines the @TBitmapFont to be used by the GUI.
-EndRem
-Type TGUIFont
- Rem
- bbdoc: The font to use.
- EndRem
- Global font:TBitmapFont
-End Type
-
-Rem
-bbdoc: The base widget type.
-EndRem
-Type TWidget Abstract
-
- Rem
- bbdoc: This widget consumes click events
- EndRem
- Const HAS_CLICK:Int=1
- Rem
- bbdoc: This widget consumes drag events
- EndRem
- Const HAS_DRAG:Int=2
- Rem
- bbdoc: This widget consumes key events
- EndRem
- Const HAS_KEY:Int=4
-
- Rem
- bbdoc: If true the widget is displayed.
- EndRem
- Field displayed:Int
- Rem
- bbdoc: If true the widget can be interacted with.
- EndRem
- Field enabled:Int
- Rem
- bbdoc: The text displayed in the widget.
- EndRem
- Field text:String
- Rem
- bbdoc: The X co-ordinate of the widget.
- EndRem
- Field x:Int
- Rem
- bbdoc: The Y co-ordinate of the widget.
- EndRem
- Field y:Int
- Rem
- bbdoc: The width of the widget.
- EndRem
- Field w:Int
- Rem
- bbdoc: The height of the widget.
- EndRem
- Field h:Int
- Rem
- bbdoc: Callback to call when clicked.
- EndRem
- Field callback(w:TWidget)
- Rem
- bbdoc: True if the mouse is over this widget, False otherwise.
- EndRem
- Field mouse_over:Int
- Rem
- bbdoc: The @TGUIHandler that owns this widget.
- EndRem
- Field owner:TGUIHandler
- Rem
- bbdoc: The mask of consumed events, zero otherwise.
- EndRem
- Field consumes:Int
-
- Rem
- bbdoc: Override this accept keypresses
- EndRem
- Method HandleKey(k:Int)
- End Method
-
- Rem
- bbdoc: Override this for when the mouse enters. Call this parent version to handle @mouse_over too.
- EndRem
- Method MouseEnter()
- If displayed And enabled
- mouse_over=True
- EndIf
- End Method
-
- Rem
- bbdoc: Override this for when the mouse leaves. Call this parent version to handle @mouse_over too.
- EndRem
- Method MouseLeave()
- mouse_over=False
- End Method
-
- Rem
- bbdoc: Override to handle a mouse button press.
- EndRem
- Method HandleClick()
- End Method
-
- Rem
- bbdoc: Handles mouse dragging.
- about: @mx and @my are the changes in mouse co-ordinates since the last drag.
- EndRem
- Method HandleDrag(mx:Int, my:Int)
- End Method
-
- Rem
- bbdoc: Must be provided by a widget to draw itself.
- EndRem
- Method Draw() Abstract
-
- Rem
- bbdoc: Helper to draw a wireframe rectangle.
- EndRem
- Function DrawBox(x:Int, y:Int, w:Int, h:Int)
- DrawLine(x,y,x+w-1,y)
- DrawLine(x+w-1,y,x+w-1,y+h-1)
- DrawLine(x+w-1,y+h-1,x,y+h-1)
- DrawLine(x,y+h-1,x,y)
- End Function
-
- Rem
- bbdoc: Helper to draw a 3D rectangle.
- EndRem
- Function Draw3DBox(x:Int, y:Int, w:Int, h:Int, invert:Int, size:Int=2)
- Local f:Int
-
- SetColor(200,200,200)
- DrawRect(x,y,w,h)
-
- If invert
- SetColor(170,170,170)
- Else
- SetColor(230,230,230)
- EndIf
-
- For f=0 Until size
- DrawLine(x+f,y+f,x+w-1-f,y+f)
- DrawLine(x+w-1-f,y+f,x+w-1-f,y+h-1-f)
- Next
-
- If invert
- SetColor(230,230,230)
- Else
- SetColor(170,170,170)
- EndIf
-
- For f=0 Until size
- DrawLine(x+w-1-f,y+h-1-f,x+f,y+h-1-f)
- DrawLine(x+f,y+h-1-f,x+f,y+f)
- Next
- End Function
-
-End Type
-
-Rem
-bbdoc: The panel widget (simply displays itself as a white bordered black box)
-EndRem
-Type TPanel Extends TWidget
-
- Rem
- bbdoc: Create a TPanel widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x, @y, @x and @h are its position and size. If @x or @y is -1 they are centered.
- EndRem
- Function Create:TPanel(gui:TGUIHandler,x:Int, y:Int, w:Int, h:Int)
- Local o:TPanel=New TPanel
- o.displayed=True
- o.enabled=True
- o.consumes=0
-
- If x=-1
- x=(GraphicsWidth()-w)/2
- EndIf
-
- If y=-1
- y=(GraphicsHeight()-h)/2
- EndIf
-
- o.x=x
- o.y=y
- o.w=w
- o.h=h
- gui.Register(o)
- Return o
- End Function
-
- Method Draw()
- SetColor(0,0,0)
- DrawRect(x,y,w,h)
- SetColor(255,255,255)
- DrawBox(x,y,w,h)
- End Method
-
-End Type
-
-Rem
-bbdoc: The label widget (simply displays the supplied string)
-EndRem
-Type TLabel Extends TWidget
- Rem
- bbdoc: Create a TLabel widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position and @text is the text to display in the label.
- EndRem
- Function Create:TLabel(gui:TGUIHandler,x:Int, y:Int, text:String)
- Local o:TLabel=New TLabel
- o.displayed=True
- o.enabled=True
- o.consumes=0
- o.x=x
- o.y=y
- o.w=TGUIFont.font.TextWidth(text)+2
- o.h=TGUIFont.font.MaxHeight()+1
- o.text=text
- gui.Register(o)
- Return o
- End Function
-
- Method Draw()
- TGUIFont.font.Draw(text,x+1,y+1)
- End Method
-
-End Type
-
-Rem
-bbdoc: The text entry widget
-EndRem
-Type TText Extends TWidget
- Field maxlen:Int
- Field mode:Int
-
- Rem
- bbdoc: The text box handles any text
- EndRem
- Const NORMAL:Int=0
-
- Rem
- bbdoc: The text box handles a number
- EndRem
- Const NUMERIC:Int=1
-
- Rem
- bbdoc: The text box handles only integer numbers
- EndRem
- Const INTEGER:Int=2
-
- Rem
- bbdoc: The text box handles only positive numbers
- EndRem
- Const POSITIVE:Int=4
-
- Rem
- bbdoc: The text box handles a basic set of filename characters (alphanumerics, periods, spaces and underscores)
- EndRem
- Const FILENAME:Int=8
-
- Rem
- bbdoc: The text box is readonly
- EndRem
- Const READONLY:Int=256
-
-
- Rem
- bbdoc: Create a TText widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position and @text is the initial text in the widget.
- about: @maxlen is the maximum number of characters allowed. @mode defines the valid characters that can be entered.
- about: @callback is called when RETURN is pressed in the text field.
- EndRem
- Function Create:TText(gui:TGUIHandler,x:Int, y:Int, text:String, maxlen:Int, mode:Int=0, callback(w:TWidget)=Null)
- Local o:TText=New TText
- o.displayed=True
- o.enabled=True
- o.consumes=HAS_CLICK|HAS_KEY
- o.x=x
- o.y=y
- o.maxlen=maxlen
- o.w=TGUIFont.font.MaxWidth()*(maxlen+1)+2
- o.h=TGUIFont.font.MaxHeight()+2
- o.text=text
- o.callback=callback
- o.mode=mode
- gui.Register(o)
- Return o
- End Function
-
- Rem
- bbdoc: Set the text to a floating point value.
- about: @v is the floating point value (a double to cover both types). This value will be placed in the text
- about: field with trailing zeros (and trailing dot if an integer) removed.
- EndRem
- Method SetFloat(v:Double)
- Local s:String=v
-
- If s.Find(".")<>-1
- While s.length>1 And s[s.length-1]=Asc("0")
- s=s[..s.length-1]
- Wend
-
- While s.length>1 And s[s.length-1]=Asc(".")
- s=s[..s.length-1]
- Wend
- EndIf
-
- text=s
- End Method
-
- Method HandleClick()
- If Not(mode & READONLY)
- owner.SetFocus(Self)
- EndIf
- End Method
-
- Method HandleKey(k:Int)
- If (mode & READONLY)
- Return
- EndIf
-
- If k=27
- text=""
- Else If k=8
- If text.length>0
- text=text[0..text.length-1]
- EndIf
- Else If k=13
- If callback<>Null
- callback(Self)
- owner.SetFocus(Null)
- EndIf
- Else If k>31 And k<127 And text.length<maxlen
- If (mode & NUMERIC)
- If k=Asc("-") And (Not (mode & POSITIVE)) And text.length=0
- text:+Chr(k)
- EndIf
-
- If k>=Asc("0") And k<=Asc("9")
- text:+Chr(k)
- EndIf
-
- If k=Asc(".") And (Not (mode & INTEGER)) And text.Find(".")=-1
- text:+Chr(k)
- EndIf
- Else
- If (mode & FILENAME)
- If (k>=Asc("a") And k<=Asc("z")) Or (k>=Asc("A") And k<=Asc("Z")) Or (k>=Asc("0") And k<=Asc("9")) Or k=Asc(" ") Or k=Asc(".") Or k=Asc("_")
- text:+Chr(k)
- EndIf
- Else
- text:+Chr(k)
- EndIf
- EndIf
- EndIf
- End Method
-
- Method Draw()
- Local s:String=text
-
- If owner.GetFocus()=Self And Not (mode & READONLY)
- SetColor(128,128,128)
- s:+"_"
- Else
- SetColor(64,64,64)
- EndIf
-
- DrawRect(x,y,w,h)
-
- TGUIFont.font.Draw(s,x+1,y+1)
- End Method
-End Type
-
-Rem
-bbdoc: The checkbox widget
-EndRem
-Type TCheckbox Extends TWidget
-
- Rem
- bbdoc: True if the box is checked, False otherwise.
- EndRem
- Field checked:Int
-
- Rem
- bbdoc: Create a TCheckox widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position and @text is the text to display by the checkbox.
- about: @callback is called when the checkbox is toggled.
- EndRem
- Function Create:TCheckbox(gui:TGUIHandler, x:Int, y:Int, text:String, callback(w:TWidget)=Null)
- Local o:TCheckbox=New TCheckbox
- o.displayed=True
- o.enabled=True
- o.consumes=HAS_CLICK
- o.x=x
- o.y=y
- o.w=TGUIFont.font.TextWidth(" "+text)+4+TGUIFont.font.MaxHeight()
- o.h=TGUIFont.font.MaxHeight()+2
- o.text=text
- o.callback=callback
- gui.Register(o)
- Return o
- End Function
-
- Method HandleClick()
- checked=Not checked
-
- If callback<>Null
- callback(Self)
- EndIf
- End Method
-
- Method Draw()
- If (mouse_over)
- SetColor(255,255,255)
- Else
- SetColor(200,200,200)
- EndIf
-
- DrawBox(x,y,TGUIFont.font.MaxHeight(),TGUIFont.font.MaxHeight())
-
- If checked
- SetColor(255,100,100)
- DrawRect(x+1,y+1,TGUIFont.font.MaxHeight()-2,TGUIFont.font.MaxHeight()-2)
- EndIf
-
- TGUIFont.font.Draw(" "+text,x+2+TGUIFont.font.MaxHeight(),y+1)
- End Method
-End Type
-
-Rem
-bbdoc: The button widget
-EndRem
-Type TButton Extends TWidget
-
- Field ox:Int
- Field oy:Int
-
- Rem
- bbdoc: Create a TButton widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x, @y, @w and @h are its position and size, and @text is the text to display in the button.
- about: @callback is called when the button is pressed.
- EndRem
- Function Create:TButton(gui:TGUIHandler, x:Int, y:Int, w:Int, h:Int, text:String, callback(w:TWidget))
- Local o:TButton=New TButton
- o.displayed=True
- o.enabled=True
- o.consumes=HAS_CLICK
- o.x=x
- o.y=y
- o.w=w
- o.h=h
- o.text=text
- o.ox=x+w/2-TGUIFont.font.TextWidth(text)/2
- o.oy=y+h/2-TGUIFont.font.TextHeight(text)/2
- o.callback=callback
- gui.Register(o)
- Return o
- End Function
-
- Method HandleClick()
- If callback<>Null
- callback(Self)
- EndIf
- End Method
-
- Method Draw()
- If (mouse_over)
- SetColor(255,255,255)
- DrawBox(x,y,w,h)
- EndIf
-
- Draw3DBox(x+1,y+1,w-2,h-2,False,2)
-
- TGUIFont.font.Draw(text,ox,oy)
- End Method
-End Type
-
-Rem
-bbdoc: A drop down list type widget
-EndRem
-Type TButtonList Extends TWidget
-
- Field options:String[]
-
- Rem
- bbdoc: The selected item.
- EndRem
- Field selected:Int
-
- Rem
- bbdoc: Create a TButtonList widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position. @options are the options for the list and
- about: @selected is the currently selected item. @callback is called when the selection changes.
- EndRem
- Function Create:TButtonList(gui:TGUIHandler, x:Int, y:Int, options:String[], selected:Int, callback(w:TWidget))
- Local o:TButtonList=New TButtonList
- Local maxw:Int=0
- o.displayed=True
- o.enabled=True
- o.consumes=HAS_CLICK
- o.x=x
- o.y=y
- o.options=options
- o.selected=selected
- o.text=options[selected]
-
- For Local s:String=EachIn options
- maxw=Max(maxw,TGUIFont.font.TextWidth(s))
- Next
-
- o.w=maxw+TGUIFont.font.MaxHeight()+4
- o.h=TGUIFont.font.MaxHeight()+2
- o.callback=callback
- gui.Register(o)
- Return o
- End Function
-
- Method HandleClick()
- Local sel:Int=GUIMenu("Select value",options,x,y)
-
- If sel<>-1
- selected=sel
- text=options[selected]
- If callback<>Null
- callback(Self)
- EndIf
- EndIf
- End Method
-
- Method Draw()
- If (mouse_over)
- SetColor(128,128,128)
- Else
- SetColor(64,64,64)
- EndIf
-
- DrawRect(x,y,w,h)
- Draw3DBox(x+2,y+2,h-4,h-4,False,1)
-
- TGUIFont.font.Draw(text,x+TGUIFont.font.MaxHeight()+3,y+1)
- End Method
-End Type
-
-Rem
-bbdoc: Optional type to use for TTextList
-about: If the objects stored as TTextList options are derived from this type then tabular lists can be created.
-EndRem
-Type TTextListItem Abstract
- Rem
- bbdoc: The number of columns.
- returns: The number of columns
- EndRem
- Method Columns:Int() Abstract
-
- Rem
- bbdoc: A column offset.
- returns: The column offset for column @i (numbered from zero).
- EndRem
- Method ColumnOffset:Int(i:Int) Abstract
-
- Rem
- bbdoc: Column data.
- returns: The column data for column @i (numbered from zero).
- EndRem
- Method ColumnData:String(i:Int) Abstract
-End Type
-
-Rem
-bbdoc: A widget that displays text items as a list.
-EndRem
-Type TTextList Extends TWidget
-
- Field options:Object[]
- Field selected:Int
- Field num:Int
- Field top:Int
- Field rows:Int
-
- Rem
- bbdoc: Create a TTextList widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x, @y, and @w are its position and width.
- about: @rows are the number of items to display at a time.
- about: @callback is called when the selection changes.
- EndRem
- Function Create:TTextList(gui:TGUIHandler, x:Int, y:Int, w:Int, rows:Int, callback(w:TWidget)=Null)
- Local o:TTextList=New TTextList
- Local maxw:Int=0
- o.displayed=True
- o.enabled=True
- o.consumes=HAS_CLICK
- o.x=x
- o.y=y
- o.options=Null
- o.selected=-1
- o.num=0
- o.top=0
- o.rows=rows
-
- o.w=w
- o.h=TGUIFont.font.MaxHeight()*rows
- o.callback=callback
- gui.Register(o)
- Return o
- End Function
-
- Rem
- bbdoc: Sets the options to display in the list.
- about: @opts is an array of objects. <i>Note</i>: If the objects passed are derived from TTextListItem then tabular output is generated.
- about: If they are not derived, ToString() is called on the objects to display them, so you are not restricted to the type of object that
- about: can be passed.
- EndRem
- Method SetOptions(opts:Object[])
- options=opts
- num=opts.length
- selected=-1
- top=0
- End Method
-
- Rem
- bbdoc: Gets the selected item's index.
- returns: The selected item's index, or -1 if nothing is selected.
- EndRem
- Method GetSelectedIndex:Int()
- Return selected
- End Method
-
- Rem
- bbdoc: Gets the selected item.
- returns: The selected item, or null if nothing is selected.
- EndRem
- Method GetSelectedItem:Object()
- If options<>Null And selected<>-1
- Return options[selected]
- Else
- Return Null
- EndIf
- End Method
-
- Rem
- bbdoc: Set the top row.
- about: @i is the index of the item to display in the first row of the widget.
- EndRem
- Method SetTopRow(i:Int)
- If options<>Null And i<num
- top=i
- EndIf
- End Method
-
- Rem
- bbdoc: Get the top row.
- returns: The index of the item displayed in the first row of the widget. -1 if no options are set.
- EndRem
- Method GetTopRow:Int()
- If options<>Null
- Return top
- Else
- Return -1
- EndIf
- End Method
-
- Rem
- bbdoc: Ensure an item is visible.
- about: @i is the index of the item that is to be made visible.
- EndRem
- Method EnsureVisible(i:Int)
- If options<>Null And i<num
- If i<top
- top=i
- ElseIf i>=top+rows
- top=Max(0,i-rows+1)
- EndIf
- EndIf
- End Method
-
- Method HandleClick()
- If options<>Null
- Local sel:Int=top+(MouseY()-y)/TGUIFont.font.MaxHeight()
-
- If sel<num
- selected=sel
- If callback<>Null
- callback(Self)
- EndIf
- EndIf
- EndIf
- End Method
-
- Method Draw()
- SetColor(64,64,64)
- DrawRect(x,y,w,h)
-
- If options<>Null
- Local vx:Int
- Local vy:Int
- Local vw:Int
- Local vh:Int
-
- GetViewport(vx,vy,vw,vh)
-
- Local ty:Int=y
- For Local f:Int=top Until top+rows
- SetViewport(x,ty,w,TGUIFont.font.MaxHeight())
-
- If f=selected
- If mouse_over And MouseY()>=ty And MouseY()<ty+TGUIFont.font.MaxHeight()
- SetColor(200,128,128)
- Else
- SetColor(128,128,128)
- EndIf
- DrawRect(x,ty,w,TGUIFont.font.MaxHeight())
- Else
- If mouse_over And MouseY()>=ty And MouseY()<ty+TGUIFont.font.MaxHeight() And f<num
- SetColor(128,0,0)
- DrawRect(x,ty,w,TGUIFont.font.MaxHeight())
- EndIf
- EndIf
-
- If f<num
- Local li:TTextListItem=TTextListItem(options[f])
-
- If li<>Null
- For Local f:Int=0 Until li.Columns()
- TGUIFont.font.Draw(li.ColumnData(f),x+li.ColumnOffset(f),ty)
- Next
- Else
- TGUIFont.font.Draw(options[f].ToString(),x,ty)
- EndIf
- EndIf
-
- ty:+TGUIFont.font.MaxHeight()
- Next
-
- SetViewport(vx,vy,vw,vh)
- EndIf
- End Method
-End Type
-
-Rem
-bbdoc: A number up/down widget for doubles
-EndRem
-Type TNumberDouble Extends TWidget
-
- Rem
- bbdoc: The value
- EndRem
- Field value:Double
-
- Rem
- bbdoc: The increment/decrement
- EndRem
- Field change:Double
-
- Rem
- bbdoc: The maximum value
- EndRem
- Field maxval:Double
-
- Rem
- bbdoc: The minimum value
- EndRem
- Field minval:Double
-
- Rem
- bbdoc: Create a TNumber widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position.
- about: @callback is called when the value changes.
- EndRem
- Function Create:TNumberDouble(gui:TGUIHandler, x:Int, y:Int, callback(w:TWidget)=Null)
- Local o:TNumberDouble=New TNumberDouble
- o.displayed=True
- o.enabled=True
- o.consumes=HAS_CLICK
- o.value=0
- o.minval=0
- o.maxval=100
- o.change=10
- o.x=x
- o.y=y
- o.w=TGUIFont.font.MaxHeight()*2+8
- o.h=TGUIFont.font.MaxHeight()+2
- o.callback=callback
- gui.Register(o)
- Return o
- End Function
-
- Method HandleClick()
- Local old:Double=value
-
- If MouseX()<x+w/2
- value=Min(value+change,maxval)
- Else
- value=Max(value-change,minval)
- EndIf
-
- If value<>old And callback<>Null
- callback(Self)
- EndIf
- End Method
-
- Method Draw()
- If mouse_over
- If MouseX()<x+w/2
- SetColor(128,128,128)
- DrawRect(x,y,w/2,h)
- SetColor(64,64,64)
- DrawRect(x+w/2,y,w/2,h)
- Else
- SetColor(64,64,64)
- DrawRect(x,y,w/2,h)
- SetColor(128,128,128)
- DrawRect(x+w/2,y,w/2,h)
- EndIf
- Else
- SetColor(64,64,64)
- DrawRect(x,y,w,h)
- EndIf
-
- Draw3DBox(x+2,y+2,h-4,h-4,False,1)
- Draw3DBox(x+w-h,y+2,h-4,h-4,False,1)
-
- TGUIFont.font.Draw(value,x+w+2,y+1)
- End Method
-End Type
-
-Rem
-bbdoc: A number up/down widget for ints
-EndRem
-Type TNumberInt Extends TWidget
-
- Rem
- bbdoc: The value
- EndRem
- Field value:Int
-
- Rem
- bbdoc: The increment/decrement
- EndRem
- Field change:Int
-
- Rem
- bbdoc: The maximum value
- EndRem
- Field maxval:Int
-
- Rem
- bbdoc: The minimum value
- EndRem
- Field minval:Int
-
- Rem
- bbdoc: Create a TNumber widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position.
- about: @callback is called when the value changes.
- EndRem
- Function Create:TNumberInt(gui:TGUIHandler, x:Int, y:Int, callback(w:TWidget)=Null)
- Local o:TNumberInt=New TNumberInt
- o.displayed=True
- o.enabled=True
- o.consumes=HAS_CLICK
- o.value=0
- o.minval=0
- o.maxval=100
- o.change=10
- o.x=x
- o.y=y
- o.w=TGUIFont.font.MaxHeight()*2+8
- o.h=TGUIFont.font.MaxHeight()+2
- o.callback=callback
- gui.Register(o)
- Return o
- End Function
-
- Method HandleClick()
- Local old:Int=value
-
- If MouseX()<x+w/2
- value=Min(value+change,maxval)
- Else
- value=Max(value-change,minval)
- EndIf
-
- If value<>old And callback<>Null
- callback(Self)
- EndIf
- End Method
-
- Method Draw()
- If mouse_over
- If MouseX()<x+w/2
- SetColor(128,128,128)
- DrawRect(x,y,w/2,h)
- SetColor(64,64,64)
- DrawRect(x+w/2,y,w/2,h)
- Else
- SetColor(64,64,64)
- DrawRect(x,y,w/2,h)
- SetColor(128,128,128)
- DrawRect(x+w/2,y,w/2,h)
- EndIf
- Else
- SetColor(64,64,64)
- DrawRect(x,y,w,h)
- EndIf
-
- Draw3DBox(x+2,y+2,h-4,h-4,False,1)
- Draw3DBox(x+w-h,y+2,h-4,h-4,False,1)
-
- TGUIFont.font.Draw(value,x+w+2,y+1)
- End Method
-End Type
-
-Rem
-bbdoc: A scrollbar widget
-EndRem
-Type TScrollbar Extends TWidget
-
- Field horiz:Int
- Field bc:Int
- Field page:Double
- Field maxval:Double
- Field minval:Double
- Field stepsize:Double
- Field blocksize:Int
-
- Rem
- bbdoc: Create a TVerticalScrollbar widget.
- returns: The created widget.
- about: @gui is the @TGUIHandler object managing this wiget. @x, @y, @w and @h are its position and size.
- about: If @w is greater than height then an horizontal scrollbar is created, otherwise its vertical. @callback is called when the scrollbar moves.
- EndRem
- Function Create:TScrollbar(gui:TGUIHandler, x:Int, y:Int, w:Int, h:Int, callback(w:TWidget)=Null)
- Local o:TScrollbar=New TScrollbar
- o.displayed=True
- o.enabled=True
- o.consumes=HAS_CLICK|HAS_DRAG
- o.x=x
- o.y=y
- o.w=w
- o.h=h
- o.horiz=(w>h)
- o.SetBar(0,100,10)
- o.callback=callback
- gui.Register(o)
- Return o
- End Function
-
- Rem
- bbdoc: Set parameters for scroll bar
- about: @min_val and @max_val are the values at the top and bottom of the scroll bar. @page_size is the numbers between the two that
- about: is covered by the block in the scrollbar. <i>Note</i>: The maximum value of @value is @max_val minus @page_size.
- EndRem
- Method SetBar(min_val:Double, max_val:Double, page_size:Double)
- minval=min_val
- maxval=max_val
- page=page_size
-
- If horiz
- stepsize=(maxval-minval)/w
- blocksize=Min(w,Max(1,page/stepsize))
- bc=x
- Else
- stepsize=(maxval-minval)/h
- blocksize=Min(h,Max(1,page/stepsize))
- bc=y
- EndIf
- End Method
-
- Rem
- bbdoc: Get the current value of the scrollbar.
- returns: The current position of the scrollbar inbetween the minimum and maximum values.
- EndRem
- Method GetValue:Double()
- If horiz
- Return minval+(bc-x)*stepsize
- Else
- Return minval+(bc-y)*stepsize
- EndIf
- End Method
-
- Rem
- bbdoc: Sets the current value of the scrollbar.
- EndRem
- Method SetValue(val:Double)
- If horiz
- bc=Max(x,Min(x+w-blocksize,x+(val-minval)/stepsize))
- Else
- bc=Max(y,Min(y+h-blocksize,y+(val-minval)/stepsize))
- EndIf
- End Method
-
- Method HandleClick()
- Local old:Double=GetValue()
-
- If horiz
- bc=Max(x,Min(x+w-blocksize,MouseX()))
- Else
- bc=Max(y,Min(y+h-blocksize,MouseY()))
- EndIf
-
- If GetValue()<>old And callback<>Null
- callback(Self)
- EndIf
- End Method
-
- Method HandleDrag(mx:Int, my:Int)
- Local old:Double=GetValue()
-
- If horiz
- bc=Max(x,Min(x+w-blocksize,bc+mx))
- Else
- bc=Max(y,Min(y+h-blocksize,bc+my))
- EndIf
-
- If GetValue()<>old And callback<>Null
- callback(Self)
- EndIf
- End Method
-
- Method Draw()
- SetColor(64,64,64)
- DrawRect(x,y,w,h)
- If horiz
- Draw3DBox(bc,y,blocksize,h,False,1)
- Else
- Draw3DBox(x,bc,w,blocksize,False,1)
- EndIf
- End Method
-End Type
-
-Rem
-bbdoc: Handles the GUI.
-EndRem
-Type TGUIHandler
-
- ' These are private
- '
- Field m_widgets:TList
- Field m_focus:TWidget
- Field m_over:TWidget
- Field m_clicked:TWidget
- Field m_dragging:Int
- Field m_dragx:Int
- Field m_dragy:Int
- Field m_dragobj:TWidget
-
- Rem
- bbdoc: Create a GUI Handler.
- returns: The GUI Hanbler.
- EndRem
- Function Create:TGUIHandler()
- Local o:TGUIHandler
-
- o=New TGUIHandler
-
- o.m_widgets=CreateList()
- o.m_focus=Null
- o.m_over=Null
- o.m_clicked=Null
- o.m_dragging=False
- o.m_dragx=0
- o.m_dragy=0
- o.m_dragobj=Null
-
- Return o
- End Function
-
- Rem
- bbdoc: Register a widget.
- about: Widgets in the library call this themselves when creating.
- EndRem
- Method Register(w:TWidget)
- m_widgets.AddLast(w)
- w.owner=Self
- End Method
-
- Rem
- bbdoc: Remove all widgets.
- EndRem
- Method Clear()
- m_widgets.Clear()
- End Method
-
- Rem
- bbdoc: Sets the enable state of all widgets.
- about: If @state is true then all widgets are enabled, otherwise all widgets are disabled.
- EndRem
- Method SetEnable(state:Int)
- For Local w:TWidget=EachIn m_widgets
- w.enabled=state
- Next
- End Method
-
- Rem
- bbdoc: Sets the displayed state of all widgets.
- about: If @state is true then all widgets are displayed, otherwise all widgets are hidden.
- EndRem
- Method SetDisplay(state:Int)
- For Local w:TWidget=EachIn m_widgets
- w.displayed=state
- Next
- End Method
-
- Rem
- bbdoc: Sets the keyboard focus to the supplied widget. Pass null for no focus.
- EndRem
- Method SetFocus(w:TWidget)
- m_focus=w
- End Method
-
- Rem
- bbdoc: Gets the keyboard focus.
- returns: The currently focused TWidget, or null for no focus.
- EndRem
- Method GetFocus:TWidget()
- Return m_focus
- End Method
-
- Rem
- bbdoc: Gets the last clicked widget.
- returns: The last clicked TWidget. Null is returned if this is called again before another widget is clicked.
- EndRem
- Method Clicked:TWidget()
- Local last:TWidget=m_clicked
- m_clicked=Null
- Return last
- End Method
-
- Rem
- bbdoc: Whether a widget is dragging
- returns: True if a widget is consuming a mouse drag.
- EndRem
- Method IsDragging:Int()
- Return m_dragging
- End Method
-
- Rem
- bbdoc: Perform the event loop and pass any necessary events.
- about: KeyHit(KEY_MOUSELEFT) and GetChar() are used to consume events for the interface.
- EndRem
- Method EventLoop()
- Local x:Int=MouseX()
- Local y:Int=MouseY()
- Local b:Int=MouseHit(1)>0
- Local drag:Int=MouseDown(1)
-
- Local w:TWidget=LocateWidget(x,y)
-
- For Local wid:TWidget=EachIn m_widgets
- If wid.displayed
- If wid.enabled
- wid.Draw()
- Else
- SetAlpha(0.3)
- wid.Draw()
- SetAlpha(1)
- EndIf
- EndIf
- Next
-
- If w<>m_over
- If m_over<>Null
- m_over.MouseLeave()
- EndIf
- m_over=w
- If m_over<>Null
- m_over.MouseEnter()
- EndIf
- EndIf
-
- If w<>Null And w.enabled And w.consumes&TWidget.HAS_CLICK=TWidget.HAS_CLICK And b And Not m_dragging
- w.HandleClick()
- m_clicked=w
- EndIf
-
- Local k:Int=GetChar()
-
- If k<>0 And m_focus<>Null And m_focus.enabled And m_focus.consumes&TWidget.HAS_KEY=TWidget.HAS_KEY
- m_focus.HandleKey(k)
- EndIf
-
- If drag
- If m_dragging
- m_dragobj.HandleDrag(MouseX()-m_dragx,MouseY()-m_dragy)
- m_dragx=MouseX()
- m_dragy=MouseY()
- Else
- If w<>Null And w.consumes&TWidget.HAS_DRAG=TWidget.HAS_DRAG
- m_dragging=True
- m_dragx=MouseX()
- m_dragy=MouseY()
- m_dragobj=w
- EndIf
- EndIf
- Else
- m_dragging=False
- m_dragobj=Null
- EndIf
- End Method
-
- ' Private method
- '
- Method LocateWidget:TWidget(x:Int,y:Int)
- For Local w:TWidget=EachIn m_widgets
- If x>=w.x And y>=w.y And x<w.x+w.w And y<w.y+w.h And w.consumes
- Return w
- EndIf
- Next
- Return Null
- End Method
-End Type
-
-
-Rem
-bbdoc: Displays a notification alert with the supplied string.
-about: The string @s can be split into multiple lines using the '|' character. If @i is not null then this image is drawn as a mouse cursor.
-EndRem
-Function GUINotify(s:String, i:TImage=Null)
- Local back:TImage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,0)
- GrabImage(back,0,0)
-
- Local txt:TSplitText=TSplitText.Create(s)
-
- Local w:Int=Max(txt.width+10,GraphicsWidth()/4)
- Local h:Int=txt.Height+TGUIFont.font.MaxHeight()*4
- Local x:Int=GraphicsWidth()/2-w/2
- Local y=GraphicsHeight()/2-h/2
- Local by=y+h-TGUIFont.font.MaxHeight()*2.5
-
- Local gui:TGUIHandler=TGUIHandler.Create()
-
- Local ty:Int=y+5
-
- For Local t:String=EachIn txt.lines
- Local label:TLabel=TLabel.Create(gui,x+5,ty,t)
- ty:+TGUIFont.font.TextHeight(t)
- Next
-
- Local button:TButton=TButton.Create(gui,x+5,by,w-10,TGUIFont.font.MaxHeight()*2,"OK",Null)
-
- Local click:TWidget=Null
-
- While click<>button
- Cls
- SetAlpha(0.5)
- DrawImage(back,0,0)
- SetAlpha(1)
- TWidget.Draw3DBox(x,y,w,h,False,2)
- gui.EventLoop()
- click=gui.Clicked()
-
- If i<>Null
- SetColor(255,255,255)
- DrawImage(i,MouseX(),MouseY())
- EndIf
-
- Flip
- Wend
-End Function
-
-Rem
-bbdoc: Displays a yes/no alert with the supplied string.
-returns: True if Yes selected, otherwise False.
-about: The string @s can be split into multiple lines using the '|' character. If @i is not null then this image is drawn as a mouse cursor.
-EndRem
-Function GUIYesNo:Int(s:String, i:TImage=Null)
- Local back:TImage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,0)
- GrabImage(back,0,0)
-
- Local txt:TSplitText=TSplitText.Create(s)
-
- Local w:Int=Max(txt.width+10,GraphicsWidth()/4)
- Local h:Int=txt.Height+TGUIFont.font.MaxHeight()*4
- Local x:Int=GraphicsWidth()/2-w/2
- Local y=GraphicsHeight()/2-h/2
- Local by=y+h-TGUIFont.font.MaxHeight()*2.5
-
- Local gui:TGUIHandler=TGUIHandler.Create()
-
- Local ty:Int=y+5
-
- For Local t:String=EachIn txt.lines
- Local label:TLabel=TLabel.Create(gui,x+5,ty,t)
- ty:+TGUIFont.font.TextHeight(t)
- Next
-
- Local yes:TButton=TButton.Create(gui,x+5,by,w/2-10,TGUIFont.font.MaxHeight()*2,"Yes",Null)
- Local no:TButton=TButton.Create(gui,x+w/2+5,by,w/2-10,TGUIFont.font.MaxHeight()*2,"No",Null)
-
- Local click:TWidget=Null
-
- While click=Null
- Cls
- SetAlpha(0.5)
- DrawImage(back,0,0)
- SetAlpha(1)
- TWidget.Draw3DBox(x,y,w,h,False,2)
- gui.EventLoop()
- click=gui.Clicked()
-
- If i<>Null
- SetColor(255,255,255)
- DrawImage(i,MouseX(),MouseY())
- EndIf
-
- Flip
- Wend
-
- Return click=yes
-End Function
-
-
-Rem
-bbdoc: Displays a pop-up menu.
-returns: The index of the selected option, -1 for none.
-about: @title is the menu title, @options the options to display and @x and @y specify its position.
-about: If @i is not null then this image is drawn as a mouse cursor.
-EndRem
-Function GUIMenu(title:String, options:String[], x:Int, y:Int, i:TImage=Null)
- Local f:Int
- Local back:TImage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,0)
- GrabImage(back,0,0)
-
- Local st:Int=TGUIFont.font.MaxHeight()*2
- Local h:Int=TGUIFont.font.MaxHeight()*3
- Local w:Int=TGUIFont.font.TextWidth(title)+30
-
- For f=0 Until options.length
- w=Max(w,TGUIFont.font.TextWidth(options[f])+30)
- h:+st
- Next
-
- Local gui:TGUIHandler=TGUIHandler.Create()
-
- x=Max(0,Min(x,GraphicsWidth()-w))
- y=Max(0,Min(y,GraphicsHeight()-h))
-
- Local label:TLabel=TLabel.Create(gui,x+5,y+2,title)
- Local button:TButton[]=New TButton[options.length]
-
- For f=0 Until options.length
- button[f]=TButton.Create(gui,x+5,y+TGUIFont.font.MaxHeight()*2+f*st,w-10,st-2,options[f],Null)
- Next
-
- Local click:TWidget=Null
-
- While click=Null And MouseHit(2)=0
- Cls
- SetAlpha(0.5)
- DrawImage(back,0,0)
- SetAlpha(1)
- TWidget.Draw3DBox(x,y,w,h,False,2)
- gui.EventLoop()
- click=gui.Clicked()
-
- If i<>Null
- SetColor(255,255,255)
- DrawImage(i,MouseX(),MouseY())
- EndIf
-
- Flip
- Wend
-
- For f=0 Until options.length
- If button[f]=click
- Return f
- EndIf
- Next
-
- Return -1
-End Function
-
-Rem
-bbdoc: Displays a basic file selector.
-returns: The selected file, or null for none.
-about: @title is the title. @file is the initially selected file, and f set to null then no file is selected and the current directory displayed.
-about: Set @save to true for a save dialog (the filename can be altered).
-about: If @i is not null then this image is drawn as a mouse cursor.
-EndRem
-Function GUIFileSelect:String(title:String, file:String, save:Int, i:TImage=Null)
- FlushKeys()
-
- Local oldpwd:String=CurrentDir()
- Local dir:String
- Local fn:String
- Local sw:Int=GraphicsWidth()
- Local sh:Int=GraphicsHeight()
- Local fh:Int=TGUIFont.font.MaxHeight()
- Local fw:Int=TGUIFont.font.MaxWidth()
- Local rows:Int=(sh-fh*10)/fh
-
- If file<>Null And file<>""
- dir=ExtractDir(file)
-
- If dir=""
- dir=oldpwd
- EndIf
-
- If FileType(file)=FILETYPE_FILE
- fn=StripDir(file)
- Else
- fn=""
- EndIf
- Else
- dir=oldpwd
- fn=""
- EndIf
-
- Local gui:TGUIHandler=TGUIHandler.Create()
-
- TPanel.Create(gui,0,0,sw,sh)
- TLabel.Create(gui,10,fh*0.5,title)
-
- Local list:TTextList=TTextList.Create(gui,20,fh*2,sw-40,rows)
- Local scroll:TScrollbar=TScrollbar.Create(gui,list.x+list.w+5,list.y,10,list.h)
-
- Local fntext:TText
-
- If save
- fntext=TText.Create(gui,20,sh-fh*6,fn,(sw-40)/fw,TText.FILENAME)
- Else
- fntext=TText.Create(gui,20,sh-fh*6,fn,(sw-40)/fw,TText.READONLY)
- EndIf
-
- Local bw:Int=TGUIFont.font.MaxWidth()*9
-
- Local cancel:TButton=TButton.Create(gui,sw-bw-20,sh-fh*3.5,bw,fh*2.5,"Cancel",Null)
- Local ok:Tbutton=TButton.Create(gui,cancel.x-bw-10,cancel.y,bw,fh*2.5,"OK",Null)
-
- Local last:TDirEntry=Null
-
- ChangeDir(dir)
- LoadDirEnts(list,scroll,rows)
-
- Repeat
- Cls
-
- gui.EventLoop()
-
- TGUIFont.font.Draw(CurrentDir(),list.x,list.y+list.h+3)
-
- Local click:TWidget=gui.Clicked()
-
- If click=ok
- Local ret:String=CurrentDir()+"/"+fntext.text
- ChangeDir(oldpwd)
- FlushKeys()
- Return ret
- EndIf
-
- If click=cancel Or (KeyHit(KEY_ESCAPE) And gui.GetFocus()=Null)
- ChangeDir(oldpwd)
- FlushKeys()
- Return Null
- EndIf
-
- If list.GetSelectedItem()<>last
- last=TDirEntry(list.GetSelectedItem())
-
- If last.is_dir
- ChangeDir(last.filename)
- LoadDirEnts(list,scroll,rows)
- fntext.text=""
- last=Null
- Else
- fntext.text=last.filename
- EndIf
- EndIf
-
- ok.enabled=(fntext.text<>"")
-
- list.SetTopRow(scroll.GetValue())
-
- If i<>Null
- SetColor(255,255,255)
- DrawImage(i,MouseX(),MouseY())
- EndIf
-
- Flip
- Forever
-End Function
-
-Rem
-bbdoc: Handles a TGUIHandler as if it's a modal dialog.
-returns: True if @ok is pressed, False if @cancel or the ESCAPE key is pressed. ESCAPE is only allowed if nothing has the text focus.
-about: @gui is the GUI handler and widgets to display as a dialog., @ok is the clickable widget that OK's the dialog, @cancel the widget that cancels it.
-about: If @i is not null then this image is drawn as a mouse cursor.
-EndRem
-Function GUIDialog(gui:TGUIHandler, ok:TWidget, cancel:TWidget, i:TImage=Null)
- FlushKeys()
-
- Local back:TImage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,0)
- GrabImage(back,0,0)
-
- Local done:Int=False
- Local ok_pressed:Int
- Local click:TWidget
-
- While done=False
- Cls
- SetAlpha(0.5)
- DrawImage(back,0,0)
- SetAlpha(1)
- gui.EventLoop()
- click=gui.Clicked()
-
- If click=ok
- done=True
- ok_pressed=True
- EndIf
-
- If click=cancel Or (KeyHit(KEY_ESCAPE) And gui.GetFocus()=Null)
- done=True
- ok_pressed=False
- EndIf
-
- If i<>Null
- SetColor(255,255,255)
- DrawImage(i,MouseX(),MouseY())
- EndIf
-
- Flip
- Wend
-
- FlushKeys()
- Return ok_pressed
-End Function
-
-Private
-
-Type TSplitText
- Field lines:TList
- Field width:Int
- Field height:Int
-
- Function Create:TSplitText(s:String)
- Local o:TSplitText=New TSplitText
-
- o.lines=CreateList()
- o.width=0
- o.height=0
-
- Local sub:String=""
-
- For Local f:Int=0 Until s.length
- Local c:Int=s[f]
- If c=Asc("|")
- o.lines.AddLast(sub)
- o.width=Max(o.width,TGUIFont.font.TextWidth(sub))
- o.height:+TGUIFont.font.TextHeight(sub)
- sub=""
- Else
- sub:+Chr(c)
- EndIf
- Next
-
- If sub.length>0
- o.lines.AddLast(sub)
- o.width=Max(o.width,TGUIFont.font.TextWidth(sub))
- o.height:+TGUIFont.font.TextHeight(sub)
- EndIf
-
- Return o
- End Function
-EndType
-
-Type TDirEntry Extends TTextListItem
- Field path:String
- Field dir:String
- Field filename:String
- Field size:Int
- Field is_dir:Int
-
- Function Create:TDirEntry(path:String)
- Local o:TDirEntry=New TDirEntry
- o.path=path
- o.dir=ExtractDir(path)
- o.filename=StripDir(path)
- o.is_dir=(FileType(path)=FILETYPE_DIR)
- o.size=FileSize(path)
- Return o
- End Function
-
- Method Compare:Int(o:Object)
- Local d:TDirEntry=TDirEntry(o)
-
- If d=Null
- Return 0
- EndIf
-
- If is_dir=d.is_dir
- Return filename.Compare(d.filename)
- Else
- If is_dir
- Return -1
- Else
- Return 1
- EndIf
- EndIf
-
- Return 0
- End Method
-
- Method Columns:Int()
- Return 2
- End Method
-
- Method ColumnOffset:Int(i:Int)
- If i=0
- Return 0
- Else
- Return GraphicsWidth()-TGUIFont.font.MaxWidth()*20
- EndIf
- End Method
-
- Method ColumnData:String(i:Int)
- If i=0
- Return filename
- Else
- If is_dir
- Return "DIR"
- Else
- Return size+" bytes"
- EndIf
- EndIf
- End Method
-End Type
-
-Function LoadDirEnts(list:TTextList, scroll:TScrollbar, rows:Int)
- Local d:TList=CreateList()
-
- For Local s:String=EachIn LoadDir(CurrentDir(),False)
- d.AddLast(TDirEntry.Create(CurrentDir()+"/"+s))
- Next
-
- d.Sort()
-
- list.SetOptions(d.ToArray())
- scroll.SetBar(0,Max(1,d.Count()-rows/2),1)
-End Function
+Rem +bbdoc: noddybox.simplegui +EndRem +Module noddybox.simplegui + +ModuleInfo "Framework: (Very) Simple GUI" +ModuleInfo "Copyright: Public Domain" +ModuleInfo "Author: Ian Cowburn" +ModuleInfo "Version: $Revision$" + +' $Id$ + +Strict +Import brl.max2d +Import brl.filesystem +Import brl.basic +Import noddybox.bitmapfont + +Rem +bbdoc: Defines the @TBitmapFont to be used by the GUI. +EndRem +Type TGUIFont + Rem + bbdoc: The font to use. + EndRem + Global font:TBitmapFont +End Type + +Rem +bbdoc: The base widget type. +EndRem +Type TWidget Abstract + + Rem + bbdoc: This widget consumes click events + EndRem + Const HAS_CLICK:Int=1 + Rem + bbdoc: This widget consumes drag events + EndRem + Const HAS_DRAG:Int=2 + Rem + bbdoc: This widget consumes key events + EndRem + Const HAS_KEY:Int=4 + + Rem + bbdoc: If true the widget is displayed. + EndRem + Field displayed:Int + Rem + bbdoc: If true the widget can be interacted with. + EndRem + Field enabled:Int + Rem + bbdoc: The text displayed in the widget. + EndRem + Field text:String + Rem + bbdoc: The X co-ordinate of the widget. + EndRem + Field x:Int + Rem + bbdoc: The Y co-ordinate of the widget. + EndRem + Field y:Int + Rem + bbdoc: The width of the widget. + EndRem + Field w:Int + Rem + bbdoc: The height of the widget. + EndRem + Field h:Int + Rem + bbdoc: Callback to call when clicked. + EndRem + Field callback(w:TWidget) + Rem + bbdoc: True if the mouse is over this widget, False otherwise. + EndRem + Field mouse_over:Int + Rem + bbdoc: The @TGUIHandler that owns this widget. + EndRem + Field owner:TGUIHandler + Rem + bbdoc: The mask of consumed events, zero otherwise. + EndRem + Field consumes:Int + + Rem + bbdoc: Override this accept keypresses + EndRem + Method HandleKey(k:Int) + End Method + + Rem + bbdoc: Override this for when the mouse enters. Call this parent version to handle @mouse_over too. + EndRem + Method MouseEnter() + If displayed And enabled + mouse_over=True + EndIf + End Method + + Rem + bbdoc: Override this for when the mouse leaves. Call this parent version to handle @mouse_over too. + EndRem + Method MouseLeave() + mouse_over=False + End Method + + Rem + bbdoc: Override to handle a mouse button press. + EndRem + Method HandleClick() + End Method + + Rem + bbdoc: Handles mouse dragging. + about: @mx and @my are the changes in mouse co-ordinates since the last drag. + EndRem + Method HandleDrag(mx:Int, my:Int) + End Method + + Rem + bbdoc: Must be provided by a widget to draw itself. + EndRem + Method Draw() Abstract + + Rem + bbdoc: Helper to draw a wireframe rectangle. + EndRem + Function DrawBox(x:Int, y:Int, w:Int, h:Int) + DrawLine(x,y,x+w-1,y) + DrawLine(x+w-1,y,x+w-1,y+h-1) + DrawLine(x+w-1,y+h-1,x,y+h-1) + DrawLine(x,y+h-1,x,y) + End Function + + Rem + bbdoc: Helper to draw a 3D rectangle. + EndRem + Function Draw3DBox(x:Int, y:Int, w:Int, h:Int, invert:Int, size:Int=2) + Local f:Int + + SetColor(200,200,200) + DrawRect(x,y,w,h) + + If invert + SetColor(170,170,170) + Else + SetColor(230,230,230) + EndIf + + For f=0 Until size + DrawLine(x+f,y+f,x+w-1-f,y+f) + DrawLine(x+w-1-f,y+f,x+w-1-f,y+h-1-f) + Next + + If invert + SetColor(230,230,230) + Else + SetColor(170,170,170) + EndIf + + For f=0 Until size + DrawLine(x+w-1-f,y+h-1-f,x+f,y+h-1-f) + DrawLine(x+f,y+h-1-f,x+f,y+f) + Next + End Function + +End Type + +Rem +bbdoc: The panel widget (simply displays itself as a white bordered black box) +EndRem +Type TPanel Extends TWidget + + Rem + bbdoc: Create a TPanel widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x, @y, @x and @h are its position and size. If @x or @y is -1 they are centered. + EndRem + Function Create:TPanel(gui:TGUIHandler,x:Int, y:Int, w:Int, h:Int) + Local o:TPanel=New TPanel + o.displayed=True + o.enabled=True + o.consumes=0 + + If x=-1 + x=(GraphicsWidth()-w)/2 + EndIf + + If y=-1 + y=(GraphicsHeight()-h)/2 + EndIf + + o.x=x + o.y=y + o.w=w + o.h=h + gui.Register(o) + Return o + End Function + + Method Draw() + SetColor(0,0,0) + DrawRect(x,y,w,h) + SetColor(255,255,255) + DrawBox(x,y,w,h) + End Method + +End Type + +Rem +bbdoc: The label widget (simply displays the supplied string) +EndRem +Type TLabel Extends TWidget + Rem + bbdoc: Create a TLabel widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position and @text is the text to display in the label. + EndRem + Function Create:TLabel(gui:TGUIHandler,x:Int, y:Int, text:String) + Local o:TLabel=New TLabel + o.displayed=True + o.enabled=True + o.consumes=0 + o.x=x + o.y=y + o.w=TGUIFont.font.TextWidth(text)+2 + o.h=TGUIFont.font.MaxHeight()+1 + o.text=text + gui.Register(o) + Return o + End Function + + Method Draw() + TGUIFont.font.Draw(text,x+1,y+1) + End Method + +End Type + +Rem +bbdoc: The text entry widget +EndRem +Type TText Extends TWidget + Field maxlen:Int + Field mode:Int + + Rem + bbdoc: The text box handles any text + EndRem + Const NORMAL:Int=0 + + Rem + bbdoc: The text box handles a number + EndRem + Const NUMERIC:Int=1 + + Rem + bbdoc: The text box handles only integer numbers + EndRem + Const INTEGER:Int=2 + + Rem + bbdoc: The text box handles only positive numbers + EndRem + Const POSITIVE:Int=4 + + Rem + bbdoc: The text box handles a basic set of filename characters (alphanumerics, periods, spaces and underscores) + EndRem + Const FILENAME:Int=8 + + Rem + bbdoc: The text box is readonly + EndRem + Const READONLY:Int=256 + + + Rem + bbdoc: Create a TText widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position and @text is the initial text in the widget. + @maxlen is the maximum number of characters allowed. @mode defines the valid characters that can be entered. + @callback is called when RETURN is pressed in the text field. + EndRem + Function Create:TText(gui:TGUIHandler,x:Int, y:Int, text:String, maxlen:Int, mode:Int=0, callback(w:TWidget)=Null) + Local o:TText=New TText + o.displayed=True + o.enabled=True + o.consumes=HAS_CLICK|HAS_KEY + o.x=x + o.y=y + o.maxlen=maxlen + o.w=TGUIFont.font.MaxWidth()*(maxlen+1)+2 + o.h=TGUIFont.font.MaxHeight()+2 + o.text=text + o.callback=callback + o.mode=mode + gui.Register(o) + Return o + End Function + + Rem + bbdoc: Set the text to a floating point value. + about: @v is the floating point value (a double to cover both types). This value will be placed in the text + field with trailing zeros (and trailing dot if an integer) removed. + EndRem + Method SetFloat(v:Double) + Local s:String=v + + If s.Find(".")<>-1 + While s.length>1 And s[s.length-1]=Asc("0") + s=s[..s.length-1] + Wend + + While s.length>1 And s[s.length-1]=Asc(".") + s=s[..s.length-1] + Wend + EndIf + + text=s + End Method + + Method HandleClick() + If Not(mode & READONLY) + owner.SetFocus(Self) + EndIf + End Method + + Method HandleKey(k:Int) + If (mode & READONLY) + Return + EndIf + + If k=27 + text="" + Else If k=8 + If text.length>0 + text=text[0..text.length-1] + EndIf + Else If k=13 + If callback<>Null + callback(Self) + owner.SetFocus(Null) + EndIf + Else If k>31 And k<127 And text.length<maxlen + If (mode & NUMERIC) + If k=Asc("-") And (Not (mode & POSITIVE)) And text.length=0 + text:+Chr(k) + EndIf + + If k>=Asc("0") And k<=Asc("9") + text:+Chr(k) + EndIf + + If k=Asc(".") And (Not (mode & INTEGER)) And text.Find(".")=-1 + text:+Chr(k) + EndIf + Else + If (mode & FILENAME) + If (k>=Asc("a") And k<=Asc("z")) Or (k>=Asc("A") And k<=Asc("Z")) Or (k>=Asc("0") And k<=Asc("9")) Or k=Asc(" ") Or k=Asc(".") Or k=Asc("_") + text:+Chr(k) + EndIf + Else + text:+Chr(k) + EndIf + EndIf + EndIf + End Method + + Method Draw() + Local s:String=text + + If owner.GetFocus()=Self And Not (mode & READONLY) + SetColor(128,128,128) + s:+"_" + Else + SetColor(64,64,64) + EndIf + + DrawRect(x,y,w,h) + + TGUIFont.font.Draw(s,x+1,y+1) + End Method +End Type + +Rem +bbdoc: The checkbox widget +EndRem +Type TCheckbox Extends TWidget + + Rem + bbdoc: True if the box is checked, False otherwise. + EndRem + Field checked:Int + + Rem + bbdoc: Create a TCheckox widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position and @text is the text to display by the checkbox. + @callback is called when the checkbox is toggled. + EndRem + Function Create:TCheckbox(gui:TGUIHandler, x:Int, y:Int, text:String, callback(w:TWidget)=Null) + Local o:TCheckbox=New TCheckbox + o.displayed=True + o.enabled=True + o.consumes=HAS_CLICK + o.x=x + o.y=y + o.w=TGUIFont.font.TextWidth(" "+text)+4+TGUIFont.font.MaxHeight() + o.h=TGUIFont.font.MaxHeight()+2 + o.text=text + o.callback=callback + gui.Register(o) + Return o + End Function + + Method HandleClick() + checked=Not checked + + If callback<>Null + callback(Self) + EndIf + End Method + + Method Draw() + If (mouse_over) + SetColor(255,255,255) + Else + SetColor(200,200,200) + EndIf + + DrawBox(x,y,TGUIFont.font.MaxHeight(),TGUIFont.font.MaxHeight()) + + If checked + SetColor(255,100,100) + DrawRect(x+1,y+1,TGUIFont.font.MaxHeight()-2,TGUIFont.font.MaxHeight()-2) + EndIf + + TGUIFont.font.Draw(" "+text,x+2+TGUIFont.font.MaxHeight(),y+1) + End Method +End Type + +Rem +bbdoc: The button widget +EndRem +Type TButton Extends TWidget + + Field ox:Int + Field oy:Int + + Rem + bbdoc: Create a TButton widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x, @y, @w and @h are its position and size, and @text is the text to display in the button. + @callback is called when the button is pressed. + EndRem + Function Create:TButton(gui:TGUIHandler, x:Int, y:Int, w:Int, h:Int, text:String, callback(w:TWidget)) + Local o:TButton=New TButton + o.displayed=True + o.enabled=True + o.consumes=HAS_CLICK + o.x=x + o.y=y + o.w=w + o.h=h + o.text=text + o.ox=x+w/2-TGUIFont.font.TextWidth(text)/2 + o.oy=y+h/2-TGUIFont.font.TextHeight(text)/2 + o.callback=callback + gui.Register(o) + Return o + End Function + + Method HandleClick() + If callback<>Null + callback(Self) + EndIf + End Method + + Method Draw() + If (mouse_over) + SetColor(255,255,255) + DrawBox(x,y,w,h) + EndIf + + Draw3DBox(x+1,y+1,w-2,h-2,False,2) + + TGUIFont.font.Draw(text,ox,oy) + End Method +End Type + +Rem +bbdoc: A drop down list type widget +EndRem +Type TButtonList Extends TWidget + + Field options:String[] + + Rem + bbdoc: The selected item. + EndRem + Field selected:Int + + Rem + bbdoc: Create a TButtonList widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position. @options are the options for the list and + @selected is the currently selected item. @callback is called when the selection changes. + EndRem + Function Create:TButtonList(gui:TGUIHandler, x:Int, y:Int, options:String[], selected:Int, callback(w:TWidget)) + Local o:TButtonList=New TButtonList + Local maxw:Int=0 + o.displayed=True + o.enabled=True + o.consumes=HAS_CLICK + o.x=x + o.y=y + o.options=options + o.selected=selected + o.text=options[selected] + + For Local s:String=EachIn options + maxw=Max(maxw,TGUIFont.font.TextWidth(s)) + Next + + o.w=maxw+TGUIFont.font.MaxHeight()+4 + o.h=TGUIFont.font.MaxHeight()+2 + o.callback=callback + gui.Register(o) + Return o + End Function + + Method HandleClick() + Local sel:Int=GUIMenu("Select value",options,x,y) + + If sel<>-1 + selected=sel + text=options[selected] + If callback<>Null + callback(Self) + EndIf + EndIf + End Method + + Method Draw() + If (mouse_over) + SetColor(128,128,128) + Else + SetColor(64,64,64) + EndIf + + DrawRect(x,y,w,h) + Draw3DBox(x+2,y+2,h-4,h-4,False,1) + + TGUIFont.font.Draw(text,x+TGUIFont.font.MaxHeight()+3,y+1) + End Method +End Type + +Rem +bbdoc: Optional type to use for TTextList +about: If the objects stored as TTextList options are derived from this type then tabular lists can be created. +EndRem +Type TTextListItem Abstract + Rem + bbdoc: The number of columns. + returns: The number of columns + EndRem + Method Columns:Int() Abstract + + Rem + bbdoc: A column offset. + returns: The column offset for column @i (numbered from zero). + EndRem + Method ColumnOffset:Int(i:Int) Abstract + + Rem + bbdoc: Column data. + returns: The column data for column @i (numbered from zero). + EndRem + Method ColumnData:String(i:Int) Abstract +End Type + +Rem +bbdoc: A widget that displays text items as a list. +EndRem +Type TTextList Extends TWidget + + Field options:Object[] + Field selected:Int + Field num:Int + Field top:Int + Field rows:Int + + Rem + bbdoc: Create a TTextList widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x, @y, and @w are its position and width. + @rows are the number of items to display at a time. + @callback is called when the selection changes. + EndRem + Function Create:TTextList(gui:TGUIHandler, x:Int, y:Int, w:Int, rows:Int, callback(w:TWidget)=Null) + Local o:TTextList=New TTextList + Local maxw:Int=0 + o.displayed=True + o.enabled=True + o.consumes=HAS_CLICK + o.x=x + o.y=y + o.options=Null + o.selected=-1 + o.num=0 + o.top=0 + o.rows=rows + + o.w=w + o.h=TGUIFont.font.MaxHeight()*rows + o.callback=callback + gui.Register(o) + Return o + End Function + + Rem + bbdoc: Sets the options to display in the list. + about: @opts is an array of objects. <i>Note</i>: If the objects passed are derived from TTextListItem then tabular output is generated. + If they are not derived, ToString() is called on the objects to display them, so you are not restricted to the type of object that + can be passed. + EndRem + Method SetOptions(opts:Object[]) + options=opts + num=opts.length + selected=-1 + top=0 + End Method + + Rem + bbdoc: Gets the selected item's index. + returns: The selected item's index, or -1 if nothing is selected. + EndRem + Method GetSelectedIndex:Int() + Return selected + End Method + + Rem + bbdoc: Gets the selected item. + returns: The selected item, or null if nothing is selected. + EndRem + Method GetSelectedItem:Object() + If options<>Null And selected<>-1 + Return options[selected] + Else + Return Null + EndIf + End Method + + Rem + bbdoc: Set the top row. + about: @i is the index of the item to display in the first row of the widget. + EndRem + Method SetTopRow(i:Int) + If options<>Null And i<num + top=i + EndIf + End Method + + Rem + bbdoc: Get the top row. + returns: The index of the item displayed in the first row of the widget. -1 if no options are set. + EndRem + Method GetTopRow:Int() + If options<>Null + Return top + Else + Return -1 + EndIf + End Method + + Rem + bbdoc: Ensure an item is visible. + about: @i is the index of the item that is to be made visible. + EndRem + Method EnsureVisible(i:Int) + If options<>Null And i<num + If i<top + top=i + ElseIf i>=top+rows + top=Max(0,i-rows+1) + EndIf + EndIf + End Method + + Method HandleClick() + If options<>Null + Local sel:Int=top+(MouseY()-y)/TGUIFont.font.MaxHeight() + + If sel<num + selected=sel + If callback<>Null + callback(Self) + EndIf + EndIf + EndIf + End Method + + Method Draw() + SetColor(64,64,64) + DrawRect(x,y,w,h) + + If options<>Null + Local vx:Int + Local vy:Int + Local vw:Int + Local vh:Int + + GetViewport(vx,vy,vw,vh) + + Local ty:Int=y + For Local f:Int=top Until top+rows + SetViewport(x,ty,w,TGUIFont.font.MaxHeight()) + + If f=selected + If mouse_over And MouseY()>=ty And MouseY()<ty+TGUIFont.font.MaxHeight() + SetColor(200,128,128) + Else + SetColor(128,128,128) + EndIf + DrawRect(x,ty,w,TGUIFont.font.MaxHeight()) + Else + If mouse_over And MouseY()>=ty And MouseY()<ty+TGUIFont.font.MaxHeight() And f<num + SetColor(128,0,0) + DrawRect(x,ty,w,TGUIFont.font.MaxHeight()) + EndIf + EndIf + + If f<num + Local li:TTextListItem=TTextListItem(options[f]) + + If li<>Null + For Local f:Int=0 Until li.Columns() + TGUIFont.font.Draw(li.ColumnData(f),x+li.ColumnOffset(f),ty) + Next + Else + TGUIFont.font.Draw(options[f].ToString(),x,ty) + EndIf + EndIf + + ty:+TGUIFont.font.MaxHeight() + Next + + SetViewport(vx,vy,vw,vh) + EndIf + End Method +End Type + +Rem +bbdoc: A number up/down widget for doubles +EndRem +Type TNumberDouble Extends TWidget + + Rem + bbdoc: The value + EndRem + Field value:Double + + Rem + bbdoc: The increment/decrement + EndRem + Field change:Double + + Rem + bbdoc: The maximum value + EndRem + Field maxval:Double + + Rem + bbdoc: The minimum value + EndRem + Field minval:Double + + Rem + bbdoc: Create a TNumber widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position. @callback is called when the value changes. + EndRem + Function Create:TNumberDouble(gui:TGUIHandler, x:Int, y:Int, callback(w:TWidget)=Null) + Local o:TNumberDouble=New TNumberDouble + o.displayed=True + o.enabled=True + o.consumes=HAS_CLICK + o.value=0 + o.minval=0 + o.maxval=100 + o.change=10 + o.x=x + o.y=y + o.w=TGUIFont.font.MaxHeight()*2+8 + o.h=TGUIFont.font.MaxHeight()+2 + o.callback=callback + gui.Register(o) + Return o + End Function + + Method HandleClick() + Local old:Double=value + + If MouseX()<x+w/2 + value=Min(value+change,maxval) + Else + value=Max(value-change,minval) + EndIf + + If value<>old And callback<>Null + callback(Self) + EndIf + End Method + + Method Draw() + If mouse_over + If MouseX()<x+w/2 + SetColor(128,128,128) + DrawRect(x,y,w/2,h) + SetColor(64,64,64) + DrawRect(x+w/2,y,w/2,h) + Else + SetColor(64,64,64) + DrawRect(x,y,w/2,h) + SetColor(128,128,128) + DrawRect(x+w/2,y,w/2,h) + EndIf + Else + SetColor(64,64,64) + DrawRect(x,y,w,h) + EndIf + + Draw3DBox(x+2,y+2,h-4,h-4,False,1) + Draw3DBox(x+w-h,y+2,h-4,h-4,False,1) + + TGUIFont.font.Draw(value,x+w+2,y+1) + End Method +End Type + +Rem +bbdoc: A number up/down widget for ints +EndRem +Type TNumberInt Extends TWidget + + Rem + bbdoc: The value + EndRem + Field value:Int + + Rem + bbdoc: The increment/decrement + EndRem + Field change:Int + + Rem + bbdoc: The maximum value + EndRem + Field maxval:Int + + Rem + bbdoc: The minimum value + EndRem + Field minval:Int + + Rem + bbdoc: Create a TNumber widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x and @y are its position. + @callback is called when the value changes. + EndRem + Function Create:TNumberInt(gui:TGUIHandler, x:Int, y:Int, callback(w:TWidget)=Null) + Local o:TNumberInt=New TNumberInt + o.displayed=True + o.enabled=True + o.consumes=HAS_CLICK + o.value=0 + o.minval=0 + o.maxval=100 + o.change=10 + o.x=x + o.y=y + o.w=TGUIFont.font.MaxHeight()*2+8 + o.h=TGUIFont.font.MaxHeight()+2 + o.callback=callback + gui.Register(o) + Return o + End Function + + Method HandleClick() + Local old:Int=value + + If MouseX()<x+w/2 + value=Min(value+change,maxval) + Else + value=Max(value-change,minval) + EndIf + + If value<>old And callback<>Null + callback(Self) + EndIf + End Method + + Method Draw() + If mouse_over + If MouseX()<x+w/2 + SetColor(128,128,128) + DrawRect(x,y,w/2,h) + SetColor(64,64,64) + DrawRect(x+w/2,y,w/2,h) + Else + SetColor(64,64,64) + DrawRect(x,y,w/2,h) + SetColor(128,128,128) + DrawRect(x+w/2,y,w/2,h) + EndIf + Else + SetColor(64,64,64) + DrawRect(x,y,w,h) + EndIf + + Draw3DBox(x+2,y+2,h-4,h-4,False,1) + Draw3DBox(x+w-h,y+2,h-4,h-4,False,1) + + TGUIFont.font.Draw(value,x+w+2,y+1) + End Method +End Type + +Rem +bbdoc: A scrollbar widget +EndRem +Type TScrollbar Extends TWidget + + Field horiz:Int + Field bc:Int + Field page:Double + Field maxval:Double + Field minval:Double + Field stepsize:Double + Field blocksize:Int + + Rem + bbdoc: Create a TVerticalScrollbar widget. + returns: The created widget. + about: @gui is the @TGUIHandler object managing this wiget. @x, @y, @w and @h are its position and size. + If @w is greater than height then an horizontal scrollbar is created, otherwise its vertical. @callback is called when the scrollbar moves. + EndRem + Function Create:TScrollbar(gui:TGUIHandler, x:Int, y:Int, w:Int, h:Int, callback(w:TWidget)=Null) + Local o:TScrollbar=New TScrollbar + o.displayed=True + o.enabled=True + o.consumes=HAS_CLICK|HAS_DRAG + o.x=x + o.y=y + o.w=w + o.h=h + o.horiz=(w>h) + o.SetBar(0,100,10) + o.callback=callback + gui.Register(o) + Return o + End Function + + Rem + bbdoc: Set parameters for scroll bar + about: @min_val and @max_val are the values at the top and bottom of the scroll bar. @page_size is the numbers between the two that + is covered by the block in the scrollbar. <i>Note</i>: The maximum value of @value is @max_val minus @page_size. + EndRem + Method SetBar(min_val:Double, max_val:Double, page_size:Double) + minval=min_val + maxval=max_val + page=page_size + + If horiz + stepsize=(maxval-minval)/w + blocksize=Min(w,Max(1,page/stepsize)) + bc=x + Else + stepsize=(maxval-minval)/h + blocksize=Min(h,Max(1,page/stepsize)) + bc=y + EndIf + End Method + + Rem + bbdoc: Get the current value of the scrollbar. + returns: The current position of the scrollbar inbetween the minimum and maximum values. + EndRem + Method GetValue:Double() + If horiz + Return minval+(bc-x)*stepsize + Else + Return minval+(bc-y)*stepsize + EndIf + End Method + + Rem + bbdoc: Sets the current value of the scrollbar. + EndRem + Method SetValue(val:Double) + If horiz + bc=Max(x,Min(x+w-blocksize,x+(val-minval)/stepsize)) + Else + bc=Max(y,Min(y+h-blocksize,y+(val-minval)/stepsize)) + EndIf + End Method + + Method HandleClick() + Local old:Double=GetValue() + + If horiz + bc=Max(x,Min(x+w-blocksize,MouseX())) + Else + bc=Max(y,Min(y+h-blocksize,MouseY())) + EndIf + + If GetValue()<>old And callback<>Null + callback(Self) + EndIf + End Method + + Method HandleDrag(mx:Int, my:Int) + Local old:Double=GetValue() + + If horiz + bc=Max(x,Min(x+w-blocksize,bc+mx)) + Else + bc=Max(y,Min(y+h-blocksize,bc+my)) + EndIf + + If GetValue()<>old And callback<>Null + callback(Self) + EndIf + End Method + + Method Draw() + SetColor(64,64,64) + DrawRect(x,y,w,h) + If horiz + Draw3DBox(bc,y,blocksize,h,False,1) + Else + Draw3DBox(x,bc,w,blocksize,False,1) + EndIf + End Method +End Type + +Rem +bbdoc: Handles the GUI. +EndRem +Type TGUIHandler + + ' These are private + ' + Field m_widgets:TList + Field m_focus:TWidget + Field m_over:TWidget + Field m_clicked:TWidget + Field m_dragging:Int + Field m_dragx:Int + Field m_dragy:Int + Field m_dragobj:TWidget + + Rem + bbdoc: Create a GUI Handler. + returns: The GUI Hanbler. + EndRem + Function Create:TGUIHandler() + Local o:TGUIHandler + + o=New TGUIHandler + + o.m_widgets=CreateList() + o.m_focus=Null + o.m_over=Null + o.m_clicked=Null + o.m_dragging=False + o.m_dragx=0 + o.m_dragy=0 + o.m_dragobj=Null + + Return o + End Function + + Rem + bbdoc: Register a widget. + about: Widgets in the library call this themselves when creating. + EndRem + Method Register(w:TWidget) + m_widgets.AddLast(w) + w.owner=Self + End Method + + Rem + bbdoc: Remove all widgets. + EndRem + Method Clear() + m_widgets.Clear() + End Method + + Rem + bbdoc: Sets the enable state of all widgets. + about: If @state is true then all widgets are enabled, otherwise all widgets are disabled. + EndRem + Method SetEnable(state:Int) + For Local w:TWidget=EachIn m_widgets + w.enabled=state + Next + End Method + + Rem + bbdoc: Sets the displayed state of all widgets. + about: If @state is true then all widgets are displayed, otherwise all widgets are hidden. + EndRem + Method SetDisplay(state:Int) + For Local w:TWidget=EachIn m_widgets + w.displayed=state + Next + End Method + + Rem + bbdoc: Sets the keyboard focus to the supplied widget. Pass null for no focus. + EndRem + Method SetFocus(w:TWidget) + m_focus=w + End Method + + Rem + bbdoc: Gets the keyboard focus. + returns: The currently focused TWidget, or null for no focus. + EndRem + Method GetFocus:TWidget() + Return m_focus + End Method + + Rem + bbdoc: Gets the last clicked widget. + returns: The last clicked TWidget. Null is returned if this is called again before another widget is clicked. + EndRem + Method Clicked:TWidget() + Local last:TWidget=m_clicked + m_clicked=Null + Return last + End Method + + Rem + bbdoc: Whether a widget is dragging + returns: True if a widget is consuming a mouse drag. + EndRem + Method IsDragging:Int() + Return m_dragging + End Method + + Rem + bbdoc: Perform the event loop and pass any necessary events. + about: KeyHit(KEY_MOUSELEFT) and GetChar() are used to consume events for the interface. + EndRem + Method EventLoop() + Local x:Int=MouseX() + Local y:Int=MouseY() + Local b:Int=MouseHit(1)>0 + Local drag:Int=MouseDown(1) + + Local w:TWidget=LocateWidget(x,y) + + For Local wid:TWidget=EachIn m_widgets + If wid.displayed + If wid.enabled + wid.Draw() + Else + SetAlpha(0.3) + wid.Draw() + SetAlpha(1) + EndIf + EndIf + Next + + If w<>m_over + If m_over<>Null + m_over.MouseLeave() + EndIf + m_over=w + If m_over<>Null + m_over.MouseEnter() + EndIf + EndIf + + If w<>Null And w.enabled And w.consumes&TWidget.HAS_CLICK=TWidget.HAS_CLICK And b And Not m_dragging + w.HandleClick() + m_clicked=w + EndIf + + Local k:Int=GetChar() + + If k<>0 And m_focus<>Null And m_focus.enabled And m_focus.consumes&TWidget.HAS_KEY=TWidget.HAS_KEY + m_focus.HandleKey(k) + EndIf + + If drag + If m_dragging + m_dragobj.HandleDrag(MouseX()-m_dragx,MouseY()-m_dragy) + m_dragx=MouseX() + m_dragy=MouseY() + Else + If w<>Null And w.consumes&TWidget.HAS_DRAG=TWidget.HAS_DRAG + m_dragging=True + m_dragx=MouseX() + m_dragy=MouseY() + m_dragobj=w + EndIf + EndIf + Else + m_dragging=False + m_dragobj=Null + EndIf + End Method + + ' Private method + ' + Method LocateWidget:TWidget(x:Int,y:Int) + For Local w:TWidget=EachIn m_widgets + If x>=w.x And y>=w.y And x<w.x+w.w And y<w.y+w.h And w.consumes + Return w + EndIf + Next + Return Null + End Method +End Type + + +Rem +bbdoc: Displays a notification alert with the supplied string. +about: The string @s can be split into multiple lines using the '|' character. If @i is not null then this image is drawn as a mouse cursor. +EndRem +Function GUINotify(s:String, i:TImage=Null) + Local back:TImage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,0) + GrabImage(back,0,0) + + Local txt:TSplitText=TSplitText.Create(s) + + Local w:Int=Max(txt.width+10,GraphicsWidth()/4) + Local h:Int=txt.Height+TGUIFont.font.MaxHeight()*4 + Local x:Int=GraphicsWidth()/2-w/2 + Local y=GraphicsHeight()/2-h/2 + Local by=y+h-TGUIFont.font.MaxHeight()*2.5 + + Local gui:TGUIHandler=TGUIHandler.Create() + + Local ty:Int=y+5 + + For Local t:String=EachIn txt.lines + Local label:TLabel=TLabel.Create(gui,x+5,ty,t) + ty:+TGUIFont.font.TextHeight(t) + Next + + Local button:TButton=TButton.Create(gui,x+5,by,w-10,TGUIFont.font.MaxHeight()*2,"OK",Null) + + Local click:TWidget=Null + + While click<>button + Cls + SetAlpha(0.5) + DrawImage(back,0,0) + SetAlpha(1) + TWidget.Draw3DBox(x,y,w,h,False,2) + gui.EventLoop() + click=gui.Clicked() + + If i<>Null + SetColor(255,255,255) + DrawImage(i,MouseX(),MouseY()) + EndIf + + Flip + Wend +End Function + +Rem +bbdoc: Displays a yes/no alert with the supplied string. +returns: True if Yes selected, otherwise False. +about: The string @s can be split into multiple lines using the '|' character. If @i is not null then this image is drawn as a mouse cursor. +EndRem +Function GUIYesNo:Int(s:String, i:TImage=Null) + Local back:TImage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,0) + GrabImage(back,0,0) + + Local txt:TSplitText=TSplitText.Create(s) + + Local w:Int=Max(txt.width+10,GraphicsWidth()/4) + Local h:Int=txt.Height+TGUIFont.font.MaxHeight()*4 + Local x:Int=GraphicsWidth()/2-w/2 + Local y=GraphicsHeight()/2-h/2 + Local by=y+h-TGUIFont.font.MaxHeight()*2.5 + + Local gui:TGUIHandler=TGUIHandler.Create() + + Local ty:Int=y+5 + + For Local t:String=EachIn txt.lines + Local label:TLabel=TLabel.Create(gui,x+5,ty,t) + ty:+TGUIFont.font.TextHeight(t) + Next + + Local yes:TButton=TButton.Create(gui,x+5,by,w/2-10,TGUIFont.font.MaxHeight()*2,"Yes",Null) + Local no:TButton=TButton.Create(gui,x+w/2+5,by,w/2-10,TGUIFont.font.MaxHeight()*2,"No",Null) + + Local click:TWidget=Null + + While click=Null + Cls + SetAlpha(0.5) + DrawImage(back,0,0) + SetAlpha(1) + TWidget.Draw3DBox(x,y,w,h,False,2) + gui.EventLoop() + click=gui.Clicked() + + If i<>Null + SetColor(255,255,255) + DrawImage(i,MouseX(),MouseY()) + EndIf + + Flip + Wend + + Return click=yes +End Function + + +Rem +bbdoc: Displays a pop-up menu. +returns: The index of the selected option, -1 for none. +about: @title is the menu title, @options the options to display and @x and @y specify its position. +If @i is not null then this image is drawn as a mouse cursor. +EndRem +Function GUIMenu(title:String, options:String[], x:Int, y:Int, i:TImage=Null) + Local f:Int + Local back:TImage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,0) + GrabImage(back,0,0) + + Local st:Int=TGUIFont.font.MaxHeight()*2 + Local h:Int=TGUIFont.font.MaxHeight()*3 + Local w:Int=TGUIFont.font.TextWidth(title)+30 + + For f=0 Until options.length + w=Max(w,TGUIFont.font.TextWidth(options[f])+30) + h:+st + Next + + Local gui:TGUIHandler=TGUIHandler.Create() + + x=Max(0,Min(x,GraphicsWidth()-w)) + y=Max(0,Min(y,GraphicsHeight()-h)) + + Local label:TLabel=TLabel.Create(gui,x+5,y+2,title) + Local button:TButton[]=New TButton[options.length] + + For f=0 Until options.length + button[f]=TButton.Create(gui,x+5,y+TGUIFont.font.MaxHeight()*2+f*st,w-10,st-2,options[f],Null) + Next + + Local click:TWidget=Null + + While click=Null And MouseHit(2)=0 + Cls + SetAlpha(0.5) + DrawImage(back,0,0) + SetAlpha(1) + TWidget.Draw3DBox(x,y,w,h,False,2) + gui.EventLoop() + click=gui.Clicked() + + If i<>Null + SetColor(255,255,255) + DrawImage(i,MouseX(),MouseY()) + EndIf + + Flip + Wend + + For f=0 Until options.length + If button[f]=click + Return f + EndIf + Next + + Return -1 +End Function + +Rem +bbdoc: Displays a basic file selector. +returns: The selected file, or null for none. +about: @title is the title. @file is the initially selected file, and f set to null then no file is selected and the current directory displayed. +Set @save to true for a save dialog (the filename can be altered). +If @i is not null then this image is drawn as a mouse cursor. +EndRem +Function GUIFileSelect:String(title:String, file:String, save:Int, i:TImage=Null) + FlushKeys() + + Local oldpwd:String=CurrentDir() + Local dir:String + Local fn:String + Local sw:Int=GraphicsWidth() + Local sh:Int=GraphicsHeight() + Local fh:Int=TGUIFont.font.MaxHeight() + Local fw:Int=TGUIFont.font.MaxWidth() + Local rows:Int=(sh-fh*10)/fh + + If file<>Null And file<>"" + dir=ExtractDir(file) + + If dir="" + dir=oldpwd + EndIf + + If FileType(file)=FILETYPE_FILE + fn=StripDir(file) + Else + fn="" + EndIf + Else + dir=oldpwd + fn="" + EndIf + + Local gui:TGUIHandler=TGUIHandler.Create() + + TPanel.Create(gui,0,0,sw,sh) + TLabel.Create(gui,10,fh*0.5,title) + + Local list:TTextList=TTextList.Create(gui,20,fh*2,sw-40,rows) + Local scroll:TScrollbar=TScrollbar.Create(gui,list.x+list.w+5,list.y,10,list.h) + + Local fntext:TText + + If save + fntext=TText.Create(gui,20,sh-fh*6,fn,(sw-40)/fw,TText.FILENAME) + Else + fntext=TText.Create(gui,20,sh-fh*6,fn,(sw-40)/fw,TText.READONLY) + EndIf + + Local bw:Int=TGUIFont.font.MaxWidth()*9 + + Local cancel:TButton=TButton.Create(gui,sw-bw-20,sh-fh*3.5,bw,fh*2.5,"Cancel",Null) + Local ok:Tbutton=TButton.Create(gui,cancel.x-bw-10,cancel.y,bw,fh*2.5,"OK",Null) + + Local last:TDirEntry=Null + + ChangeDir(dir) + LoadDirEnts(list,scroll,rows) + + Repeat + Cls + + gui.EventLoop() + + TGUIFont.font.Draw(CurrentDir(),list.x,list.y+list.h+3) + + Local click:TWidget=gui.Clicked() + + If click=ok + Local ret:String=CurrentDir()+"/"+fntext.text + ChangeDir(oldpwd) + FlushKeys() + Return ret + EndIf + + If click=cancel Or (KeyHit(KEY_ESCAPE) And gui.GetFocus()=Null) + ChangeDir(oldpwd) + FlushKeys() + Return Null + EndIf + + If list.GetSelectedItem()<>last + last=TDirEntry(list.GetSelectedItem()) + + If last.is_dir + ChangeDir(last.filename) + LoadDirEnts(list,scroll,rows) + fntext.text="" + last=Null + Else + fntext.text=last.filename + EndIf + EndIf + + ok.enabled=(fntext.text<>"") + + list.SetTopRow(scroll.GetValue()) + + If i<>Null + SetColor(255,255,255) + DrawImage(i,MouseX(),MouseY()) + EndIf + + Flip + Forever +End Function + +Rem +bbdoc: Handles a TGUIHandler as if it's a modal dialog. +returns: True if @ok is pressed, False if @cancel or the ESCAPE key is pressed. ESCAPE is only allowed if nothing has the text focus. +about: @gui is the GUI handler and widgets to display as a dialog., @ok is the clickable widget that OK's the dialog, @cancel the widget that cancels it. +If @i is not null then this image is drawn as a mouse cursor. +EndRem +Function GUIDialog(gui:TGUIHandler, ok:TWidget, cancel:TWidget, i:TImage=Null) + FlushKeys() + + Local back:TImage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,0) + GrabImage(back,0,0) + + Local done:Int=False + Local ok_pressed:Int + Local click:TWidget + + While done=False + Cls + SetAlpha(0.5) + DrawImage(back,0,0) + SetAlpha(1) + gui.EventLoop() + click=gui.Clicked() + + If click=ok + done=True + ok_pressed=True + EndIf + + If click=cancel Or (KeyHit(KEY_ESCAPE) And gui.GetFocus()=Null) + done=True + ok_pressed=False + EndIf + + If i<>Null + SetColor(255,255,255) + DrawImage(i,MouseX(),MouseY()) + EndIf + + Flip + Wend + + FlushKeys() + Return ok_pressed +End Function + +Private + +Type TSplitText + Field lines:TList + Field width:Int + Field height:Int + + Function Create:TSplitText(s:String) + Local o:TSplitText=New TSplitText + + o.lines=CreateList() + o.width=0 + o.height=0 + + Local sub:String="" + + For Local f:Int=0 Until s.length + Local c:Int=s[f] + If c=Asc("|") + o.lines.AddLast(sub) + o.width=Max(o.width,TGUIFont.font.TextWidth(sub)) + o.height:+TGUIFont.font.TextHeight(sub) + sub="" + Else + sub:+Chr(c) + EndIf + Next + + If sub.length>0 + o.lines.AddLast(sub) + o.width=Max(o.width,TGUIFont.font.TextWidth(sub)) + o.height:+TGUIFont.font.TextHeight(sub) + EndIf + + Return o + End Function +EndType + +Type TDirEntry Extends TTextListItem + Field path:String + Field dir:String + Field filename:String + Field size:Int + Field is_dir:Int + + Function Create:TDirEntry(path:String) + Local o:TDirEntry=New TDirEntry + o.path=path + o.dir=ExtractDir(path) + o.filename=StripDir(path) + o.is_dir=(FileType(path)=FILETYPE_DIR) + o.size=FileSize(path) + Return o + End Function + + Method Compare:Int(o:Object) + Local d:TDirEntry=TDirEntry(o) + + If d=Null + Return 0 + EndIf + + If is_dir=d.is_dir + Return filename.Compare(d.filename) + Else + If is_dir + Return -1 + Else + Return 1 + EndIf + EndIf + + Return 0 + End Method + + Method Columns:Int() + Return 2 + End Method + + Method ColumnOffset:Int(i:Int) + If i=0 + Return 0 + Else + Return GraphicsWidth()-TGUIFont.font.MaxWidth()*20 + EndIf + End Method + + Method ColumnData:String(i:Int) + If i=0 + Return filename + Else + If is_dir + Return "DIR" + Else + Return size+" bytes" + EndIf + EndIf + End Method +End Type + +Function LoadDirEnts(list:TTextList, scroll:TScrollbar, rows:Int) + Local d:TList=CreateList() + + For Local s:String=EachIn LoadDir(CurrentDir(),False) + d.AddLast(TDirEntry.Create(CurrentDir()+"/"+s)) + Next + + d.Sort() + + list.SetOptions(d.ToArray()) + scroll.SetBar(0,Max(1,d.Count()-rows/2),1) +End Function |