Răsfoiți Sursa

Added maxgui.proxygadgets module.

woollybah 11 ani în urmă
părinte
comite
e489c49edf

+ 41 - 0
proxygadgets.mod/doc/createhyperlink.bmx

@@ -0,0 +1,41 @@
+Strict
+
+Import MaxGUI.Drivers
+Import MaxGUI.ProxyGadgets
+
+AppTitle = "Hyperlink Test Window"
+
+Global wndMain:TGadget = CreateWindow( AppTitle, 100, 100, 300, 59, Null, WINDOW_TITLEBAR|WINDOW_CLIENTCOORDS|WINDOW_STATUS )
+	
+	'Standard Hyperlink Gadget
+	Global hypLeft:TGadget = CreateHyperlink( "http://www.google.com/", 2, 2, ClientWidth(wndMain)-4, 15, wndMain, LABEL_LEFT )
+	
+	'Center Aligned Hyperlink Gadget with alternate text
+	Global hypCenter:TGadget = CreateHyperlink( "http://www.blitzbasic.com/", 2, 21, ClientWidth(wndMain)-4, 17, wndMain, LABEL_CENTER|LABEL_FRAME, "BlitzBasic" )
+	
+	'Right Aligned Sunken Hyperlink Gadget with custom rollover colors set
+	Global hypRight:TGadget = CreateHyperlink( "http://www.blitzmax.com/", 2, 42, ClientWidth(wndMain)-4, 15, wndMain, LABEL_RIGHT, "Custom Rollover Colors" )
+		SetGadgetTextColor(hypRight,128,128,128)	'Set normal text color to grey.
+		SetGadgetColor(hypRight,255,128,0)			'Set rollover color to orange.
+
+'Example of how to retrieve a hyperlink gadget's URL
+Print "Hyperlink 1 URL: " + String(GadgetExtra(hypLeft))
+Print "Hyperlink 2 URL: " + String(GadgetExtra(hypCenter))
+Print "Hyperlink 3 URL: " + String(GadgetExtra(hypRight))
+
+'Example of how to set a hyperlink gadget's URL
+SetGadgetExtra( hypRight, "http://www.blitzbasic.co.nz" )
+'We need to update the tooltip to the new URL
+SetGadgetToolTip( hypRight, String(GadgetExtra(hypRight)) )
+
+Repeat
+	
+	WaitEvent()
+	
+	SetStatusText wndMain, CurrentEvent.ToString()
+	
+	Select EventID()
+		Case EVENT_WINDOWCLOSE, EVENT_APPTERMINATE;End
+	EndSelect
+	
+Forever

+ 66 - 0
proxygadgets.mod/doc/createscrollpanel.bmx

@@ -0,0 +1,66 @@
+Strict
+
+'Import MaxGUI.Drivers
+Framework BaH.GTKMaxGUI
+Import BRL.EventQueue
+Import MaxGUI.ProxyGadgets
+Import brl.random
+
+AppTitle = "Scroll Panel Example"
+SeedRnd MilliSecs()
+
+Global wndMain:TGadget = CreateWindow(AppTitle,100,100,400,300,Null,WINDOW_TITLEBAR|WINDOW_RESIZABLE|WINDOW_CENTER|WINDOW_CLIENTCOORDS|WINDOW_STATUS)
+	
+	' Create a scroll-panel
+	Global scrlMain:TScrollPanel = CreateScrollPanel( 0, 0, ClientWidth(wndMain), ClientHeight(wndMain)-30, wndMain, SCROLLPANEL_SUNKEN )
+	SetGadgetLayout scrlMain,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED
+	
+	' Retrieve the panel that is scrolled
+	Local tmpClient:TGadget = ScrollPanelClient(scrlMain)
+	
+	' Draw some buttons on the scroll-panel
+	Local tmpButton:TGadget
+	
+	For Local i:Int = 1 To 50
+		tmpButton = CreateButton( "Button " + i, 0, (i-1)*35, ClientWidth(scrlMain)-20, 30, tmpClient, BUTTON_PUSH )
+		SetGadgetTextColor tmpButton,Rand(0,255),Rand(0,255),Rand(0,255)
+		SetGadgetLayout tmpButton,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_CENTERED
+	Next
+	
+	' Resize the scrollable region tight around the buttons
+	FitScrollPanelClient( scrlMain, SCROLLPANEL_SIZETOKIDS )
+	
+	' Add some buttons for testing the ScrollScrollPanel function.
+	Global btnTopLeft:TGadget = CreateButton( "Top Left", 0, ClientHeight(wndMain)-30, ClientWidth(wndMain)/4, 30, wndMain, BUTTON_PUSH )
+	SetGadgetLayout( btnTopLeft, EDGE_ALIGNED, EDGE_RELATIVE, EDGE_CENTERED, EDGE_ALIGNED )
+	SetGadgetToolTip( btnTopLeft, "ScrollScrollPanel( scrlMain, SCROLLPANEL_LEFT, SCROLLPANEL_TOP )" )
+	
+	Global btnTopRight:TGadget = CreateButton( "Top Right", ClientWidth(wndMain)/4, ClientHeight(wndMain)-30, ClientWidth(wndMain)/4, 30, wndMain, BUTTON_PUSH )
+	SetGadgetLayout( btnTopRight, EDGE_RELATIVE, EDGE_RELATIVE, EDGE_CENTERED, EDGE_ALIGNED )
+	SetGadgetToolTip( btnTopRight, "ScrollScrollPanel( scrlMain, SCROLLPANEL_RIGHT, SCROLLPANEL_TOP )" )
+	
+	Global btnBottomLeft:TGadget = CreateButton( "Bottom Left", 2*ClientWidth(wndMain)/4, ClientHeight(wndMain)-30, ClientWidth(wndMain)/4, 30, wndMain, BUTTON_PUSH )
+	SetGadgetLayout( btnBottomLeft, EDGE_RELATIVE, EDGE_RELATIVE, EDGE_CENTERED, EDGE_ALIGNED )
+	SetGadgetToolTip( btnBottomLeft, "ScrollScrollPanel( scrlMain, SCROLLPANEL_LEFT, SCROLLPANEL_BOTTOM )" )
+	
+	Global btnBottomRight:TGadget = CreateButton( "Bottom Right", 3*ClientWidth(wndMain)/4, ClientHeight(wndMain)-30, ClientWidth(wndMain)/4, 30, wndMain, BUTTON_PUSH )
+	SetGadgetLayout( btnBottomRight, EDGE_RELATIVE, EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED )
+	SetGadgetToolTip( btnBottomRight, "ScrollScrollPanel( scrlMain, SCROLLPANEL_RIGHT, SCROLLPANEL_BOTTOM )" )
+	
+Repeat
+	Select WaitEvent()
+		Case EVENT_WINDOWCLOSE, EVENT_APPTERMINATE;End
+		Case EVENT_GADGETACTION
+			Select EventSource()
+				Case btnTopLeft
+					ScrollScrollPanel( scrlMain, SCROLLPANEL_LEFT, SCROLLPANEL_TOP )
+				Case btnTopRight
+					ScrollScrollPanel( scrlMain, SCROLLPANEL_RIGHT, SCROLLPANEL_TOP )
+				Case btnBottomLeft
+					ScrollScrollPanel( scrlMain, SCROLLPANEL_LEFT, SCROLLPANEL_BOTTOM )
+				Case btnBottomRight
+					ScrollScrollPanel( scrlMain, SCROLLPANEL_RIGHT, SCROLLPANEL_BOTTOM )
+			EndSelect
+	EndSelect
+	SetStatusText wndMain, "ScrollPanelX(): " + ScrollPanelX( scrlMain ) + ", ScrollPanelY():" + ScrollPanelY( scrlMain )
+Forever

+ 37 - 0
proxygadgets.mod/doc/createsplitter.bmx

@@ -0,0 +1,37 @@
+Strict
+
+Import MaxGUI.Drivers
+Import MaxGUI.ProxyGadgets
+
+Global wndMain:TGadget = CreateWindow("Splitter Example",100,100,400,300,Null,WINDOW_TITLEBAR|WINDOW_RESIZABLE|WINDOW_CENTER|WINDOW_CLIENTCOORDS|WINDOW_STATUS)
+	
+	'Create a splitter gadget
+	Global spltMain:TSplitter = CreateSplitter( 0, 0, ClientWidth(wndMain), ClientHeight(wndMain), wndMain )
+	SetGadgetLayout spltMain,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED
+	
+	Local tmpSplitPanel:TGadget
+		
+		'Add a gadget to our left pane
+		tmpSplitPanel = SplitterPanel(spltMain,SPLITPANEL_MAIN)
+		Global txtEditor:TGadget = CreateTextArea(0,0,ClientWidth(tmpSplitPanel),ClientHeight(tmpSplitPanel),tmpSplitPanel,TEXTAREA_WORDWRAP)
+		SetGadgetLayout(txtEditor,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED)
+		
+			AddTextAreaText(txtEditor, "The quick brown fox jumped over the lazy dogs.~n~n")
+			AddTextAreaText(txtEditor, "The quick brown fox jumped over the lazy dogs.~n~n")
+			AddTextAreaText(txtEditor, "The quick brown fox jumped over the lazy dogs.~n~n")
+		
+		'Add a gadget to our right pane
+		tmpSplitPanel = SplitterPanel(spltMain,SPLITPANEL_SIDEPANE)
+		Global treeView:TGadget = CreateTreeView(0,0,ClientWidth(tmpSplitPanel),ClientHeight(tmpSplitPanel),tmpSplitPanel)
+		SetGadgetLayout(treeView,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED)
+		
+			AddTreeViewNode("Child", AddTreeViewNode("Parent Node", TreeViewRoot(treeView)))
+			AddTreeViewNode("Other", TreeViewRoot(treeView))
+	
+Repeat
+	WaitEvent()
+	SetStatusText wndMain, CurrentEvent.ToString()
+	Select EventID()
+		Case EVENT_WINDOWCLOSE, EVENT_APPTERMINATE;End
+	EndSelect
+Forever

BIN
proxygadgets.mod/doc/scroll_dimensions.png


BIN
proxygadgets.mod/doc/scroll_position.png


+ 120 - 0
proxygadgets.mod/hyperlink.bmx

