Code archives/BlitzPlus Gui/Modified Splitter proxy gadget

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

Download source code

Modified Splitter proxy gadget by JoshK2010
Changes:

-Splitter handle is much narrower
-Removed lines on splitter handle
-Splitter will emit a window size event when resized. This is useful if any gadgets in the splitter panels need to be resized when the splitter changes.
SuperStrict

Import MaxGUI.MaxGUI


Private

Function GadgetWindow:TGadget(gadget:TGadget)
	While gadget
		If gadgetclass(gadget)=GADGET_WINDOW Return gadget
		gadget=gadgetgroup(gadget)
	Wend
EndFunction

Public

' 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$ = ""
	
	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% = 2 )
		
		gadParent = CreatePanel(pX, pY, pW, pH, pParent);SetProxy( gadParent )
		
		intGutterSize = 3'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 SetGadgetColor( pnlSplitHandle, pRed, pGreen, pBlue, True )
	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
								
								EmitEvent CreateEvent(EVENT_WINDOWSIZE,GadgetWindow(Self))
								
								'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

Comments

None.

Code Archives Forum