summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--algorithm.mod/.cvsignore7
-rw-r--r--bitmapfont.mod/.cvsignore5
-rw-r--r--gfxmenu.mod/.cvsignore7
-rw-r--r--glflag.mod/.cvsignore4
-rw-r--r--glflag.mod/glflag.bmx210
-rw-r--r--keysyms.mod/.cvsignore7
-rw-r--r--mwidget.mod/.cvsignore7
-rw-r--r--showlicense.mod/.cvsignore1
-rw-r--r--simplegui.mod/.cvsignore7
-rw-r--r--simplegui.mod/simplegui.bmx3364
-rw-r--r--vector.mod/.cvsignore7
-rw-r--r--vectorgfx.mod/.cvsignore8
-rw-r--r--win32.mod/.cvsignore7
13 files changed, 1711 insertions, 1930 deletions
diff --git a/algorithm.mod/.cvsignore b/algorithm.mod/.cvsignore
index 16d9505..0f5601a 100644
--- a/algorithm.mod/.cvsignore
+++ b/algorithm.mod/.cvsignore
@@ -1,6 +1,5 @@
.bmx
doc
-algorithm.debug.win32.a
-algorithm.debug.win32.i
-algorithm.release.win32.a
-algorithm.release.win32.i
+*.a
+*.i
+*.i2
diff --git a/bitmapfont.mod/.cvsignore b/bitmapfont.mod/.cvsignore
index 75c593a..0f5601a 100644
--- a/bitmapfont.mod/.cvsignore
+++ b/bitmapfont.mod/.cvsignore
@@ -1,4 +1,5 @@
.bmx
doc
-bitmapfont.debug.win32.i
-bitmapfont.release.win32.i
+*.a
+*.i
+*.i2
diff --git a/gfxmenu.mod/.cvsignore b/gfxmenu.mod/.cvsignore
index 9565593..0f5601a 100644
--- a/gfxmenu.mod/.cvsignore
+++ b/gfxmenu.mod/.cvsignore
@@ -1,6 +1,5 @@
-gfxmenu.release.win32.i
-gfxmenu.debug.win32.a
-gfxmenu.debug.win32.i
-gfxmenu.release.win32.a
.bmx
doc
+*.a
+*.i
+*.i2
diff --git a/glflag.mod/.cvsignore b/glflag.mod/.cvsignore
deleted file mode 100644
index 84d3b1f..0000000
--- a/glflag.mod/.cvsignore
+++ /dev/null
@@ -1,4 +0,0 @@
-glflag.release.win32.i
-glflag.debug.win32.i
-.bmx
-doc
diff --git a/glflag.mod/glflag.bmx b/glflag.mod/glflag.bmx
deleted file mode 100644
index 2efab50..0000000
--- a/glflag.mod/glflag.bmx
+++ /dev/null
@@ -1,210 +0,0 @@
-' Copyright (c) 2006 Ian Cowburn
-'
-' Permission is hereby granted, free of charge, to any person obtaining a copy of
-' this software and associated documentation files (the "Software"), to deal in
-' the Software without restriction, including without limitation the rights to
-' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-' of the Software, and to permit persons to whom the Software is furnished to do
-' so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included in all
-' copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-' SOFTWARE.
-'
-' $Id$
-'
-Module noddybox.glflag
-
-ModuleInfo "Framework: Simple Open GL Backdrop flag"
-ModuleInfo "Copyright: Ian Cowburn -- released under the MIT License"
-ModuleInfo "Author: Ian Cowburn"
-ModuleInfo "Version: $Revision$"
-
-Import brl.Basic
-Import pub.OpenGL
-
-Strict
-
-Type TGLFlag
-
- ' These are public and can be used to modify the flag
- '
- Field xpos:Float
- Field ypos:Float
- Field zpos:Float
- Field xrot:Float
- Field yrot:Float
- Field zrot:Float
-
- ' These are considered private
- '
- Global static:Int=False
- Global si:Float[]=Null
- Field v:TGLFlagVertex[,]
- Field cell:Int
- Field move:Int
- Field width:Int
- Field height:Int
- Field txt:Int
-
- ' Creates a new flag
- '
- ' texture - Flag texture
- ' horiz - Number of horizontal vertices
- ' vert - Number of vertical vertices
- ' size - Size of each square
- ' tile - Whether the texture is tiled or not
- ' z - Distance of flag (flags always created in the XY plane)
- '
- ' Returns null for invalid parameters.
- '
- Function Create:TGLFlag(texture:Int, horiz:Int, vert:Int, size:Float, tile:Int, z:Float)
- Local o:TGLFlag
-
- If (horiz<2 Or vert<2)
- Return Null
- EndIf
-
- o=New TGLFlag
-
- If (Not o.static)
- o.si=New Float[3600]
- For Local a:Float=0 Until 3600
- o.si[a]=Sin(a/10)
- Next
- o.static=True
- EndIf
-
- o.xpos=0
- o.ypos=0
- o.zpos=z
- o.xrot=0
- o.yrot=0
- o.zrot=0
-
- o.txt=texture
- o.width=horiz
- o.height=vert
- o.cell=size
- o.move=size/2
- o.v=New TGLFlagVertex[horiz,vert]
-
- Local ox:Float
- Local oy:Float
-
- ox=-(size*horiz)/2
- oy=-(size*horiz)/2
-
- For Local x=0 Until horiz
- For Local y=0 Until vert
- Local v:TGLFlagVertex=New TGLFlagVertex
- v.x=ox+x*size
- v.y=oy+y*size
- v.z=0
-
- If (tile)
- v.u=(x&1)
- v.v=(y&1)
- Else
- v.u=1.0/(horiz-1)*x
- v.v=1.0/(vert-1)*(vert-1-y)
- EndIf
-
- o.v[x,y]=v
- Next
- Next
-
- Return o
- End Function
-
- ' Call to render the flag
- '
- Method Render()
- glPushMatrix()
- glTranslatef(xpos,ypos,zpos)
- glRotatef(xrot,1,0,0)
- glRotatef(yrot,0,1,0)
- glRotatef(zrot,0,0,1)
- glBindTexture(GL_TEXTURE_2D,txt)
-
- For Local vert:TGLFlagVertex=EachIn v
- vert.ax=(vert.ax+vert.aix) Mod 3600
- vert.ay=(vert.ay+vert.aiy) Mod 3600
- vert.az=(vert.az+vert.aiz) Mod 3600
- vert.cx=vert.x+si[vert.ax]*move
- vert.cy=vert.y+si[vert.ay]*move
- vert.cz=vert.z+si[vert.az]*move
- Next
-
- For Local x:Int=0 Until width-1
- glBegin(GL_TRIANGLE_STRIP)
- For Local y:Int=0 Until height
- glTexCoord2f(v[x,y].u,v[x,y].v)
- glVertex3f(v[x,y].cx,v[x,y].cy,v[x,y].cz)
- glTexCoord2f(v[x+1,y].u,v[x+1,y].v)
- glVertex3f(v[x+1,y].cx,v[x+1,y].cy,v[x+1,y].cz)
- Next
- glEnd()
- Next
- glPopMatrix()
- End Method
-
- ' Sets the amount of movement for vertex movement (defaults to half the cell size)
- '
- Method SetMove(m:Int)
- move=m
- End Method
-
- ' Sets the movements for a vertex
- '
- ' x - The X co-ord of the vertex
- ' y - The Y co-ord of the vertex
- ' angz - The initial angle (movement is done on a sine wave with 3600 positions) for the Z co-ord
- ' angiz - The angle increment for the Z co-ord
- ' angx - Ditto for X
- ' angix - Ditto for X
- ' angy - And Y
- ' angiy - And Y
- '
- ' Note increments must be positive - to simulate negative ones pass a large increment (eg. 3599 for -1)
- '
- Method Nudge(x:Int, y:Int, angz:Float, angiz:Float=10, angx:Float=0, angix:Float=0, angy:Float=0, angiy:Float=0)
- v[x,y].ax=angx
- v[x,y].ay=angy
- v[x,y].az=angz
- v[x,y].aix=angix
- v[x,y].aiy=angiy
- v[x,y].aiz=angiz
- End Method
-
-End Type
-
-Type TGLFlagVertex
- Field x#,y#,z#
- Field cx#,cy#,cz#
- Field u#,v#
- Field ax#,ay#,az#
- Field aix#,aiy#,aiz#
-
- Method New()
- x=0
- y=0
- z=0
- cx=0
- cy=0
- cz=0
- ax=0
- ay=0
- az=0
- aix=0
- aiy=0
- aiz=0
- End Method
-End Type
diff --git a/keysyms.mod/.cvsignore b/keysyms.mod/.cvsignore
index e3c0b2d..0f5601a 100644
--- a/keysyms.mod/.cvsignore
+++ b/keysyms.mod/.cvsignore
@@ -1,6 +1,5 @@
.bmx
doc
-keysyms.debug.win32.a
-keysyms.debug.win32.i
-keysyms.release.win32.a
-keysyms.release.win32.i
+*.a
+*.i
+*.i2
diff --git a/mwidget.mod/.cvsignore b/mwidget.mod/.cvsignore
index c7027e3..0f5601a 100644
--- a/mwidget.mod/.cvsignore
+++ b/mwidget.mod/.cvsignore
@@ -1,6 +1,5 @@
-mwidget.release.win32.i
-mwidget.debug.win32.a
-mwidget.debug.win32.i
-mwidget.release.win32.a
.bmx
doc
+*.a
+*.i
+*.i2
diff --git a/showlicense.mod/.cvsignore b/showlicense.mod/.cvsignore
index a37585c..0bddba6 100644
--- a/showlicense.mod/.cvsignore
+++ b/showlicense.mod/.cvsignore
@@ -2,3 +2,4 @@ doc
.bmx
*.a
*.i
+*.i2
diff --git a/simplegui.mod/.cvsignore b/simplegui.mod/.cvsignore
index 5c46a3b..f3c28d9 100644
--- a/simplegui.mod/.cvsignore
+++ b/simplegui.mod/.cvsignore
@@ -1,6 +1,5 @@
doc
.bmx
-simplegui.debug.win32.a
-simplegui.debug.win32.i
-simplegui.release.win32.a
-simplegui.release.win32.i
+*.a
+*.i
+*.i2
diff --git a/simplegui.mod/simplegui.bmx b/simplegui.mod/simplegui.bmx
index e7e2319..fcf0c17 100644
--- a/simplegui.mod/simplegui.bmx
+++ b/simplegui.mod/simplegui.bmx
@@ -1,1682 +1,1682 @@
-' Copyright (c) 2006 Ian Cowburn
-'
-' Permission is hereby granted, free of charge, to any person obtaining a copy of
-' this software and associated documentation files (the "Software"), to deal in
-' the Software without restriction, including without limitation the rights to
-' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-' of the Software, and to permit persons to whom the Software is furnished to do
-' so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included in all
-' copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-' SOFTWARE.
-'
-' $Id$
-'
-Rem
-bbdoc: noddybox.simplegui
-EndRem
-Module noddybox.simplegui
-
-ModuleInfo "Framework: (Very) Simple GUI"
-ModuleInfo "Copyright: Ian Cowburn -- released under the MIT License"
-ModuleInfo "Author: Ian Cowburn"
-ModuleInfo "Version: $Revision$"
-
-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 TSGUIFont
- 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=TSGUIFont.font.TextWidth(text)+2
- o.h=TSGUIFont.font.MaxHeight()+1
- o.text=text
- gui.Register(o)
- Return o
- End Function
-
- Method Draw()
- TSGUIFont.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=TSGUIFont.font.MaxWidth()*(maxlen+1)+2
- o.h=TSGUIFont.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)
-
- TSGUIFont.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=TSGUIFont.font.TextWidth(" "+text)+4+TSGUIFont.font.MaxHeight()
- o.h=TSGUIFont.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,TSGUIFont.font.MaxHeight(),TSGUIFont.font.MaxHeight())
-
- If checked
- SetColor(255,100,100)
- DrawRect(x+1,y+1,TSGUIFont.font.MaxHeight()-2,TSGUIFont.font.MaxHeight()-2)
- EndIf
-
- TSGUIFont.font.Draw(" "+text,x+2+TSGUIFont.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-TSGUIFont.font.TextWidth(text)/2
- o.oy=y+h/2-TSGUIFont.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)
-
- TSGUIFont.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,TSGUIFont.font.TextWidth(s))
- Next
-
- o.w=maxw+TSGUIFont.font.MaxHeight()+4
- o.h=TSGUIFont.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)
-
- TSGUIFont.font.Draw(text,x+TSGUIFont.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=TSGUIFont.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)/TSGUIFont.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,TSGUIFont.font.MaxHeight())
-
- If f=selected
- If mouse_over And MouseY()>=ty And MouseY()<ty+TSGUIFont.font.MaxHeight()
- SetColor(200,128,128)
- Else
- SetColor(128,128,128)
- EndIf
- DrawRect(x,ty,w,TSGUIFont.font.MaxHeight())
- Else
- If mouse_over And MouseY()>=ty And MouseY()<ty+TSGUIFont.font.MaxHeight() And f<num
- SetColor(128,0,0)
- DrawRect(x,ty,w,TSGUIFont.font.MaxHeight())
- EndIf
- EndIf
-
- If f<num
- Local li:TTextListItem=TTextListItem(options[f])
-
- If li<>Null
- For Local f:Int=0 Until li.Columns()
- TSGUIFont.font.Draw(li.ColumnData(f),x+li.ColumnOffset(f),ty)
- Next
- Else
- TSGUIFont.font.Draw(options[f].ToString(),x,ty)
- EndIf
- EndIf
-
- ty:+TSGUIFont.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=TSGUIFont.font.MaxHeight()*2+8
- o.h=TSGUIFont.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)
-
- TSGUIFont.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=TSGUIFont.font.MaxHeight()*2+8
- o.h=TSGUIFont.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)
-
- TSGUIFont.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+TSGUIFont.font.MaxHeight()*4
- Local x:Int=GraphicsWidth()/2-w/2
- Local y=GraphicsHeight()/2-h/2
- Local by=y+h-TSGUIFont.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:+TSGUIFont.font.TextHeight(t)
- Next
-
- Local button:TButton=TButton.Create(gui,x+5,by,w-10,TSGUIFont.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+TSGUIFont.font.MaxHeight()*4
- Local x:Int=GraphicsWidth()/2-w/2
- Local y=GraphicsHeight()/2-h/2
- Local by=y+h-TSGUIFont.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:+TSGUIFont.font.TextHeight(t)
- Next
-
- Local yes:TButton=TButton.Create(gui,x+5,by,w/2-10,TSGUIFont.font.MaxHeight()*2,"Yes",Null)
- Local no:TButton=TButton.Create(gui,x+w/2+5,by,w/2-10,TSGUIFont.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=TSGUIFont.font.MaxHeight()*2
- Local h:Int=TSGUIFont.font.MaxHeight()*3
- Local w:Int=TSGUIFont.font.TextWidth(title)+30
-
- For f=0 Until options.length
- w=Max(w,TSGUIFont.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+TSGUIFont.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=TSGUIFont.font.MaxHeight()
- Local fw:Int=TSGUIFont.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=TSGUIFont.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()
-
- TSGUIFont.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,TSGUIFont.font.TextWidth(sub))
- o.height:+TSGUIFont.font.TextHeight(sub)
- sub=""
- Else
- sub:+Chr(c)
- EndIf
- Next
-
- If sub.length>0
- o.lines.AddLast(sub)
- o.width=Max(o.width,TSGUIFont.font.TextWidth(sub))
- o.height:+TSGUIFont.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()-TSGUIFont.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
+' Copyright (c) 2006 Ian Cowburn
+'
+' Permission is hereby granted, free of charge, to any person obtaining a copy of
+' this software and associated documentation files (the "Software"), to deal in
+' the Software without restriction, including without limitation the rights to
+' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+' of the Software, and to permit persons to whom the Software is furnished to do
+' so, subject to the following conditions:
+'
+' The above copyright notice and this permission notice shall be included in all
+' copies or substantial portions of the Software.
+'
+' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+' SOFTWARE.
+'
+' $Id$
+'
+Rem
+bbdoc: noddybox.simplegui
+EndRem
+Module noddybox.simplegui
+
+ModuleInfo "Framework: (Very) Simple GUI"
+ModuleInfo "Copyright: Ian Cowburn -- released under the MIT License"
+ModuleInfo "Author: Ian Cowburn"
+ModuleInfo "Version: $Revision$"
+
+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 TSGUIFont
+ 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=TSGUIFont.font.TextWidth(text)+2
+ o.h=TSGUIFont.font.MaxHeight()+1
+ o.text=text
+ gui.Register(o)
+ Return o
+ End Function
+
+ Method Draw()
+ TSGUIFont.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 READ_ONLY: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=TSGUIFont.font.MaxWidth()*(maxlen+1)+2
+ o.h=TSGUIFont.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 & READ_ONLY)
+ owner.SetFocus(Self)
+ EndIf
+ End Method
+
+ Method HandleKey(k:Int)
+ If (mode & READ_ONLY)
+ 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 & READ_ONLY)
+ SetColor(128,128,128)
+ s:+"_"
+ Else
+ SetColor(64,64,64)
+ EndIf
+
+ DrawRect(x,y,w,h)
+
+ TSGUIFont.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=TSGUIFont.font.TextWidth(" "+text)+4+TSGUIFont.font.MaxHeight()
+ o.h=TSGUIFont.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,TSGUIFont.font.MaxHeight(),TSGUIFont.font.MaxHeight())
+
+ If checked
+ SetColor(255,100,100)
+ DrawRect(x+1,y+1,TSGUIFont.font.MaxHeight()-2,TSGUIFont.font.MaxHeight()-2)
+ EndIf
+
+ TSGUIFont.font.Draw(" "+text,x+2+TSGUIFont.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-TSGUIFont.font.TextWidth(text)/2
+ o.oy=y+h/2-TSGUIFont.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)
+
+ TSGUIFont.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,TSGUIFont.font.TextWidth(s))
+ Next
+
+ o.w=maxw+TSGUIFont.font.MaxHeight()+4
+ o.h=TSGUIFont.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)
+
+ TSGUIFont.font.Draw(text,x+TSGUIFont.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=TSGUIFont.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)/TSGUIFont.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,TSGUIFont.font.MaxHeight())
+
+ If f=selected
+ If mouse_over And MouseY()>=ty And MouseY()<ty+TSGUIFont.font.MaxHeight()
+ SetColor(200,128,128)
+ Else
+ SetColor(128,128,128)
+ EndIf
+ DrawRect(x,ty,w,TSGUIFont.font.MaxHeight())
+ Else
+ If mouse_over And MouseY()>=ty And MouseY()<ty+TSGUIFont.font.MaxHeight() And f<num
+ SetColor(128,0,0)
+ DrawRect(x,ty,w,TSGUIFont.font.MaxHeight())
+ EndIf
+ EndIf
+
+ If f<num
+ Local li:TTextListItem=TTextListItem(options[f])
+
+ If li<>Null
+ For Local f:Int=0 Until li.Columns()
+ TSGUIFont.font.Draw(li.ColumnData(f),x+li.ColumnOffset(f),ty)
+ Next
+ Else
+ TSGUIFont.font.Draw(options[f].ToString(),x,ty)
+ EndIf
+ EndIf
+
+ ty:+TSGUIFont.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=TSGUIFont.font.MaxHeight()*2+8
+ o.h=TSGUIFont.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)
+
+ TSGUIFont.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=TSGUIFont.font.MaxHeight()*2+8
+ o.h=TSGUIFont.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)
+
+ TSGUIFont.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+TSGUIFont.font.MaxHeight()*4
+ Local x:Int=GraphicsWidth()/2-w/2
+ Local y=GraphicsHeight()/2-h/2
+ Local by=y+h-TSGUIFont.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:+TSGUIFont.font.TextHeight(t)
+ Next
+
+ Local button:TButton=TButton.Create(gui,x+5,by,w-10,TSGUIFont.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+TSGUIFont.font.MaxHeight()*4
+ Local x:Int=GraphicsWidth()/2-w/2
+ Local y=GraphicsHeight()/2-h/2
+ Local by=y+h-TSGUIFont.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:+TSGUIFont.font.TextHeight(t)
+ Next
+
+ Local yes:TButton=TButton.Create(gui,x+5,by,w/2-10,TSGUIFont.font.MaxHeight()*2,"Yes",Null)
+ Local no:TButton=TButton.Create(gui,x+w/2+5,by,w/2-10,TSGUIFont.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=TSGUIFont.font.MaxHeight()*2
+ Local h:Int=TSGUIFont.font.MaxHeight()*3
+ Local w:Int=TSGUIFont.font.TextWidth(title)+30
+
+ For f=0 Until options.length
+ w=Max(w,TSGUIFont.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+TSGUIFont.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=TSGUIFont.font.MaxHeight()
+ Local fw:Int=TSGUIFont.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.READ_ONLY)
+ EndIf
+
+ Local bw:Int=TSGUIFont.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()
+
+ TSGUIFont.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,TSGUIFont.font.TextWidth(sub))
+ o.height:+TSGUIFont.font.TextHeight(sub)
+ sub=""
+ Else
+ sub:+Chr(c)
+ EndIf
+ Next
+
+ If sub.length>0
+ o.lines.AddLast(sub)
+ o.width=Max(o.width,TSGUIFont.font.TextWidth(sub))
+ o.height:+TSGUIFont.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()-TSGUIFont.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
diff --git a/vector.mod/.cvsignore b/vector.mod/.cvsignore
index 5f1a86a..0f5601a 100644
--- a/vector.mod/.cvsignore
+++ b/vector.mod/.cvsignore
@@ -1,6 +1,5 @@
-vector.release.win32.i
-vector.debug.win32.a
-vector.debug.win32.i
-vector.release.win32.a
.bmx
doc
+*.a
+*.i
+*.i2
diff --git a/vectorgfx.mod/.cvsignore b/vectorgfx.mod/.cvsignore
index eda0494..0f5601a 100644
--- a/vectorgfx.mod/.cvsignore
+++ b/vectorgfx.mod/.cvsignore
@@ -1,5 +1,5 @@
-vectorgfx.release.win32.i
-vectorgfx.debug.win32.a
-vectorgfx.debug.win32.i
-vectorgfx.release.win32.a
.bmx
+doc
+*.a
+*.i
+*.i2
diff --git a/win32.mod/.cvsignore b/win32.mod/.cvsignore
index dd78089..0f5601a 100644
--- a/win32.mod/.cvsignore
+++ b/win32.mod/.cvsignore
@@ -1,6 +1,5 @@
-win32.release.win32.i
-win32.debug.win32.a
-win32.debug.win32.i
-win32.release.win32.a
.bmx
doc
+*.a
+*.i
+*.i2