@@ -0,0 +1,120 @@
+Strict
+
+Import MaxGUI.MaxGUI
+
+' THyperlinkGadget Proxy Gadget
+' Author: Seb Hollington
+
+Rem
+bbdoc: Creates a basic hyperlink gadget that opens the specified @url$ in the default browser when clicked.
+about: The underlying gadget is a label, and so the @style parameter can take all the #CreateLabel flags apart from LABEL_SEPARATOR.
+
+The normal and roll-over text color can be set individually using #SetGadgetTextColor and #SetGadgetColor respectively.
+
+The optional @customtext$ parameter allows you to set user-friendly text that masks the URL in the label. If this is specified in #CreateHyperlink
+then the label's tooltip is automatically set to the URL the link refers to. This masking text can be changed at any time by calling #SetGadgetText.
+Finally, the @url$ that the hyperlink gadget opens can be modified/retrieved using #SetGadgetExtra and String( #GadgetExtra )
+respectively (see code example).
+End Rem
+Function CreateHyperlink:TGadget( url$,x,y,w,h,group:TGadget,style=0,customtext$ = "" )
+	
+	Return New THyperlinkGadget.Create(url,x,y,w,h,group,style,customtext)
+	
+EndFunction
+
+Type THyperlinkGadget Extends TProxyGadget
+	
+	Global lstHyperlinkGadgets:TList
+	
+	Global fntDefault:TGuiFont, fntHoverDefault:TGuiFont
+	
+	Field hyperlinkstyle%
+	Field colors[][] = [[0,0,255],[255,0,0]]
+	
+	Field lastclick[] = [-1, -1]
+	
+	Method New()
+		If Not lstHyperlinkGadgets Then Initialize()
+		Local r:Byte, g:Byte, b:Byte
+		LookupGuiColor( GUICOLOR_LINKFG, r, g, b )
+		colors[0] = [Int r, Int g, Int b]
+	EndMethod
+	
+	Method Create:THyperlinkGadget(pUrl$,x,y,w,h,group:TGadget,style,customtext$)
+		
+		If Not customtext Then customtext = pUrl$
+		If (style&LABEL_SEPARATOR) = LABEL_SEPARATOR Then style:&~LABEL_SEPARATOR
+		
+		Local tmpLabel:TGadget = CreateLabel( customtext, x, y, w, h, group, style&31 )
+		If Not tmpLabel Then Return Null Else SetGadgetSensitivity(tmpLabel, SENSITIZE_MOUSE)
+		
+		SetGadgetFont(tmpLabel,fntDefault)	
+		
+		If customtext <> pUrl Then SetGadgetToolTip( tmpLabel, pUrl )
+		
+		SetProxy( tmpLabel );Super.SetTextColor(colors[0][0], colors[0][1], colors[0][2])
+		
+		hyperlinkstyle = style;extra = pUrl
+		lstHyperlinkGadgets.AddLast Self
+		
+		Return Self
+		
+	EndMethod
+	
+	Method EventHook:TEvent( pEvent:TEvent )
+		
+		Select pEvent.id
+		
+			Case EVENT_MOUSEENTER
+				Super.SetTextColor(colors[1][0], colors[1][1], colors[1][2]);SetPointer(POINTER_HAND)
+				Super.SetFont( fntHoverDefault )
+			Case EVENT_MOUSELEAVE
+				Super.SetTextColor(colors[0][0], colors[0][1], colors[0][2]);SetPointer(POINTER_DEFAULT)
+				Super.SetFont( fntDefault )
+			Case EVENT_MOUSEDOWN;If lastclick[0] <> pEvent.x Or lastclick[1] <> pEvent.y Then lastclick = [pEvent.x,pEvent.y];OpenURL(String(extra))
+		
+		EndSelect
+		
+		Return Null
+	
+	EndMethod
+	
+	Method SetFont( font:TGuiFont )
+		fntDefault = font;fntHoverDefault = font
+		Super.SetFont(font)
+	EndMethod
+	
+	Method SetColor(r,g,b)
+		colors[1][0] = r;colors[1][1] = g;colors[1][2] = b
+	EndMethod
+	
+	Method SetTextColor(r,g,b)
+		colors[0][0] = r;colors[0][1] = g;colors[0][2] = b
+		Super.SetTextColor(colors[0][0], colors[0][1], colors[0][2])
+	EndMethod
+	
+	Method CleanUp()
+		lstHyperlinkGadgets.Remove(Self)
+		Super.CleanUp()
+	EndMethod
+	
+	Function Initialize()
+		lstHyperlinkGadgets = New TList
+		AddHook EmitEventHook, eventHandler, Null, -1
+		fntDefault = LookupGuiFont( GUIFONT_SYSTEM, 0, 0 )
+		fntHoverDefault = LookupGuiFont( GUIFONT_SYSTEM, 0, FONT_UNDERLINE )
+	EndFunction
+	
+	Function eventHandler:Object( pID%, pData:Object, pContext:Object )
+		Local pEvent:TEvent = TEvent(pData)
+		
+		If pEvent Then
+			For Local tmpHyperlinkGadget:THyperlinkGadget = EachIn lstHyperlinkGadgets
+				If tmpHyperlinkGadget = pEvent.source Then Return tmpHyperlinkGadget.EventHook( pEvent )
+			Next
+		EndIf
+		
+		Return pData
+	EndFunction
+	
+EndType

+ 48 - 0
proxygadgets.mod/proxygadgets.bmx

@@ -0,0 +1,48 @@
+Strict
+
+Rem
+bbdoc: MaxGUI/Proxy Gadgets
+about: This module contains any official proxy gadgets that wrap around the standard MaxGUI gadgets and provide an additional library
+of gadgets that can be used in a whole host of programs. Any gadgets in this library can be used with the standard MaxGUI functions
+available in the core #MaxGUI.MaxGUI module.
+End Rem
+Module MaxGUI.ProxyGadgets
+
+ModuleInfo "Version: 1.12"
+ModuleInfo "License: BSD License"
+
+ModuleInfo "History: 1.12 Release"
+ModuleInfo "History: Added optional pHandleSize parameter."
+ModuleInfo "History: Added ability to set split handle background color."
+ModuleInfo "History: Fixed SPLIT_LIMITPANESIZE and SPLIT_CLICKTOTOGGLE bug."
+ModuleInfo "History: 1.11 Release"
+ModuleInfo "History: Hyperlink gadget now defaults to link colour returned by LookupGuiColor()."
+ModuleInfo "History: 1.10 Release"
+ModuleInfo "History: Decreased the TSplitter threshold for orientation flip."
+ModuleInfo "History: 1.09 Release"
+ModuleInfo "History: Added SCROLLPANEL_HNEVER and SCROLLPANEL_VNEVER constants."
+ModuleInfo "History: 1.08 Release"
+ModuleInfo "History: Added a new TScrollPanel gadget."
+ModuleInfo "History: 1.07 Release"
+ModuleInfo "History: Tweaked THyperlinkGadget.eventHandler() so that it works consistently on all platforms."
+ModuleInfo "History: 1.06 Release"
+ModuleInfo "History: Fixed some rogue dragging locks for splitters on Windows."
+ModuleInfo "History: 1.05 Release"
+ModuleInfo "History: Tidied up TSplitter.eventHook(), fixing several bugs in drag code."
+ModuleInfo "History: 1.04 Release"
+ModuleInfo "History: Added a new SetSplitterBehavior command."
+ModuleInfo "History: 1.03 Release"
+ModuleInfo "History: Fixed hyperlink tooltips."
+ModuleInfo "History: A hyperlink's URL can now be modified/retrieved using SetGadgetExtra / GadgetExtra."
+ModuleInfo "History: 1.02 Release"
+ModuleInfo "History: Added a new TSplitter gadget. See CreateSplitter for more info."
+ModuleInfo "History: 1.01 Release"
+ModuleInfo "History: Filtered EVENT_MOUSEDOWN to avoid infinite loop on Windows."
+ModuleInfo "History: Updated THyperlinkGadget to use LookupGuiFont()."
+ModuleInfo "History: Inherited MaxGUI.Win32MaxGUI's label SS_NOTIFY fix."
+ModuleInfo "History: 1.00 Release"
+ModuleInfo "History: Added the first custom gadget: the hyperlink control."
+
+Import "hyperlink.bmx"
+Import "splitter.bmx"
+Import "scrollpanel.bmx"

+ 518 - 0
proxygadgets.mod/scrollpanel.bmx

@@ -0,0 +1,518 @@
+Strict
+
+Import MaxGUI.MaxGUI
+
+' TScrollPanel Proxy Gadget
+' Author: Seb Hollington
+
+Const SCROLLPANEL_SUNKEN:Int = 1
+Const SCROLLPANEL_HALWAYS:Int = 2
+Const SCROLLPANEL_VALWAYS:Int = 4
+
+Const SCROLLPANEL_HSCALING:Int = 8
+Const SCROLLPANEL_VSCALING:Int = 16
+
+Const SCROLLPANEL_HNEVER:Int = 32
+Const SCROLLPANEL_VNEVER:Int = 64
+
+Rem
+bbdoc: Creates a scrollable panel.
+about: A scroll panel can be used to present a large number of gadgets in a small area.  Scrollbars are displayed to allow the
+user to move around a client-area that is viewed through a, typically smaller, viewport.  The #ScrollPanelX and #ScrollPanelY functions
+can be used to retrieve the current scroll position, and the #ScrollScrollPanel command, to set the scroll position.  A @TScrollPanel gadget
+emits the following event when %{the user} scrolls around the scroll area:
+
+[ @{Event} | @{EventX} | @{EventY}
+* EVENT_GADGETACTION | New value of #ScrollPanelX. | New value of #ScrollPanelY.
+]
+
+Any combination of the following style flags are supported:
+
+[ @Constant | @Meaning
+* SCROLLPANEL_SUNKEN | The scroll-panel will be drawn with a sunken border.
+* SCROLLPANEL_HALWAYS | The horizontal scroll-bar will be shown at all times (even if not necessary).
+* SCROLLPANEL_VALWAYS | The vertical scroll-bar will be shown at all times (even if not necessary).
+* SCROLLPANEL_HNEVER | The horizontal scroll-bar will never be shown (even if client-area width is greater than viewport's).
+* SCROLLPANEL_VNEVER | The vertical scroll-bar will never be shown (even if client-area height is greater than viewport's).
+]
+
+The above can also be combined with any of the following behavioural flags which determine how the scrollable client-area resizes with the viewport:
+
+[ @Constant | @Meaning
+* SCROLLPANEL_HSCALING | The client area's width grows uniformly as the viewport is sized.
+* SCROLLPANEL_VSCALING | The client area's height grows uniformly as the viewport is sized.
+]
+
+[
+* The @TScrollPanel instance itself represents the viewport of the scroll-panel, which can be manipulated (e.g. resized/shown/hidden) using the
+standard MaxGUI commands.
+* The client area is the panel that will actually be scrolled and is retrieved using the #ScrollPanelClient command.  This is the panel
+whose dimensions determine the total scrollable area, and is also the panel that all your child gadgets should be added to.
+]
+
+<img src="scroll_dimensions.png" />
+
+The dimensions given above can each be retrieved programatically:
+
+{{
+GadgetWidth( myScrollPanel )                           'Gadget Width
+GadgetHeight( myScrollPanel )                          'Gadget Height
+
+ClientWidth( myScrollPanel )                           'Viewport Width
+ClientHeight( myScrollPanel )                          'Viewport Height
+
+ClientWidth( ScrollPanelClient( myScrollPanel ) )      'Client Area Width
+ClientHeight( ScrollPanelClient( myScrollPanel ) )     'Client Area Height
+}}
+
+And the gadget and client dimensions can be set programatically using (viewport sizing is handled automatically):
+
+{{
+'Set Gadget dimensions (and position).
+SetGadgetShape( myScrollPanel, x, y, w, h )
+
+'Set Client Area dimensions (position parameters are ignored).
+SetGadgetShape( ScrollPanelClient( myScrollPanel ), 0, 0, w, h )
+}}
+
+See Also: #ScrollPanelClient, #FitScrollPanelClient, #ScrollScrollPanel, #ScrollPanelX, #ScrollPanelY and #FitScrollPanelClient.
+End Rem
+Function CreateScrollPanel:TScrollPanel( x,y,w,h,group:TGadget,flags=0 )
+	
+	Return New TScrollPanel.Create(x,y,w,h,group,flags)
+	
+EndFunction
+
+Rem
+bbdoc: Retrieves the panel that is scrolled.
+about: This panel represents the total scrollable region of the gadget.  As such, use #SetGadgetShape on this panel to alter the
+scrollable region (the xpos and ypos parameters will be ignored) or use the helper function #FitScrollPanelClient to resize the client area to
+common dimensions.  In either case, it is important to note that, contrary to typical MaxGUI behaviour, resizing the client panel
+%{will not alter the position or dimensions of the children}, irrespective of any sizing behaviour previously defined using #SetGadgetLayout.
+
+See #CreateScrollPanel for more information.
+End Rem
+Function ScrollPanelClient:TGadget( scrollpanel:TScrollPanel )
+	Return scrollpanel.pnlClientArea
+EndFunction
+
+Const SCROLLPANEL_SIZETOKIDS:Int = 0
+Const SCROLLPANEL_SIZETOVIEWPORT:Int = 1
+
+Rem
+bbdoc: Helper function that resizes the client area to common dimensions.
+about: This function resizes the scrollable area of a @TScrollPanel widget.  Any child gadgets will retain their current
+position and dimensions, irrespective of any sizing behaviour previously defined using #SetGadgetLayout. This function will
+also reset the current visible area, to the furthest top-left.
+
+[
+* @scrollpanel: The scrollpanel whose client you want to resize.
+* @fitType: Should be one of the following constants:
+]
+
+[ @Constant | @Meaning
+* SCROLLPANEL_SIZETOKIDS | The client area will be resized so that its width and height are just enough to enclose all child gadgets.
+* SCROLLPANEL_SIZETOVIEWPORT | The client area will be resized so that it is the same size that the viewport is currently (effectively removing the scrollbars).
+]
+
+See #CreateScrollPanel and #ScrollPanelClient for more information.
+End Rem
+Function FitScrollPanelClient( scrollpanel:TScrollPanel, fitType% = SCROLLPANEL_SIZETOKIDS )
+	Select fitType
+		Case SCROLLPANEL_SIZETOKIDS
+			scrollpanel.FitToChildren()
+		Case SCROLLPANEL_SIZETOVIEWPORT
+			scrollpanel.FitToViewport()
+	EndSelect
+EndFunction
+
+Const SCROLLPANEL_HOLD:Int = -1
+Const SCROLLPANEL_TOP:Int = 0
+Const SCROLLPANEL_LEFT:Int = 0
+Const SCROLLPANEL_BOTTOM:Int = 2147483647
+Const SCROLLPANEL_RIGHT:Int = 2147483647
+
+Rem
+bbdoc: Scrolls the current viewport to a new position.
+about: This function moves the client area of the scroll panel so that the the top-left corner of the viewport is as close
+as possible to the specified @{pX}, @{pY} position in the client-area.
+
+<img src="scroll_position.png" />
+
+There are 4 position constants provided:
+
+[ @Constant | @{Position}
+* SCROLLPANEL_TOP | Top-most edge.
+* SCROLLPANEL_LEFT | Left-most edge.
+* SCROLLPANEL_BOTTOM | Bottom-most edge.
+* SCROLLPANEL_RIGHT | Right-most edge.
+* SCROLLPANEL_HOLD | Current position.
+]
+
+For example, both of these commands...
+
+{{
+ScrollScrollPanel( myScrollPanel, SCROLLPANEL_LEFT, SCROLLPANEL_TOP )
+ScrollScrollPanel( myScrollPanel, 0, 0 )
+}}
+...would scroll to the top-leftmost section of the client area. Conversely, we can scroll to the bottom-right most
+region of the client area by calling:
+{{
+ScrollScrollPanel( myScrollPanel, SCROLLPANEL_RIGHT, SCROLLPANEL_BOTTOM )
+}}
+
+If we only want to change just the horizontal or just the vertical scroll position, we can use the SCROLLPANEL_HOLD constant. E.g.
+to scroll to the left most side without changing the current vertical scroll position, we could use:
+{{
+ScrollScrollPanel( myScrollPanel, SCROLLPANEL_LEFT, SCROLLPANEL_HOLD )
+}}
+
+See #CreateScrollPanel, #ScrollPanelX, #ScrollPanelY and #ScrollPanelClient for more information.
+EndRem
+Function ScrollScrollPanel( scrollpanel:TScrollPanel, pX = SCROLLPANEL_TOP, pY = SCROLLPANEL_LEFT )
+	scrollpanel.ScrollTo( pX, pY )
+	scrollpanel.Update()
+EndFunction
+
+Rem
+bbdoc: Returns the x position of the client-area that is currently at the top-left of the viewport.
+about: Complementary function to #ScrollPanelY and #ScrollScrollPanel.  See #ScrollScrollPanel for a visual representation
+of this value.
+
+See #CreateScrollPanel for more information.
+EndRem
+Function ScrollPanelX:Int( scrollpanel:TScrollpanel )
+	Return scrollpanel.GetXScroll()
+EndFunction
+
+Rem
+bbdoc: Returns the y position of the client-area that is currently at the top-left of the viewport.
+about: Complementary function to #ScrollPanelX and #ScrollScrollPanel.  See #ScrollScrollPanel for a visual representation
+of this value.
+
+See #CreateScrollPanel for more information.
+EndRem
+Function ScrollPanelY:Int( scrollpanel:TScrollpanel )
+	Return scrollpanel.GetYScroll()
+EndFunction
+
+Type TScrollPanel Extends TProxyGadget
+	
+	Field flags:Int
+	
+	Field pnlEntire:TGadget
+	Field pnlViewport:TGadget
+	Field pnlClientArea:TProxyGadget
+	Field scrHorizontal:TGadget
+	Field scrVertical:TGadget
+	
+	Field currentH%, currentV%, clientW%, clientH%
+	
+	Const SCROLL_WIDTH% = 18
+	
+	Method New()
+		
+		AddHook EmitEventHook,eventHandler,Self, -1
+		RemoveVerticalScroll();RemoveHorizontalScroll()
+		
+	EndMethod
+	
+	Method Create:TScrollPanel(pX%, pY%, pWidth%, pHeight%, pParent:TGadget, pFlags% = 0)
+		
+		Local tmpPanelFlags:Int
+		
+		flags = pFlags
+		
+		If flags & (SCROLLPANEL_SUNKEN) Then tmpPanelFlags:|PANEL_SUNKEN
+		
+		pnlEntire = CreatePanel(pX,pY,pWidth,pHeight,pParent,tmpPanelFlags);HideGadget(pnlEntire);SetProxy(pnlEntire)
+		pnlViewport = CreatePanel(0,0,pnlEntire.ClientWidth(),pnlEntire.ClientHeight(), pnlEntire)
+		pnlClientArea = New TScrollClient
+		pnlClientArea.SetProxy(CreatePanel(0,0,pnlViewport.ClientWidth(),pnlViewport.ClientHeight(), pnlViewport))
+		scrHorizontal = CreateSlider(0,pnlEntire.ClientHeight()-SCROLL_WIDTH,pnlEntire.ClientWidth()-SCROLL_WIDTH,SCROLL_WIDTH, pnlEntire, SLIDER_HORIZONTAL|SLIDER_SCROLLBAR )
+		scrVertical = CreateSlider(pnlEntire.ClientWidth()-SCROLL_WIDTH,0,SCROLL_WIDTH,pnlEntire.ClientHeight()-SCROLL_WIDTH, pnlEntire, SLIDER_VERTICAL|SLIDER_SCROLLBAR )
+		
+		SetGadgetLayout(pnlViewport, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED )
+		SetGadgetLayout(scrHorizontal, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED )
+		SetGadgetLayout(scrVertical, EDGE_CENTERED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED )
+		
+		Select (flags & (SCROLLPANEL_HSCALING|SCROLLPANEL_VSCALING))
+			Case 0
+				SetGadgetLayout(pnlClientArea.GetProxy(), EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED, EDGE_CENTERED )
+			Case SCROLLPANEL_HSCALING
+				SetGadgetLayout(pnlClientArea.GetProxy(), EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_CENTERED )
+			Case SCROLLPANEL_VSCALING
+				SetGadgetLayout(pnlClientArea.GetProxy(), EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED, EDGE_ALIGNED )
+			Case SCROLLPANEL_HSCALING|SCROLLPANEL_VSCALING
+				SetGadgetLayout(pnlClientArea.GetProxy(), EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED )
+		EndSelect
+		
+		HideGadget(scrHorizontal);HideGadget(scrVertical)
+		
+		ShowGadget(pnlEntire)
+		
+		Return Self
+	
+	EndMethod
+	
+	Method SetShape(x,y,w,h)
+		Super.SetShape(x,y,w,h)
+		Update()
+	EndMethod
+	
+	Method ClientWidth:Int()
+		Return pnlViewport.ClientWidth()
+	EndMethod
+	
+	Method ClientHeight:Int()
+		Return pnlViewport.ClientHeight()
+	EndMethod
+	
+	Method GetXScroll:Int()
+		Return currentH
+	EndMethod
+	
+	Method GetYScroll:Int()
+		Return currentV
+	EndMethod
+	
+	Method ScrollTo(pHSlider%, pVSlider%)
+		
+		Local tmpRight:Int = Max( pnlClientArea.ClientWidth()-pnlViewport.ClientWidth(), 0 )
+		Local tmpBottom:Int = Max( pnlClientArea.ClientHeight()-pnlViewport.ClientHeight(), 0 )
+		
+		If (pHSlider > tmpRight) Then pHSlider = tmpRight
+		If (pVSlider > tmpBottom) Then pVSlider = tmpBottom
+		
+		If (pHSlider >= 0) Then currentH = pHSlider
+		If (pVSlider >= 0) Then currentV = pVSlider
+		
+		SetGadgetShape(pnlClientArea.GetProxy(),-currentH,-currentV,pnlClientArea.GetWidth(),pnlClientArea.GetHeight())
+		
+	EndMethod
+	
+	Method FitToChildren( pRightMargin:Int = 0, pBottomMargin:Int = 0 )
+		
+		Local tmpRight:Int, tmpBottom:Int
+		
+		For Local tmpChild:TGadget = EachIn pnlClientArea.proxy.kids
+			tmpRight = Max(tmpRight,GadgetX(tmpChild)+GadgetWidth(tmpChild))
+			tmpBottom = Max(tmpBottom,GadgetY(tmpChild)+GadgetHeight(tmpChild))
+		Next
+		
+		HideGadget( pnlViewport )
+		pnlClientArea.SetShape(0,0,tmpRight + pRightMargin,tmpBottom + pBottomMargin)
+		ScrollTo(0,0)
+		ShowGadget( pnlViewport )
+		
+	EndMethod
+	
+	Method FitToViewport()
+		
+		HideGadget( pnlViewport )
+		pnlClientArea.SetShape(0,0,pnlViewport.ClientWidth(),pnlViewport.ClientHeight())
+		ScrollTo(0,0)
+		ShowGadget( pnlViewport )
+		
+	EndMethod
+	
+	Method Update()
+		
+		Local tmpDiff:Int, tmpPos:Int
+		
+		If Not pnlClientArea Then Return
+		
+		If pnlViewport.ClientWidth() < pnlClientArea.GetWidth() Then
+			AddHorizontalScroll(pnlViewport.ClientWidth(),pnlClientArea.GetXPos(),pnlClientArea.GetWidth())
+		Else
+			RemoveHorizontalScroll()
+		EndIf
+		
+		If pnlViewport.ClientHeight() < pnlClientArea.GetHeight() Then
+			AddVerticalScroll(pnlViewport.ClientHeight(),pnlClientArea.GetYPos(),pnlClientArea.GetHeight())
+		Else
+			RemoveVerticalScroll()
+		EndIf
+		
+		If pnlViewport.ClientWidth() < pnlClientArea.GetWidth() Then
+			
+			tmpDiff = Max(pnlViewport.ClientWidth()-(pnlClientArea.GetXpos() + pnlClientArea.GetWidth()),0)
+			tmpPos = Min(pnlClientArea.GetXPos()+tmpDiff,0)
+			
+			AddHorizontalScroll(pnlViewport.ClientWidth(),tmpPos,pnlClientArea.GetWidth())
+			ScrollTo( -tmpPos, currentV )
+			
+		Else
+		
+			RemoveHorizontalScroll()
+			
+		EndIf
+		
+		If pnlViewport.ClientHeight() < pnlClientArea.GetHeight() Then
+			
+			tmpDiff = Max(pnlViewport.ClientHeight()-(pnlClientArea.GetYPos() + pnlClientArea.GetHeight()),0)
+			tmpPos = Min(pnlClientArea.GetYPos()+tmpDiff,0)
+			
+			AddVerticalScroll(pnlViewport.ClientHeight(),tmpPos,pnlClientArea.GetHeight())
+			ScrollTo( currentH, -tmpPos )
+			
+		Else
+		
+			RemoveVerticalScroll()
+			
+		EndIf
+		
+	EndMethod
+	
+	Method AddVerticalScroll(pVisible%, pY%, pHeight%)
+		
+		If scrVertical And Not (flags&SCROLLPANEL_VNEVER) Then
+			
+			SetGadgetShape(pnlViewport, 0, 0, pnlEntire.ClientWidth() - SCROLL_WIDTH, GadgetHeight(pnlViewport))
+			SetGadgetShape(scrVertical, pnlEntire.ClientWidth()-SCROLL_WIDTH, 0, SCROLL_WIDTH, GadgetHeight(pnlViewport))
+			
+			SetSliderRange(scrVertical, pVisible, pHeight);SetSliderValue(scrVertical,-pY)
+			EnableGadget(scrVertical);ShowGadget(scrVertical)
+		
+		EndIf
+		
+	EndMethod
+	
+	Method RemoveVerticalScroll()
+	
+		If scrVertical And Not GadgetDisabled(scrVertical) Then
+			
+			If Not (flags&SCROLLPANEL_VALWAYS) Then
+				HideGadget(scrVertical)
+				SetGadgetShape(pnlViewport, 0, 0, pnlEntire.ClientWidth(), GadgetHeight(pnlViewport))
+			EndIf
+			
+			DisableGadget(scrVertical)
+			
+			ScrollTo(currentH,0)
+			
+		EndIf
+	
+	EndMethod
+	
+	Method AddHorizontalScroll(pVisible%, pX%, pWidth%)
+	
+		If scrHorizontal And Not (flags&SCROLLPANEL_HNEVER) Then
+			
+			SetGadgetShape(pnlViewport, 0, 0, GadgetWidth(pnlViewport), pnlEntire.ClientHeight()-SCROLL_WIDTH )
+			SetGadgetShape(scrHorizontal, 0, pnlEntire.ClientHeight()-SCROLL_WIDTH, GadgetWidth(pnlViewport), SCROLL_WIDTH)
+			
+			SetSliderRange(scrHorizontal, pVisible, pWidth);SetSliderValue(scrHorizontal,-pX)
+			EnableGadget(scrHorizontal);ShowGadget(scrHorizontal)
+		
+		EndIf
+		
+	EndMethod
+	
+	Method RemoveHorizontalScroll()
+	
+		If scrHorizontal And Not GadgetDisabled(scrHorizontal) Then
+			
+			If Not (flags&SCROLLPANEL_HALWAYS) Then
+				SetGadgetShape(pnlViewport, 0, 0, GadgetWidth(pnlViewport), pnlEntire.ClientHeight())
+				HideGadget(scrHorizontal)
+			EndIf
+			
+			DisableGadget(scrHorizontal)
+			
+			ScrollTo(0,currentV)
+			
+		EndIf
+	
+	EndMethod
+	
+	Method eventHook:Object(pID%, pData:Object, pContext:Object)
+	
+		Local tmpEvent:TEvent = TEvent(pData)
+		If tmpEvent = Null Then Return pData
+		
+		Select tmpEvent.id
+			
+			Case EVENT_WINDOWSIZE
+			
+				If CheckParent(pnlEntire, TGadget(tmpEvent.source)) Then Update()
+			
+			Case EVENT_GADGETACTION
+				
+				Local tmpH:Int = currentH, tmpV:Int = currentV
+				
+				Select tmpEvent.source
+				
+					Case scrHorizontal
+						tmpH = SliderValue(scrHorizontal)
+					Case scrVertical
+						tmpV = SliderValue(scrVertical)
+					Default
+						Return pData
+				
+				EndSelect
+			
+				ScrollTo(tmpH, tmpV)
+				EmitEvent CreateEvent( EVENT_GADGETACTION, Self, 0, 0, currentH, currentV, Null )
+				pData = Null
+				
+		EndSelect
+		
+		Return pData
+		
+	EndMethod
+	
+	Method CleanUp()
+	
+		RemoveHook EmitEventHook, eventHandler, Self
+		SetProxy(Null)
+		If pnlClientArea Then pnlClientArea.SetProxy(Null);pnlClientArea = Null
+		If pnlEntire Then HideGadget(pnlEntire);FreeGadget(pnlEntire)
+	
+	EndMethod
+	
+	Function eventHandler:Object(pID%, pData:Object, pContext:Object)
+	
+		Local tmpSuperPanel:TScrollPanel = TScrollPanel(pContext)
+		If tmpSuperPanel Then pData = tmpSuperPanel.eventHook(pID%, pData:Object, pContext:Object)
+		Return pData
+	
+	EndFunction
+	
+	Function CheckParent%( pGadget:TGadget, pParentToCheck:TGadget )
+		
+		If pGadget = pParentToCheck Then Return True
+		If pGadget.parent Then Return CheckParent(pGadget.parent, pParentToCheck)
+		
+	EndFunction
+	
+EndType
+
+Private
+
+Type TScrollClient Extends TProxyGadget
+	
+	Method SetShape(x,y,w,h)
+		
+		Local i:Int, arrDimensions:Int[][], tmpDimensions:Int[]
+		
+		For Local tmpChild:TGadget = EachIn proxy.kids
+			tmpDimensions = [GadgetX(tmpChild),GadgetY(tmpChild),GadgetWidth(tmpChild),GadgetHeight(tmpChild)]
+			arrDimensions:+[tmpDimensions]
+		Next
+		
+		Super.SetShape(GetXPos(),GetYPos(),w,h)
+		TScrollPanel(proxy.parent.parent.source).Update()
+		
+		For Local tmpChild:TGadget = EachIn proxy.kids
+			tmpDimensions = arrDimensions[i];i:+1
+			SetGadgetShape( tmpChild, tmpDimensions[0], tmpDimensions[1], tmpDimensions[2], tmpDimensions[3] )
+		Next
+
+	EndMethod
+	
+	Method SetLayout(lft,rht,top,bot)
+		'Do nothing
+	EndMethod
+	
+EndType

+ 817 - 0
proxygadgets.mod/splitter.bmx

@@ -0,0 +1,817 @@
+SuperStrict
+
+Import MaxGUI.MaxGUI
+
+' TSplitter Proxy Gadget
+' Author: Seb Hollington
+
+Rem
+bbdoc: Creates a gadget consisting of two panels separated by a draggable divider.
+about: A splitter is made up of two panels: a main panel (identified using SPLITPANEL_MAIN) which acts as the main working area; and a side pane
+(identified using SPLITPANEL_SIDEPANE) which is typically used to display additional information. Both of these panels are contained within a
+parent panel that is represented by the @TSplitter instance. The two panels are separated by a split handle/divider, the behavior of which can be
+queried and altered using the #SplitterBehavior and #SetSplitterBehavior functions respectively. 
+
+The size of the split handle is determined using the optional @pHandleSize parameter.  The default size of 10 pixels should work well in most 
+situations, and the minimum value that this can be is 4.
+
+After creating a splitter gadget, you can start adding gadgets to it by retrieving the appropriate panel with the #SplitterPanel command.
+
+The @TSplitter type instance can be used with most of the standard MaxGUI commands, allowing you to change the properties of the entire splitter
+gadget. There are, however, a few exceptions:
+
+#SetGadgetSensitivity and #GadgetSensitivity will have no effect on the splitter gadget. If you want to use active panels, create your own
+sub-panel within each splitter panel.
+
+#SetGadgetTooltip and #GadgetTooltip will set/retrieve a tooltip for when the user is hovering over the splitter handle/divider.
+
+#SetGadgetColor will modify the split handle/divider background color.
+
+See Also: #SplitterPanel, #SetSplitterPosition, #SplitterPosition, #SetSplitterBehavior, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
+End Rem
+Function CreateSplitter:TSplitter( pX%, pY%, pW%, pH%, pParent:TGadget, pOrientation% = SPLIT_VERTICAL, pHandleSize% = 10 )
+	Return New TSplitter.Create( pX, pY, pW, pH, pParent, pOrientation, pHandleSize )
+EndFunction
+
+Const SPLITPANEL_MAIN% = 0, SPLITPANEL_SIDEPANE% = 1, SPLITPANEL_HANDLE% = 2
+
+Rem
+bbdoc: Retrieves either one of the two panels which make up a TSplitter gadget.
+about: This function is used to return a standard MaxGUI panel that you can add your gadgets to.
+
+The panels available are SPLITPANEL_MAIN and SPLITPANEL_SIDEPANE. See #CreateSplitter for more information
+about the differences between the two panels.
+
+See Also: #CreateSplitter, #SetSplitterPosition, #SplitterPosition, #SetSplitterBehavior, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
+End Rem
+Function SplitterPanel:TGadget( splitter:TSplitter, panel% = SPLITPANEL_MAIN )
+	Return splitter.GetPanel(panel)
+EndFunction
+
+Rem
+bbdoc: Sets the position of the splitter (in pixels) from the edge of a TSplitter gadget.
+about: This function's most common use is to restore a split position previously returned by #SplitterPosition.
+
+The optional @save% parameter determines whether or not the position supplied is restored when the splitter returns from it's hidden state.
+In most circumstances, this should be left as #True.
+
+See Also: #CreateSplitter, #SplitterPanel, #SplitterPosition, #SetSplitterBehavior, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
+End Rem
+Function SetSplitterPosition( splitter:TSplitter, position%, save% = True )
+	splitter.SetPanelSpace( position, save )
+EndFunction
+
+Rem
+bbdoc: Returns the position of the splitter (in pixels) from the edge of a TSplitter gadget.
+about: This function's most common use is probably for saving the current splitter position to restore at a later time using #SetSplitterPosition.
+
+See Also: #CreateSplitter, #SplitterPanel, #SetSplitterPosition, #SetSplitterBehavior, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
+End Rem
+Function SplitterPosition:Int( splitter:TSplitter )
+	Return splitter.GetPanelSpace( SPLITPANEL_SIDEPANE )
+EndFunction
+
+Const SPLIT_HORIZONTAL% = 0, SPLIT_VERTICAL% = 1, SPLIT_FLIPPED% = 2
+
+Rem
+bbdoc: Sets the splitter orientation.
+about: The two orientations available are (both of which can be combined with SPLIT_FLIPPED):
+
+[ @Orientation | @Description
+* -1 | Toggles the SPLIT_FLIPPED flag.
+* SPLIT_VERTICAL | The splitter consists of a main left panel with a side-pane along the right edge.
+* SPLIT_HORIZONTAL | The splitter consists of a main top panel with a side-pane along the bottom edge.
+* SPLIT_VERTICAL ~| SPLIT_FLIPPED | The splitter consists of a main right panel with a side-pane along the left edge.
+* SPLIT_HORIZONTAL ~| SPLIT_FLIPPED | The splitter consists of a main bottom with a side-pane along the top edge.
+]
+
+See Also: #CreateSplitter, #SplitterPanel, #SetSplitterPosition, #SplitterPosition, #SetSplitterBehavior and #SplitterOrientation.
+End Rem
+Function SetSplitterOrientation( splitter:TSplitter, orientation% = -1 )
+	splitter.ChangeOrientation( orientation )
+EndFunction
+
+Rem
+bbdoc: Returns the orientation of the splitter.
+about: The two orientations available are (both of which can be combined with SPLIT_FLIPPED):
+
+[ @Orientation | @Description
+* SPLIT_VERTICAL | The splitter consists of a main left panel with a side-pane along the right edge.
+* SPLIT_HORIZONTAL | The splitter consists of a main top panel with a side-pane along the bottom edge.
+* SPLIT_VERTICAL ~| SPLIT_FLIPPED | The splitter consists of a main right panel with a side-pane along the left edge.
+* SPLIT_HORIZONTAL ~| SPLIT_FLIPPED | The splitter consists of a main bottom with a side-pane along the top edge.
+]
+
+See Also: #CreateSplitter, #SplitterPanel, #SetSplitterPosition, #SplitterPosition, #SetSplitterBehavior and #SetSplitterOrientation.
+End Rem
+Function SplitterOrientation:Int( splitter:TSplitter )
+	Return splitter.GetOrientation()
+EndFunction
+
+Const SPLIT_RESIZABLE% = %1, SPLIT_LIMITPANESIZE% = %10, SPLIT_CANFLIP% = %100, SPLIT_CANORIENTATE% = %1000, SPLIT_CLICKTOTOGGLE% = %100000, SPLIT_ALL% = -1
+
+Rem
+bbdoc: Sets the behavior of a splitter.
+about: Any combination of the following are available:
+
+[ @{Behavior Flag} | @Description
+* 0 | The splitter does none of the actions listed below.
+* SPLIT_RESIZABLE | The splitter can be resized by dragging.
+* SPLIT_LIMITPANESIZE | The splitter side-pane is not allowed to take up more than half the splitted dimensions.
+* SPLIT_CANFLIP | The splitter can switch between opposite edges by dragging to the edge.
+* SPLIT_CANORIENTATE | The splitter can switch between vertical and horizontal modes by dragging to right/bottom edges.
+* SPLIT_CLICKTOTOGGLE | The splitter will hide/show when the drag-bar is clicked.
+* SPLIT_ALL | A shorthand flag for representing all of the above.
+]
+
+The default behavior of a splitter is SPLIT_ALL&~~SPLIT_LIMITPANESIZE (i.e. everything but SPLIT_LIMITPANESIZE).
+
+See Also: #CreateSplitter, #SplitterPanel, #SplitterPosition, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
+End Rem
+Function SetSplitterBehavior( splitter:TSplitter, flags%=SPLIT_ALL )
+	splitter.SetBehavior( flags )
+EndFunction
+
+Rem
+bbdoc: Returns the value previously set using #SetSplitterBehavior.
+returns: An integer composed of a combination of bitwise flags that describe the behavior of the splitter.
+about: See #SetSplitterBehavior for more information.
+End Rem
+Function SplitterBehavior:Int( splitter:TSplitter )
+	Return splitter.GetBehavior()
+EndFunction
+
+
+Type TSplitter Extends TProxyGadget
+	
+	Const JUMP% = 200
+	
+								'	SPLITPANEL_MAIN                                          SPLITPANEL_SIDEPANE                                       SPLITPANEL_HANDLE
+	Global intOrientationLocks%[][][] =	[[	[EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED],[EDGE_ALIGNED, EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED],[EDGE_ALIGNED, EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED]	], ..	'SPLIT_HORIZONTAL
+								 [	[EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED],[EDGE_CENTERED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED],[EDGE_CENTERED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED]	], .. 'SPLIT_VERTICAL
+								 [	[EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED],[EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_CENTERED],[EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_CENTERED]	], ..	'SPLIT_HORIZONTAL|SPLIT_FLIPPED
+								 [	[EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED],[EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED, EDGE_ALIGNED],[EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED, EDGE_ALIGNED]	]]	'SPLIT_VERTICAL|SPLIT_FLIPPED
+	
+	Field strToggleTooltip$ = "Click to toggle!"
+	
+	Field intOrientation%, intMinPanelSpace% = 0, intSavePanelSpace% = 220, intBehavior% = 0, intGutterSize%
+	Field intPanelSpace% = intMinPanelSpace, intMouseDown%[2], intHasMoved% = False, intShouldUpdate% = False
+	
+	Field pnlPanes:TGadget[]
+	Field pnlSplitHandle:TGadget, divSplitHandle1:TGadget, divSplitHandle2:TGadget
+	Field gadParent:TGadget
+	
+	Field pixHandle:TPixmap[] = [TPixmap(Null), TPixmap(Null)]
+	
+	Method Create:TSplitter( pX%, pY%, pW%, pH%, pParent:TGadget, pOrientation% = SPLIT_VERTICAL, pHandleSize% = 10 )
+		
+		gadParent = CreatePanel(pX, pY, pW, pH, pParent);SetProxy( gadParent )
+		
+		intGutterSize = Max(pHandleSize, 4)
+		DrawHandle();DrawPanes();ChangeOrientation(pOrientation)
+		
+		SetBehavior(SPLIT_ALL&~SPLIT_LIMITPANESIZE)
+		
+		AddHook EmitEventHook, eventHandler, Self, -1
+		
+		Return Self
+		
+	EndMethod
+	
+	'Interface
+	
+	Method GetOrientation:Int()
+		Return intOrientation
+	EndMethod
+	
+	Method SetOrientation(pOrientation%)
+		ChangeOrientation(pOrientation)
+	EndMethod
+	
+	Method SetBehavior( pBehavior% )
+		intBehavior = pBehavior
+		If (intBehavior&SPLIT_CLICKTOTOGGLE) Then
+			If strToggleTooltip Then SetGadgetToolTip(pnlSplitHandle,strToggleTooltip)
+		Else
+			If strToggleTooltip Then SetGadgetToolTip(pnlSplitHandle,"")
+		EndIf
+	EndMethod
+	
+	Method GetBehavior%()
+		Return intBehavior
+	EndMethod
+	
+	Method GetPanel:TGadget(pPane%)
+		Return pnlPanes[pPane]
+	EndMethod
+	
+	Method GetPanelSpace%(pPane%)
+			Select pPane
+				Case SPLITPANEL_SIDEPANE
+					Return intPanelSpace
+				Case SPLITPANEL_MAIN
+					If intOrientation&SPLIT_VERTICAL Then
+						Return (ClientWidth()-intPanelSpace-intGutterSize)
+					Else
+						Return (ClientHeight()-intPanelSpace-intGutterSize)
+					EndIf
+			EndSelect
+	EndMethod
+	
+	Method SetPanelSpace( pPanelSpace%, flgSave% = True )
+		
+		Local tmpOldPanelSpace% = intPanelSpace
+		
+		If (intBehavior & SPLIT_LIMITPANESIZE) Then
+			pPanelSpace = Min(pPanelSpace, [ClientHeight(), ClientWidth()][intOrientation&SPLIT_VERTICAL] Shr 1)
+		EndIf
+		
+		pPanelSpace = Max(pPanelSpace, intMinPanelSpace)
+		
+		intPanelSpace = pPanelSpace
+		If GetPanelSpace(SPLITPANEL_MAIN) < intMinPanelSpace Then intPanelSpace = tmpOldPanelSpace
+		
+		If flgSave And intPanelSpace > Min(intGutterSize,intMinPanelSpace) Then intSavePanelSpace = intPanelSpace
+		
+		DrawHandle();DrawPanes()
+		
+	EndMethod
+	
+	'Proxy Gadget Methods
+	
+	Method CleanUp()
+		RemoveHook EmitEventHook, eventHandler, Self
+		gadParent = Null
+		Super.CleanUp()
+	EndMethod
+	
+	Method SetTooltip%( pTooltip$ )
+		strToggleTooltip = ""
+		divSplitHandle1.SetTooltip( pTooltip )
+		divSplitHandle2.SetTooltip( pTooltip )
+		Return pnlSplitHandle.SetTooltip( pTooltip )
+	EndMethod
+	
+	Method GetTooltip$()
+		Return pnlSplitHandle.GetTooltip()
+	EndMethod
+	
+	Method SetTextColor%( pRed%, pGreen%, pBlue%)
+		pixHandle[0] = MakeColourHandlePixmap( pRed, pGreen, pBlue, intGutterSize )
+		If intOrientation & SPLIT_VERTICAL Then pixHandle[0] = RotatePixmap(pixHandle[0])
+		pixHandle[1] = BrightenPixmap(pixHandle[0])
+		HideGadget(divSplitHandle1);HideGadget(divSplitHandle2)
+		SetPanelPixmap(pnlSplitHandle, pixHandle[0])
+	EndMethod
+	
+	Method SetColor%( pRed%, pGreen%, pBlue%)
+		Return SetPanelColor( pnlSplitHandle, pRed, pGreen, pBlue )
+	EndMethod
+	
+	Method SetSensitivity%(pSensitivity%)
+		Return 0
+	EndMethod
+	
+	Method GetSensitivity%()
+		Return 0
+	EndMethod
+	
+	'Internal Methods
+	
+	Method ReapplyLocks()
+		Local tmpLocks%[][] = intOrientationLocks[intOrientation]
+		If pnlPanes And pnlPanes.length > 1 Then
+			SetGadgetLayout( pnlPanes[SPLITPANEL_MAIN], tmpLocks[SPLITPANEL_MAIN][0], tmpLocks[SPLITPANEL_MAIN][1], tmpLocks[SPLITPANEL_MAIN][2], tmpLocks[SPLITPANEL_MAIN][3] )
+			SetGadgetLayout( pnlPanes[SPLITPANEL_SIDEPANE], tmpLocks[SPLITPANEL_SIDEPANE][0], tmpLocks[SPLITPANEL_SIDEPANE][1], tmpLocks[SPLITPANEL_SIDEPANE][2], tmpLocks[SPLITPANEL_SIDEPANE][3] )
+		EndIf
+		If pnlSplitHandle Then SetGadgetLayout( pnlSplitHandle, tmpLocks[SPLITPANEL_HANDLE][0], tmpLocks[SPLITPANEL_HANDLE][1], tmpLocks[SPLITPANEL_HANDLE][2], tmpLocks[SPLITPANEL_HANDLE][3] )
+	EndMethod
+	
+	Const SPLITSIDE_LEFT% = 0, SPLITSIDE_RIGHT% = 1, SPLITSIDE_TOP% = 0, SPLITSIDE_BOTTOM% = 1
+	Global intSideToPanelMapping%[][] = 	[[	SPLITPANEL_MAIN, SPLITPANEL_SIDEPANE	], ..	'SPLIT_HORIZONTAL
+								 [	SPLITPANEL_MAIN, SPLITPANEL_SIDEPANE	], .. 'SPLIT_VERTICAL
+								 [	SPLITPANEL_SIDEPANE, SPLITPANEL_MAIN	], ..	'SPLIT_HORIZONTAL|SPLIT_FLIPPED
+								 [	SPLITPANEL_SIDEPANE, SPLITPANEL_MAIN	]]	'SPLIT_VERTICAL|SPLIT_FLIPPED
+	
+	Method GetSideSpace%( pSide% )
+		Return GetPanelSpace(intSideToPanelMapping[intOrientation][pSide])
+	EndMethod
+	
+	Method DrawHandle()
+	
+		Local tmpDimensions%[]	'0: X, 1: Y, 2: W, 3: H
+		
+		Select intOrientation&SPLIT_VERTICAL
+		
+			Case SPLIT_HORIZONTAL;tmpDimensions = [0, GetSideSpace(SPLITSIDE_TOP), ClientWidth(), intGutterSize]
+			Case SPLIT_VERTICAL;tmpDimensions = [GetSideSpace(SPLITSIDE_LEFT), 0, intGutterSize, ClientHeight()]
+			
+		EndSelect
+		
+		If pnlSplitHandle Then
+			SetGadgetShape(pnlSplitHandle, tmpDimensions[0], tmpDimensions[1], tmpDimensions[2], tmpDimensions[3])
+			Select intOrientation&SPLIT_VERTICAL
+				Case SPLIT_HORIZONTAL
+					SetGadgetShape( divSplitHandle1,0,Ceil(tmpDimensions[3]/2.0)-2,tmpDimensions[2],2 )
+					SetGadgetShape( divSplitHandle2,0,Ceil(tmpDimensions[3]/2.0),tmpDimensions[2],2 )
+				Case SPLIT_VERTICAL
+					SetGadgetShape( divSplitHandle1,Ceil(tmpDimensions[2]/2.0)-2,0,2,tmpDimensions[3] )
+					SetGadgetShape( divSplitHandle2,Ceil(tmpDimensions[2]/2.0),0,2,tmpDimensions[3] )
+			EndSelect
+			If pixHandle[0] Then
+				HideGadget(divSplitHandle1)
+				HideGadget(divSplitHandle2)
+			Else
+				ShowGadget(divSplitHandle1)
+				ShowGadget(divSplitHandle2)
+			EndIf
+		Else
+			pnlSplitHandle = CreatePanel(tmpDimensions[0], tmpDimensions[1], tmpDimensions[2], tmpDimensions[3], gadParent, PANEL_ACTIVE)
+			
+			SetPanelPixmap( pnlSplitHandle, pixHandle[0]);SetGadgetToolTip(pnlSplitHandle,strToggleTooltip)
+			
+			Select intOrientation&SPLIT_VERTICAL
+				Case SPLIT_HORIZONTAL
+					divSplitHandle1 = CreateLabel("",0,Ceil(tmpDimensions[3]/2.0)-2,tmpDimensions[2],2,pnlSplitHandle,LABEL_SEPARATOR)
+					divSplitHandle2 = CreateLabel("",0,Ceil(tmpDimensions[3]/2.0),tmpDimensions[2],2,pnlSplitHandle,LABEL_SEPARATOR)
+				Case SPLIT_VERTICAL
+					divSplitHandle1 = CreateLabel("",Ceil(tmpDimensions[2]/2.0)-2,0,2,tmpDimensions[3],pnlSplitHandle,LABEL_SEPARATOR)
+					divSplitHandle2 = CreateLabel("",Ceil(tmpDimensions[2]/2.0),0,2,tmpDimensions[3],pnlSplitHandle,LABEL_SEPARATOR)
+			EndSelect
+			SetGadgetSensitivity(divSplitHandle1,SENSITIZE_MOUSE);SetGadgetSensitivity(divSplitHandle2,SENSITIZE_MOUSE)
+			
+			?Win32
+			DisableGadget( divSplitHandle1 );DisableGadget( divSplitHandle2 )
+			?
+			
+			SetGadgetToolTip( divSplitHandle1, strToggleTooltip );SetGadgetToolTip( divSplitHandle2, strToggleTooltip )
+			SetGadgetLayout( divSplitHandle1, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED )
+			SetGadgetLayout( divSplitHandle2, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED )
+			If pixHandle[0] Then HideGadget(divSplitHandle1);HideGadget(divSplitHandle2)
+			
+		EndIf
+	
+	EndMethod
+	
+	Method DrawPanes()
+	
+		Local tmpDimensions%[][]	'0: X, 1: Y, 2: W, 3: H
+		
+		Select intOrientation&SPLIT_VERTICAL
+			Case SPLIT_HORIZONTAL
+				tmpDimensions = [[0, 0, ClientWidth(), GetSideSpace(SPLITSIDE_TOP)], [0, GetSideSpace(SPLITSIDE_TOP)+intGutterSize, ClientWidth(), GetSideSpace(SPLITSIDE_BOTTOM)]]
+			Case SPLIT_VERTICAL
+				tmpDimensions = [[0,0,GetSideSpace(SPLITSIDE_LEFT),ClientHeight()], [GetSideSpace(SPLITSIDE_LEFT)+intGutterSize,0,GetSideSpace(SPLITSIDE_RIGHT),ClientHeight()]]
+		EndSelect
+		
+		If intOrientation & SPLIT_FLIPPED Then tmpDimensions = [tmpDimensions[1],tmpDimensions[0]]
+		
+		If pnlPanes.length <> 2 Then
+			pnlPanes = [CreatePanel(0,0,1,1,gadParent,0), CreatePanel(0,0,1,1,gadParent,0)]
+			ReapplyLocks()
+		EndIf
+		
+		SetGadgetShape(pnlPanes[SPLITPANEL_MAIN], tmpDimensions[SPLITPANEL_MAIN][0], tmpDimensions[SPLITPANEL_MAIN][1], tmpDimensions[SPLITPANEL_MAIN][2], tmpDimensions[SPLITPANEL_MAIN][3])
+		SetGadgetShape(pnlPanes[SPLITPANEL_SIDEPANE], tmpDimensions[SPLITPANEL_SIDEPANE][0], tmpDimensions[SPLITPANEL_SIDEPANE][1], tmpDimensions[SPLITPANEL_SIDEPANE][2], tmpDimensions[SPLITPANEL_SIDEPANE][3])
+	
+	EndMethod
+	
+	Method ChangeOrientation(pOrientation% = -1)
+		If pOrientation = intOrientation Then Return
+		If pOrientation < 0 Then
+			intOrientation:~SPLIT_FLIPPED
+		Else
+			If pixHandle[0] And intOrientation&SPLIT_VERTICAL <> pOrientation&SPLIT_VERTICAL Then
+				pixHandle[0] = RotatePixmap(pixHandle[0]);pixHandle[1] = RotatePixmap(pixHandle[1])
+			EndIf
+			intOrientation = pOrientation
+		EndIf
+		SetPanelPixmap(pnlSplitHandle, pixHandle[0]);DrawHandle();DrawPanes();ReapplyLocks();RedrawGadget(gadParent)
+	EndMethod
+	
+	Method Toggle()
+		If intPanelSpace > intMinPanelSpace Then SetPanelSpace( intMinPanelSpace ) Else SetPanelSpace( intSavePanelSpace )
+	EndMethod
+	
+	Method eventHook:Object( pID%, pData:Object )
+		
+		Local tmpEvent:TEvent = TEvent(pData)
+		If (Not tmpEvent) Or (Not TGadget(tmpEvent.source)) Then Return pData
+		
+		Select tmpEvent.source
+			
+			Case pnlSplitHandle, divSplitHandle1, divSplitHandle2
+				
+				If (tmpEvent.source = divSplitHandle1) Or (tmpEvent.source = divSplitHandle2) Then
+					tmpEvent.x:+GadgetX(TGadget(tmpEvent.source))
+					tmpEvent.y:+GadgetY(TGadget(tmpEvent.source))
+					tmpEvent.source = pnlSplitHandle
+				EndIf
+				
+				Select tmpEvent.id
+					
+					Case EVENT_MOUSEDOWN
+						
+						If (tmpEvent.data <> MOUSE_LEFT) Then Return Null
+						intMouseDown = [tmpEvent.x, tmpEvent.y]
+						intHasMoved = False
+						
+					Case EVENT_MOUSEMOVE
+						
+						intHasMoved = True
+						
+						If tmpEvent.data Then
+							
+							If intMouseDown Or (tmpEvent.data = MOUSE_LEFT And intShouldUpdate) Then
+								
+								'Update our mouse pointer and re-set our drag-point (if needed).
+								ShowDragPointer()
+								If intShouldUpdate Or Not intMouseDown Then
+									intMouseDown = [tmpEvent.x,tmpEvent.y]
+									intShouldUpdate = False
+								EndIf
+								
+								'New values that are updated once everything has been checked
+								Local tmpOrientation% = GetOrientation(), tmpPanelSpace% = -1, tmpPanelSave% = False
+								
+								'New size of panel if resized with mouse cursor
+								Local tmpDraggedSpace% = -[tmpEvent.y-intMouseDown[1],tmpEvent.x-intMouseDown[0]][intOrientation&SPLIT_VERTICAL]
+								If tmpOrientation&SPLIT_FLIPPED Then tmpDraggedSpace:*-1
+								tmpDraggedSpace:+intPanelSpace
+								
+								'Update intPanelSpace if we can drag as any calls to GetPanelSpace() need to return an accurate value
+								If (intBehavior&SPLIT_RESIZABLE) And tmpDraggedSpace <> intPanelSpace Then
+									
+									'Simulate a snap-closed action for the splitter
+									If tmpDraggedSpace < intGutterSize Then tmpDraggedSpace = intMinPanelSpace
+									
+									tmpPanelSpace = tmpDraggedSpace
+									intPanelSpace = tmpDraggedSpace
+								EndIf
+								
+								'Limit the pane-size to half the client-area if SPLIT_LIMITPANESIZE is set.
+								If (intBehavior&SPLIT_LIMITPANESIZE) Then
+									Local tmpDimensions%[] = [ClientHeight(),ClientWidth()]
+									If GetPanelSpace(SPLITPANEL_SIDEPANE) > (tmpDimensions[(tmpOrientation&SPLIT_VERTICAL)])/2 Then
+										If (intBehavior&SPLIT_CANFLIP) Then
+											tmpOrientation:~SPLIT_FLIPPED
+											tmpPanelSpace = GetPanelSpace(SPLITPANEL_MAIN)
+										Else
+											tmpPanelSpace = (tmpDimensions[(tmpOrientation&SPLIT_VERTICAL)])/2
+										EndIf
+										tmpPanelSave = True
+									EndIf
+								EndIf
+								
+								'Update the splitter's orientation if needed.
+								If (intBehavior&(SPLIT_CANORIENTATE|SPLIT_CANFLIP)) Then
+									
+									'Drag test conditions
+									Local tmpLeftCond% = (GadgetX(pnlSplitHandle)+tmpEvent.x < 1)
+									Local tmpRightCond% = (GadgetX(pnlSplitHandle)+tmpEvent.x > ClientWidth()-intGutterSize)
+									Local tmpTopCond% = (GadgetY(pnlSplitHandle)+tmpEvent.y < 1)
+									Local tmpBottomCond% = (GadgetY(pnlSplitHandle)+tmpEvent.y > ClientHeight()-intGutterSize)
+									
+									Select True
+										Case (tmpRightCond And Not (tmpTopCond|tmpBottomCond)), (tmpLeftCond And Not (tmpTopCond|tmpBottomCond)), ..
+										     (tmpBottomCond And Not (tmpLeftCond|tmpRightCond)), (tmpTopCond And Not (tmpLeftCond|tmpRightCond))
+											If (intBehavior&SPLIT_CANFLIP) Or ((tmpLeftCond|tmpTopCond)=(tmpOrientation&SPLIT_FLIPPED)) Then
+												If (intBehavior&SPLIT_CANORIENTATE) Then
+													If (tmpLeftCond|tmpRightCond) Then tmpOrientation:|SPLIT_VERTICAL Else tmpOrientation:&~SPLIT_VERTICAL
+												Else
+													Select (tmpOrientation&SPLIT_VERTICAL)
+														Case SPLIT_VERTICAL;tmpTopCond = 0;tmpBottomCond = 0
+														Case SPLIT_HORIZONTAL;tmpLeftCond = 0;tmpRightCond = 0
+													EndSelect
+												EndIf
+												'Let's determine whether our side-panel should be flipped or not.
+												If (tmpLeftCond|tmpTopCond) Then tmpOrientation:|SPLIT_FLIPPED ElseIf (tmpRightCond|tmpBottomCond) Then tmpOrientation:&~SPLIT_FLIPPED
+												'If we are resizable and the orientation has changed, let's reset the side-pane size.
+												If (intBehavior&SPLIT_RESIZABLE) And (tmpOrientation <> intOrientation) Then tmpPanelSpace = intMinPanelSpace;tmpPanelSave = True
+											EndIf
+									EndSelect
+									
+								EndIf
+								
+								'Apply our newly calculated values to the splitter.
+								If (tmpOrientation <> GetOrientation()) Then
+									If (tmpOrientation&SPLIT_VERTICAL <> GetOrientation()&SPLIT_VERTICAL) Then
+										intMouseDown = Null
+										intShouldUpdate = True
+									EndIf
+									ChangeOrientation( tmpOrientation )
+									ShowActivePointer()
+								EndIf
+								
+								If tmpPanelSpace > -1 Then SetPanelSpace( tmpPanelSpace, tmpPanelSave )
+								
+							EndIf
+							
+						Else
+							
+							intMouseDown = Null
+							
+						EndIf
+						
+					Case EVENT_MOUSEUP
+						
+						If (intMouseDown And tmpEvent.data = MOUSE_LEFT) Then
+						
+							If Not intHasMoved Then
+								If (intBehavior&SPLIT_CLICKTOTOGGLE) Then Toggle()
+							Else
+								SetPanelSpace( intPanelSpace, True )
+							EndIf
+							
+							intMouseDown = Null
+							
+							ShowNormalPointer()
+							
+						EndIf
+						
+					Case EVENT_MOUSELEAVE
+						
+						If (intBehavior&(SPLIT_RESIZABLE|SPLIT_CLICKTOTOGGLE)) Then
+							SetPanelPixmap(pnlSplitHandle, pixHandle[0])
+						EndIf
+						
+						ShowNormalPointer()
+						
+					Case EVENT_MOUSEENTER
+						
+						If (intBehavior&(SPLIT_RESIZABLE|SPLIT_CLICKTOTOGGLE)) Then
+							SetPanelPixmap(pnlSplitHandle, pixHandle[1])
+						EndIf
+						
+						ShowActivePointer()
+				
+				EndSelect
+				
+			Case pnlPanes[SPLITPANEL_MAIN], pnlPanes[SPLITPANEL_SIDEPANE], gadParent
+				
+				'Don't show these events to the other hooks!
+				
+			Default
+			
+				Select tmpEvent.id
+					Case EVENT_WINDOWSIZE
+						If (intBehavior&SPLIT_RESIZABLE) And TGadget(tmpEvent.source).HasDescendant(gadParent) Then
+							Local tmpLimit% = [ClientHeight(),ClientWidth()][intOrientation&SPLIT_VERTICAL]
+							If (intBehavior&SPLIT_LIMITPANESIZE) Then tmpLimit:Shr 1 Else tmpLimit:-intGutterSize
+							If GetPanelSpace(SPLITPANEL_SIDEPANE) > tmpLimit Then SetPanelSpace( tmpLimit, True )
+						EndIf
+				EndSelect
+				
+				Return pData
+		EndSelect
+	
+	EndMethod	
+	
+	'Mouse Cursor
+	Function ShowNormalPointer()
+		SetPointer(POINTER_DEFAULT)
+	EndFunction
+	
+	Method ShowActivePointer()
+		If (intBehavior&SPLIT_RESIZABLE) Then
+			Select intOrientation&SPLIT_VERTICAL
+				Case SPLIT_HORIZONTAL;SetPointer(POINTER_SIZENS)
+				Case SPLIT_VERTICAL;SetPointer(POINTER_SIZEWE)
+			EndSelect
+		ElseIf (intBehavior&SPLIT_CLICKTOTOGGLE) Then
+			SetPointer(POINTER_HAND)
+		Else
+			SetPointer(POINTER_DEFAULT)
+		EndIf
+	EndMethod
+	
+	Method ShowDragPointer()
+		If (intBehavior&SPLIT_RESIZABLE) Then
+			Select intOrientation&SPLIT_VERTICAL
+				Case SPLIT_HORIZONTAL;SetPointer(POINTER_SIZENS)
+				Case SPLIT_VERTICAL;SetPointer(POINTER_SIZEWE)
+			EndSelect
+		ElseIf (intBehavior&(SPLIT_CANFLIP|SPLIT_CANORIENTATE))
+			SetPointer(POINTER_SIZEALL)
+		Else
+			SetPointer(POINTER_DEFAULT)
+		EndIf
+	EndMethod
+	
+	'Helper Functions
+	
+	Function eventHandler:Object( pID%, pData:Object, pContext:Object)
+		If TSplitter(pContext) Then Return TSplitter(pContext).eventHook( pID, pData ) Else Return pData
+	EndFunction
+	
+	Function RotatePixmap:TPixmap( pSrcPixmap:TPixmap )
+		Local tmpDestPixmap:TPixmap = CreatePixmap(pSrcPixmap.height, pSrcPixmap.width, pSrcPixmap.format)
+		For Local y% = 0 Until pSrcPixmap.height
+			For Local x% = 0 Until pSrcPixmap.width
+				WritePixel( tmpDestPixmap, y, x, ReadPixel(pSrcPixmap, x, y) )
+			Next
+		Next
+		Return tmpDestPixmap
+	EndFunction
+	
+	Function BrightenPixmap:TPixmap( pSrcPixmap:TPixmap, pBrightness# = 1.05 )
+		Local tmpDestPixmap:TPixmap = CreatePixmap(pSrcPixmap.width, pSrcPixmap.height, pSrcPixmap.format)
+		For Local y% = 0 Until pSrcPixmap.height
+			For Local x% = 0 Until pSrcPixmap.width
+				WritePixel( tmpDestPixmap, x, y, BrightenPixel(ReadPixel(pSrcPixmap, x, y), pBrightness) )
+			Next
+		Next
+		Return tmpDestPixmap
+	EndFunction
+	
+	Function BrightenPixel%( pARGB%, pBrightness# = 1.05 )
+		Local tmpHSV:TColorHSV = New TColorHSV.fromARGB(pARGB)
+		tmpHSV.v=Min(tmpHSV.v*pBrightness,1)
+		Return tmpHSV.toARGB()
+	EndFunction
+	
+	Function WhitenPixel%( pARGB%, pWhiteness# = 0.8 )
+		Local tmpHSV:TColorHSV = New TColorHSV.fromARGB(pARGB)
+		tmpHSV.s=Min(tmpHSV.s*pWhiteness,1)
+		Return tmpHSV.toARGB()	
+	EndFunction
+	
+	Function MakeColourHandlePixmap:TPixmap( pRed%, pGreen%, pBlue%, pWidth% )
+		Local tmpPixmap:TPixmap = CreatePixmap(1,pWidth,PF_RGB888)
+		Local tmpPixel% = (pRed Shl 16)|(pGreen Shl 8)|pBlue
+		For Local i% = 0 To pWidth/2
+			Local tmpCalculatedPixel% = BrightenPixel(tmpPixel,1.05^i)
+			WritePixel(tmpPixmap,0,i,tmpCalculatedPixel)
+			WritePixel(tmpPixmap,0,pWidth-1-i,tmpCalculatedPixel)
+		Next
+		Return tmpPixmap
+	EndFunction
+	
+EndType
+
+Private
+
+'Some type declarations from fredborg's pub.color module
+'http://www.blitzbasic.com/codearcs/codearcs.php?code=1749
+
+Type TColor
+	Method toARGB:Int() Abstract	
+End Type
+
+Type TColorHSV Extends TColor
+	
+	Field h:Float,s:Float,v:Float,a:Float=1.0
+	
+	Method toRGB:TColorRGB()
+
+		Local temph:Float = Self.h
+		Local temps:Float = Self.s
+		Local tempv:Float = Self.v
+	
+		Local rgb:TColorRGB = New TColorRGB
+	
+		If temph=>360.0 Or temph<0.0 Then temph = 0.0
+	
+		If temps = 0 Then
+			rgb.r = v
+			rgb.g = v
+			rgb.b = v
+		Else
+			temph = temph / 60.0
+			
+			Local i:Int   = Floor(temph)
+			Local f:Float = temph - i
+			Local p:Float = tempv * (1 - temps)
+			Local q:Float = tempv * (1 - temps * f)
+			Local t:Float = tempv * (1 - temps * (1 - f))
+
+			Select i
+				Case 0
+					rgb.r = v
+					rgb.g = t
+					rgb.b = p
+				Case 1
+					rgb.r = q
+					rgb.g = v
+					rgb.b = p
+				Case 2
+					rgb.r = p
+					rgb.g = v
+					rgb.b = t
+				Case 3
+					rgb.r = p
+					rgb.g = q
+					rgb.b = v
+				Case 4
+					rgb.r = t
+					rgb.g = p
+					rgb.b = v
+				Default
+					rgb.r = v
+					rgb.g = p
+					rgb.b = q
+			End Select		
+		EndIf
+
+		rgb.a = a
+
+		Return rgb
+	
+	EndMethod
+	
+	Function fromARGB:TColorHSV(argb:Int)
+		Return TColorRGB.fromARGB(argb).toHSV()
+	EndFunction
+	
+	Method toARGB:Int()
+		Return Self.toRGB().toARGB()
+	EndMethod
+	
+EndType
+
+Type TColorRGB Extends TColor
+
+	Field r:Float,g:Float,b:Float,a:Float=1.0
+	
+	Method toHSV:TColorHSV()
+		
+		Local tempr:Float = Min(1.0,Max(0.0,Self.r))
+		Local tempg:Float = Min(1.0,Max(0.0,Self.g))
+		Local tempb:Float = Min(1.0,Max(0.0,Self.b))
+
+		Local minVal:Float = Min(Min(tempr,tempg),tempb)
+		Local maxVal:Float = Max(Max(tempr,tempg),tempb)
+		
+		Local diff:Float = maxVal - minVal
+	
+		Local hsv:TColorHSV = New TColorHSV
+		hsv.v = maxVal
+	
+		If maxVal = 0.0 Then
+			hsv.s = 0.0
+			hsv.h = 0.0
+		Else
+			hsv.s = diff / maxVal
+	
+			If tempr = maxVal
+				hsv.h = (tempg - tempb) / diff
+			ElseIf tempg = maxVal
+				hsv.h = 2.0 + (tempb - tempr) / diff
+			Else
+				hsv.h = 4.0 + (tempr - tempg) / diff
+			EndIf
+	
+			hsv.h = hsv.h * 60.0
+			If hsv.h < 0 Then hsv.h = hsv.h + 360.0
+		EndIf
+
+		If hsv.h<  0.0 Then hsv.h = 0.0
+		If hsv.h>360.0 Then hsv.h = 0.0
+		
+		hsv.a = a
+		
+		Return hsv
+		
+	EndMethod
+
+	Function fromARGB:TColorRGB(argb:Int,alpha:Int=True)
+	
+		Local rgb:TColorRGB = New TColorRGB
+	
+		If alpha	
+			rgb.a = ((argb Shr 24) & $FF)/255.0
+		EndIf
+		
+		rgb.r = ((argb Shr 16) & $FF)/255.0
+		rgb.g = ((argb Shr 8) & $FF)/255.0
+		rgb.b = (argb & $FF)/255.0
+	
+		Return rgb
+		
+	EndFunction
+
+	Function fromBGR:TColorRGB(argb:Int)
+	
+		Local rgb:TColorRGB = New TColorRGB
+	
+		rgb.r = (argb & $000000FF)/255.0
+		rgb.g = ((argb Shr 8) & $000000FF)/255.0
+		rgb.b = ((argb Shr 16) & $000000FF)/255.0
+	
+		Return rgb
+		
+	EndFunction
+
+	Method toARGB:Int()
+		
+		Local tempr:Int = Min(255,Max(0,Int(Self.r*255)))
+		Local tempg:Int = Min(255,Max(0,Int(Self.g*255)))
+		Local tempb:Int = Min(255,Max(0,Int(Self.b*255)))
+		Local tempa:Int = Min(255,Max(0,Int(Self.a*255)))
+						
+		Return (tempa Shl 24) | (tempr Shl 16) | (tempg Shl 8) | tempb
+
+	EndMethod
+	
+EndType
+