splitter.bmx 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. SuperStrict
  2. Import MaxGUI.MaxGUI
  3. ' TSplitter Proxy Gadget
  4. ' Author: Seb Hollington
  5. Rem
  6. bbdoc: Creates a gadget consisting of two panels separated by a draggable divider.
  7. 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
  8. (identified using SPLITPANEL_SIDEPANE) which is typically used to display additional information. Both of these panels are contained within a
  9. 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
  10. queried and altered using the #SplitterBehavior and #SetSplitterBehavior functions respectively.
  11. The size of the split handle is determined using the optional @pHandleSize parameter. The default size of 10 pixels should work well in most
  12. situations, and the minimum value that this can be is 4.
  13. After creating a splitter gadget, you can start adding gadgets to it by retrieving the appropriate panel with the #SplitterPanel command.
  14. The @TSplitter type instance can be used with most of the standard MaxGUI commands, allowing you to change the properties of the entire splitter
  15. gadget. There are, however, a few exceptions:
  16. #SetGadgetSensitivity and #GadgetSensitivity will have no effect on the splitter gadget. If you want to use active panels, create your own
  17. sub-panel within each splitter panel.
  18. #SetGadgetTooltip and #GadgetTooltip will set/retrieve a tooltip for when the user is hovering over the splitter handle/divider.
  19. #SetGadgetColor will modify the split handle/divider background color.
  20. See Also: #SplitterPanel, #SetSplitterPosition, #SplitterPosition, #SetSplitterBehavior, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
  21. End Rem
  22. Function CreateSplitter:TSplitter( pX%, pY%, pW%, pH%, pParent:TGadget, pOrientation% = SPLIT_VERTICAL, pHandleSize% = 10 )
  23. Return New TSplitter.Create( pX, pY, pW, pH, pParent, pOrientation, pHandleSize )
  24. EndFunction
  25. Const SPLITPANEL_MAIN% = 0, SPLITPANEL_SIDEPANE% = 1, SPLITPANEL_HANDLE% = 2
  26. Rem
  27. bbdoc: Retrieves either one of the two panels which make up a TSplitter gadget.
  28. about: This function is used to return a standard MaxGUI panel that you can add your gadgets to.
  29. The panels available are SPLITPANEL_MAIN and SPLITPANEL_SIDEPANE. See #CreateSplitter for more information
  30. about the differences between the two panels.
  31. See Also: #CreateSplitter, #SetSplitterPosition, #SplitterPosition, #SetSplitterBehavior, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
  32. End Rem
  33. Function SplitterPanel:TGadget( splitter:TSplitter, panel% = SPLITPANEL_MAIN )
  34. Return splitter.GetPanel(panel)
  35. EndFunction
  36. Rem
  37. bbdoc: Sets the position of the splitter (in pixels) from the edge of a TSplitter gadget.
  38. about: This function's most common use is to restore a split position previously returned by #SplitterPosition.
  39. The optional @save% parameter determines whether or not the position supplied is restored when the splitter returns from it's hidden state.
  40. In most circumstances, this should be left as #True.
  41. See Also: #CreateSplitter, #SplitterPanel, #SplitterPosition, #SetSplitterBehavior, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
  42. End Rem
  43. Function SetSplitterPosition( splitter:TSplitter, position%, save% = True )
  44. splitter.SetPanelSpace( position, save )
  45. EndFunction
  46. Rem
  47. bbdoc: Returns the position of the splitter (in pixels) from the edge of a TSplitter gadget.
  48. about: This function's most common use is probably for saving the current splitter position to restore at a later time using #SetSplitterPosition.
  49. See Also: #CreateSplitter, #SplitterPanel, #SetSplitterPosition, #SetSplitterBehavior, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
  50. End Rem
  51. Function SplitterPosition:Int( splitter:TSplitter )
  52. Return splitter.GetPanelSpace( SPLITPANEL_SIDEPANE )
  53. EndFunction
  54. Const SPLIT_HORIZONTAL% = 0, SPLIT_VERTICAL% = 1, SPLIT_FLIPPED% = 2
  55. Rem
  56. bbdoc: Sets the splitter orientation.
  57. about: The two orientations available are (both of which can be combined with SPLIT_FLIPPED):
  58. [ @Orientation | @Description
  59. * -1 | Toggles the SPLIT_FLIPPED flag.
  60. * SPLIT_VERTICAL | The splitter consists of a main left panel with a side-pane along the right edge.
  61. * SPLIT_HORIZONTAL | The splitter consists of a main top panel with a side-pane along the bottom edge.
  62. * SPLIT_VERTICAL ~| SPLIT_FLIPPED | The splitter consists of a main right panel with a side-pane along the left edge.
  63. * SPLIT_HORIZONTAL ~| SPLIT_FLIPPED | The splitter consists of a main bottom with a side-pane along the top edge.
  64. ]
  65. See Also: #CreateSplitter, #SplitterPanel, #SetSplitterPosition, #SplitterPosition, #SetSplitterBehavior and #SplitterOrientation.
  66. End Rem
  67. Function SetSplitterOrientation( splitter:TSplitter, orientation% = -1 )
  68. splitter.ChangeOrientation( orientation )
  69. EndFunction
  70. Rem
  71. bbdoc: Returns the orientation of the splitter.
  72. about: The two orientations available are (both of which can be combined with SPLIT_FLIPPED):
  73. [ @Orientation | @Description
  74. * SPLIT_VERTICAL | The splitter consists of a main left panel with a side-pane along the right edge.
  75. * SPLIT_HORIZONTAL | The splitter consists of a main top panel with a side-pane along the bottom edge.
  76. * SPLIT_VERTICAL ~| SPLIT_FLIPPED | The splitter consists of a main right panel with a side-pane along the left edge.
  77. * SPLIT_HORIZONTAL ~| SPLIT_FLIPPED | The splitter consists of a main bottom with a side-pane along the top edge.
  78. ]
  79. See Also: #CreateSplitter, #SplitterPanel, #SetSplitterPosition, #SplitterPosition, #SetSplitterBehavior and #SetSplitterOrientation.
  80. End Rem
  81. Function SplitterOrientation:Int( splitter:TSplitter )
  82. Return splitter.GetOrientation()
  83. EndFunction
  84. Const SPLIT_RESIZABLE% = %1, SPLIT_LIMITPANESIZE% = %10, SPLIT_CANFLIP% = %100, SPLIT_CANORIENTATE% = %1000, SPLIT_CLICKTOTOGGLE% = %100000, SPLIT_ALL% = -1
  85. Rem
  86. bbdoc: Sets the behavior of a splitter.
  87. about: Any combination of the following are available:
  88. [ @{Behavior Flag} | @Description
  89. * 0 | The splitter does none of the actions listed below.
  90. * SPLIT_RESIZABLE | The splitter can be resized by dragging.
  91. * SPLIT_LIMITPANESIZE | The splitter side-pane is not allowed to take up more than half the splitted dimensions.
  92. * SPLIT_CANFLIP | The splitter can switch between opposite edges by dragging to the edge.
  93. * SPLIT_CANORIENTATE | The splitter can switch between vertical and horizontal modes by dragging to right/bottom edges.
  94. * SPLIT_CLICKTOTOGGLE | The splitter will hide/show when the drag-bar is clicked.
  95. * SPLIT_ALL | A shorthand flag for representing all of the above.
  96. ]
  97. The default behavior of a splitter is SPLIT_ALL&~~SPLIT_LIMITPANESIZE (i.e. everything but SPLIT_LIMITPANESIZE).
  98. See Also: #CreateSplitter, #SplitterPanel, #SplitterPosition, #SplitterBehavior, #SetSplitterOrientation and #SplitterOrientation.
  99. End Rem
  100. Function SetSplitterBehavior( splitter:TSplitter, flags%=SPLIT_ALL )
  101. splitter.SetBehavior( flags )
  102. EndFunction
  103. Rem
  104. bbdoc: Returns the value previously set using #SetSplitterBehavior.
  105. returns: An integer composed of a combination of bitwise flags that describe the behavior of the splitter.
  106. about: See #SetSplitterBehavior for more information.
  107. End Rem
  108. Function SplitterBehavior:Int( splitter:TSplitter )
  109. Return splitter.GetBehavior()
  110. EndFunction
  111. Type TSplitter Extends TProxyGadget
  112. Const JUMP% = 200
  113. ' SPLITPANEL_MAIN SPLITPANEL_SIDEPANE SPLITPANEL_HANDLE
  114. 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
  115. [ [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
  116. [ [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
  117. [ [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
  118. Field strToggleTooltip$ = "Click to toggle!"
  119. Field intOrientation%, intMinPanelSpace% = 0, intSavePanelSpace% = 220, intBehavior% = 0, intGutterSize%
  120. Field intPanelSpace% = intMinPanelSpace, intMouseDown%[2], intHasMoved% = False, intShouldUpdate% = False
  121. Field pnlPanes:TGadget[]
  122. Field pnlSplitHandle:TGadget, divSplitHandle1:TGadget, divSplitHandle2:TGadget
  123. Field gadParent:TGadget
  124. Field pixHandle:TPixmap[] = [TPixmap(Null), TPixmap(Null)]
  125. Method Create:TSplitter( pX%, pY%, pW%, pH%, pParent:TGadget, pOrientation% = SPLIT_VERTICAL, pHandleSize% = 10 )
  126. gadParent = CreatePanel(pX, pY, pW, pH, pParent);SetProxy( gadParent )
  127. intGutterSize = Max(pHandleSize, 4)
  128. DrawHandle();DrawPanes();ChangeOrientation(pOrientation)
  129. SetBehavior(SPLIT_ALL&~SPLIT_LIMITPANESIZE)
  130. AddHook EmitEventHook, eventHandler, Self, -1
  131. Return Self
  132. EndMethod
  133. 'Interface
  134. Method GetOrientation:Int()
  135. Return intOrientation
  136. EndMethod
  137. Method SetOrientation(pOrientation%)
  138. ChangeOrientation(pOrientation)
  139. EndMethod
  140. Method SetBehavior( pBehavior% )
  141. intBehavior = pBehavior
  142. If (intBehavior&SPLIT_CLICKTOTOGGLE) Then
  143. If strToggleTooltip Then SetGadgetToolTip(pnlSplitHandle,strToggleTooltip)
  144. Else
  145. If strToggleTooltip Then SetGadgetToolTip(pnlSplitHandle,"")
  146. EndIf
  147. EndMethod
  148. Method GetBehavior%()
  149. Return intBehavior
  150. EndMethod
  151. Method GetPanel:TGadget(pPane%)
  152. Return pnlPanes[pPane]
  153. EndMethod
  154. Method GetPanelSpace%(pPane%)
  155. Select pPane
  156. Case SPLITPANEL_SIDEPANE
  157. Return intPanelSpace
  158. Case SPLITPANEL_MAIN
  159. If intOrientation&SPLIT_VERTICAL Then
  160. Return (ClientWidth()-intPanelSpace-intGutterSize)
  161. Else
  162. Return (ClientHeight()-intPanelSpace-intGutterSize)
  163. EndIf
  164. EndSelect
  165. EndMethod
  166. Method SetPanelSpace( pPanelSpace%, flgSave% = True )
  167. Local tmpOldPanelSpace% = intPanelSpace
  168. If (intBehavior & SPLIT_LIMITPANESIZE) Then
  169. pPanelSpace = Min(pPanelSpace, [ClientHeight(), ClientWidth()][intOrientation&SPLIT_VERTICAL] Shr 1)
  170. EndIf
  171. pPanelSpace = Max(pPanelSpace, intMinPanelSpace)
  172. intPanelSpace = pPanelSpace
  173. If GetPanelSpace(SPLITPANEL_MAIN) < intMinPanelSpace Then intPanelSpace = tmpOldPanelSpace
  174. If flgSave And intPanelSpace > Min(intGutterSize,intMinPanelSpace) Then intSavePanelSpace = intPanelSpace
  175. DrawHandle();DrawPanes()
  176. EndMethod
  177. 'Proxy Gadget Methods
  178. Method CleanUp()
  179. RemoveHook EmitEventHook, eventHandler, Self
  180. gadParent = Null
  181. Super.CleanUp()
  182. EndMethod
  183. Method SetTooltip%( pTooltip$ )
  184. strToggleTooltip = ""
  185. divSplitHandle1.SetTooltip( pTooltip )
  186. divSplitHandle2.SetTooltip( pTooltip )
  187. Return pnlSplitHandle.SetTooltip( pTooltip )
  188. EndMethod
  189. Method GetTooltip$()
  190. Return pnlSplitHandle.GetTooltip()
  191. EndMethod
  192. Method SetTextColor%( pRed%, pGreen%, pBlue%)
  193. pixHandle[0] = MakeColourHandlePixmap( pRed, pGreen, pBlue, intGutterSize )
  194. If intOrientation & SPLIT_VERTICAL Then pixHandle[0] = RotatePixmap(pixHandle[0])
  195. pixHandle[1] = BrightenPixmap(pixHandle[0])
  196. HideGadget(divSplitHandle1);HideGadget(divSplitHandle2)
  197. SetPanelPixmap(pnlSplitHandle, pixHandle[0])
  198. EndMethod
  199. Method SetColor%( pRed%, pGreen%, pBlue%)
  200. Return SetPanelColor( pnlSplitHandle, pRed, pGreen, pBlue )
  201. EndMethod
  202. Method SetSensitivity%(pSensitivity%)
  203. Return 0
  204. EndMethod
  205. Method GetSensitivity%()
  206. Return 0
  207. EndMethod
  208. 'Internal Methods
  209. Method ReapplyLocks()
  210. Local tmpLocks%[][] = intOrientationLocks[intOrientation]
  211. If pnlPanes And pnlPanes.length > 1 Then
  212. SetGadgetLayout( pnlPanes[SPLITPANEL_MAIN], tmpLocks[SPLITPANEL_MAIN][0], tmpLocks[SPLITPANEL_MAIN][1], tmpLocks[SPLITPANEL_MAIN][2], tmpLocks[SPLITPANEL_MAIN][3] )
  213. SetGadgetLayout( pnlPanes[SPLITPANEL_SIDEPANE], tmpLocks[SPLITPANEL_SIDEPANE][0], tmpLocks[SPLITPANEL_SIDEPANE][1], tmpLocks[SPLITPANEL_SIDEPANE][2], tmpLocks[SPLITPANEL_SIDEPANE][3] )
  214. EndIf
  215. If pnlSplitHandle Then SetGadgetLayout( pnlSplitHandle, tmpLocks[SPLITPANEL_HANDLE][0], tmpLocks[SPLITPANEL_HANDLE][1], tmpLocks[SPLITPANEL_HANDLE][2], tmpLocks[SPLITPANEL_HANDLE][3] )
  216. EndMethod
  217. Const SPLITSIDE_LEFT% = 0, SPLITSIDE_RIGHT% = 1, SPLITSIDE_TOP% = 0, SPLITSIDE_BOTTOM% = 1
  218. Global intSideToPanelMapping%[][] = [[ SPLITPANEL_MAIN, SPLITPANEL_SIDEPANE ], .. 'SPLIT_HORIZONTAL
  219. [ SPLITPANEL_MAIN, SPLITPANEL_SIDEPANE ], .. 'SPLIT_VERTICAL
  220. [ SPLITPANEL_SIDEPANE, SPLITPANEL_MAIN ], .. 'SPLIT_HORIZONTAL|SPLIT_FLIPPED
  221. [ SPLITPANEL_SIDEPANE, SPLITPANEL_MAIN ]] 'SPLIT_VERTICAL|SPLIT_FLIPPED
  222. Method GetSideSpace%( pSide% )
  223. Return GetPanelSpace(intSideToPanelMapping[intOrientation][pSide])
  224. EndMethod
  225. Method DrawHandle()
  226. Local tmpDimensions%[] '0: X, 1: Y, 2: W, 3: H
  227. Select intOrientation&SPLIT_VERTICAL
  228. Case SPLIT_HORIZONTAL;tmpDimensions = [0, GetSideSpace(SPLITSIDE_TOP), ClientWidth(), intGutterSize]
  229. Case SPLIT_VERTICAL;tmpDimensions = [GetSideSpace(SPLITSIDE_LEFT), 0, intGutterSize, ClientHeight()]
  230. EndSelect
  231. If pnlSplitHandle Then
  232. SetGadgetShape(pnlSplitHandle, tmpDimensions[0], tmpDimensions[1], tmpDimensions[2], tmpDimensions[3])
  233. Select intOrientation&SPLIT_VERTICAL
  234. Case SPLIT_HORIZONTAL
  235. SetGadgetShape( divSplitHandle1,0,Ceil(tmpDimensions[3]/2.0)-2,tmpDimensions[2],2 )
  236. SetGadgetShape( divSplitHandle2,0,Ceil(tmpDimensions[3]/2.0),tmpDimensions[2],2 )
  237. Case SPLIT_VERTICAL
  238. SetGadgetShape( divSplitHandle1,Ceil(tmpDimensions[2]/2.0)-2,0,2,tmpDimensions[3] )
  239. SetGadgetShape( divSplitHandle2,Ceil(tmpDimensions[2]/2.0),0,2,tmpDimensions[3] )
  240. EndSelect
  241. If pixHandle[0] Then
  242. HideGadget(divSplitHandle1)
  243. HideGadget(divSplitHandle2)
  244. Else
  245. ShowGadget(divSplitHandle1)
  246. ShowGadget(divSplitHandle2)
  247. EndIf
  248. Else
  249. pnlSplitHandle = CreatePanel(tmpDimensions[0], tmpDimensions[1], tmpDimensions[2], tmpDimensions[3], gadParent, PANEL_ACTIVE)
  250. SetPanelPixmap( pnlSplitHandle, pixHandle[0]);SetGadgetToolTip(pnlSplitHandle,strToggleTooltip)
  251. Select intOrientation&SPLIT_VERTICAL
  252. Case SPLIT_HORIZONTAL
  253. divSplitHandle1 = CreateLabel("",0,Ceil(tmpDimensions[3]/2.0)-2,tmpDimensions[2],2,pnlSplitHandle,LABEL_SEPARATOR)
  254. divSplitHandle2 = CreateLabel("",0,Ceil(tmpDimensions[3]/2.0),tmpDimensions[2],2,pnlSplitHandle,LABEL_SEPARATOR)
  255. Case SPLIT_VERTICAL
  256. divSplitHandle1 = CreateLabel("",Ceil(tmpDimensions[2]/2.0)-2,0,2,tmpDimensions[3],pnlSplitHandle,LABEL_SEPARATOR)
  257. divSplitHandle2 = CreateLabel("",Ceil(tmpDimensions[2]/2.0),0,2,tmpDimensions[3],pnlSplitHandle,LABEL_SEPARATOR)
  258. EndSelect
  259. SetGadgetSensitivity(divSplitHandle1,SENSITIZE_MOUSE);SetGadgetSensitivity(divSplitHandle2,SENSITIZE_MOUSE)
  260. ?Win32
  261. DisableGadget( divSplitHandle1 );DisableGadget( divSplitHandle2 )
  262. ?
  263. SetGadgetToolTip( divSplitHandle1, strToggleTooltip );SetGadgetToolTip( divSplitHandle2, strToggleTooltip )
  264. SetGadgetLayout( divSplitHandle1, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED )
  265. SetGadgetLayout( divSplitHandle2, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED )
  266. If pixHandle[0] Then HideGadget(divSplitHandle1);HideGadget(divSplitHandle2)
  267. EndIf
  268. EndMethod
  269. Method DrawPanes()
  270. Local tmpDimensions%[][] '0: X, 1: Y, 2: W, 3: H
  271. Select intOrientation&SPLIT_VERTICAL
  272. Case SPLIT_HORIZONTAL
  273. tmpDimensions = [[0, 0, ClientWidth(), GetSideSpace(SPLITSIDE_TOP)], [0, GetSideSpace(SPLITSIDE_TOP)+intGutterSize, ClientWidth(), GetSideSpace(SPLITSIDE_BOTTOM)]]
  274. Case SPLIT_VERTICAL
  275. tmpDimensions = [[0,0,GetSideSpace(SPLITSIDE_LEFT),ClientHeight()], [GetSideSpace(SPLITSIDE_LEFT)+intGutterSize,0,GetSideSpace(SPLITSIDE_RIGHT),ClientHeight()]]
  276. EndSelect
  277. If intOrientation & SPLIT_FLIPPED Then tmpDimensions = [tmpDimensions[1],tmpDimensions[0]]
  278. If pnlPanes.length <> 2 Then
  279. pnlPanes = [CreatePanel(0,0,1,1,gadParent,0), CreatePanel(0,0,1,1,gadParent,0)]
  280. ReapplyLocks()
  281. EndIf
  282. SetGadgetShape(pnlPanes[SPLITPANEL_MAIN], tmpDimensions[SPLITPANEL_MAIN][0], tmpDimensions[SPLITPANEL_MAIN][1], tmpDimensions[SPLITPANEL_MAIN][2], tmpDimensions[SPLITPANEL_MAIN][3])
  283. SetGadgetShape(pnlPanes[SPLITPANEL_SIDEPANE], tmpDimensions[SPLITPANEL_SIDEPANE][0], tmpDimensions[SPLITPANEL_SIDEPANE][1], tmpDimensions[SPLITPANEL_SIDEPANE][2], tmpDimensions[SPLITPANEL_SIDEPANE][3])
  284. EndMethod
  285. Method ChangeOrientation(pOrientation% = -1)
  286. If pOrientation = intOrientation Then Return
  287. If pOrientation < 0 Then
  288. intOrientation:~SPLIT_FLIPPED
  289. Else
  290. If pixHandle[0] And intOrientation&SPLIT_VERTICAL <> pOrientation&SPLIT_VERTICAL Then
  291. pixHandle[0] = RotatePixmap(pixHandle[0]);pixHandle[1] = RotatePixmap(pixHandle[1])
  292. EndIf
  293. intOrientation = pOrientation
  294. EndIf
  295. SetPanelPixmap(pnlSplitHandle, pixHandle[0]);DrawHandle();DrawPanes();ReapplyLocks();RedrawGadget(gadParent)
  296. EndMethod
  297. Method Toggle()
  298. If intPanelSpace > intMinPanelSpace Then SetPanelSpace( intMinPanelSpace ) Else SetPanelSpace( intSavePanelSpace )
  299. EndMethod
  300. Method eventHook:Object( pID%, pData:Object )
  301. Local tmpEvent:TEvent = TEvent(pData)
  302. If (Not tmpEvent) Or (Not TGadget(tmpEvent.source)) Then Return pData
  303. Select tmpEvent.source
  304. Case pnlSplitHandle, divSplitHandle1, divSplitHandle2
  305. If (tmpEvent.source = divSplitHandle1) Or (tmpEvent.source = divSplitHandle2) Then
  306. tmpEvent.x:+GadgetX(TGadget(tmpEvent.source))
  307. tmpEvent.y:+GadgetY(TGadget(tmpEvent.source))
  308. tmpEvent.source = pnlSplitHandle
  309. EndIf
  310. Select tmpEvent.id
  311. Case EVENT_MOUSEDOWN
  312. If (tmpEvent.data <> MOUSE_LEFT) Then Return Null
  313. intMouseDown = [tmpEvent.x, tmpEvent.y]
  314. intHasMoved = False
  315. Case EVENT_MOUSEMOVE
  316. intHasMoved = True
  317. If tmpEvent.data Then
  318. If intMouseDown Or (tmpEvent.data = MOUSE_LEFT And intShouldUpdate) Then
  319. 'Update our mouse pointer and re-set our drag-point (if needed).
  320. ShowDragPointer()
  321. If intShouldUpdate Or Not intMouseDown Then
  322. intMouseDown = [tmpEvent.x,tmpEvent.y]
  323. intShouldUpdate = False
  324. EndIf
  325. 'New values that are updated once everything has been checked
  326. Local tmpOrientation% = GetOrientation(), tmpPanelSpace% = -1, tmpPanelSave% = False
  327. 'New size of panel if resized with mouse cursor
  328. Local tmpDraggedSpace% = -[tmpEvent.y-intMouseDown[1],tmpEvent.x-intMouseDown[0]][intOrientation&SPLIT_VERTICAL]
  329. If tmpOrientation&SPLIT_FLIPPED Then tmpDraggedSpace:*-1
  330. tmpDraggedSpace:+intPanelSpace
  331. 'Update intPanelSpace if we can drag as any calls to GetPanelSpace() need to return an accurate value
  332. If (intBehavior&SPLIT_RESIZABLE) And tmpDraggedSpace <> intPanelSpace Then
  333. 'Simulate a snap-closed action for the splitter
  334. If tmpDraggedSpace < intGutterSize Then tmpDraggedSpace = intMinPanelSpace
  335. tmpPanelSpace = tmpDraggedSpace
  336. intPanelSpace = tmpDraggedSpace
  337. EndIf
  338. 'Limit the pane-size to half the client-area if SPLIT_LIMITPANESIZE is set.
  339. If (intBehavior&SPLIT_LIMITPANESIZE) Then
  340. Local tmpDimensions%[] = [ClientHeight(),ClientWidth()]
  341. If GetPanelSpace(SPLITPANEL_SIDEPANE) > (tmpDimensions[(tmpOrientation&SPLIT_VERTICAL)])/2 Then
  342. If (intBehavior&SPLIT_CANFLIP) Then
  343. tmpOrientation:~SPLIT_FLIPPED
  344. tmpPanelSpace = GetPanelSpace(SPLITPANEL_MAIN)
  345. Else
  346. tmpPanelSpace = (tmpDimensions[(tmpOrientation&SPLIT_VERTICAL)])/2
  347. EndIf
  348. tmpPanelSave = True
  349. EndIf
  350. EndIf
  351. 'Update the splitter's orientation if needed.
  352. If (intBehavior&(SPLIT_CANORIENTATE|SPLIT_CANFLIP)) Then
  353. 'Drag test conditions
  354. Local tmpLeftCond% = (GadgetX(pnlSplitHandle)+tmpEvent.x < 1)
  355. Local tmpRightCond% = (GadgetX(pnlSplitHandle)+tmpEvent.x > ClientWidth()-intGutterSize)
  356. Local tmpTopCond% = (GadgetY(pnlSplitHandle)+tmpEvent.y < 1)
  357. Local tmpBottomCond% = (GadgetY(pnlSplitHandle)+tmpEvent.y > ClientHeight()-intGutterSize)
  358. Select True
  359. Case (tmpRightCond And Not (tmpTopCond|tmpBottomCond)), (tmpLeftCond And Not (tmpTopCond|tmpBottomCond)), ..
  360. (tmpBottomCond And Not (tmpLeftCond|tmpRightCond)), (tmpTopCond And Not (tmpLeftCond|tmpRightCond))
  361. If (intBehavior&SPLIT_CANFLIP) Or ((tmpLeftCond|tmpTopCond)=(tmpOrientation&SPLIT_FLIPPED)) Then
  362. If (intBehavior&SPLIT_CANORIENTATE) Then
  363. If (tmpLeftCond|tmpRightCond) Then tmpOrientation:|SPLIT_VERTICAL Else tmpOrientation:&~SPLIT_VERTICAL
  364. Else
  365. Select (tmpOrientation&SPLIT_VERTICAL)
  366. Case SPLIT_VERTICAL;tmpTopCond = 0;tmpBottomCond = 0
  367. Case SPLIT_HORIZONTAL;tmpLeftCond = 0;tmpRightCond = 0
  368. EndSelect
  369. EndIf
  370. 'Let's determine whether our side-panel should be flipped or not.
  371. If (tmpLeftCond|tmpTopCond) Then tmpOrientation:|SPLIT_FLIPPED ElseIf (tmpRightCond|tmpBottomCond) Then tmpOrientation:&~SPLIT_FLIPPED
  372. 'If we are resizable and the orientation has changed, let's reset the side-pane size.
  373. If (intBehavior&SPLIT_RESIZABLE) And (tmpOrientation <> intOrientation) Then tmpPanelSpace = intMinPanelSpace;tmpPanelSave = True
  374. EndIf
  375. EndSelect
  376. EndIf
  377. 'Apply our newly calculated values to the splitter.
  378. If (tmpOrientation <> GetOrientation()) Then
  379. If (tmpOrientation&SPLIT_VERTICAL <> GetOrientation()&SPLIT_VERTICAL) Then
  380. intMouseDown = Null
  381. intShouldUpdate = True
  382. EndIf
  383. ChangeOrientation( tmpOrientation )
  384. ShowActivePointer()
  385. EndIf
  386. If tmpPanelSpace > -1 Then SetPanelSpace( tmpPanelSpace, tmpPanelSave )
  387. EndIf
  388. Else
  389. intMouseDown = Null
  390. EndIf
  391. Case EVENT_MOUSEUP
  392. If (intMouseDown And tmpEvent.data = MOUSE_LEFT) Then
  393. If Not intHasMoved Then
  394. If (intBehavior&SPLIT_CLICKTOTOGGLE) Then Toggle()
  395. Else
  396. SetPanelSpace( intPanelSpace, True )
  397. EndIf
  398. intMouseDown = Null
  399. ShowNormalPointer()
  400. EndIf
  401. Case EVENT_MOUSELEAVE
  402. If (intBehavior&(SPLIT_RESIZABLE|SPLIT_CLICKTOTOGGLE)) Then
  403. SetPanelPixmap(pnlSplitHandle, pixHandle[0])
  404. EndIf
  405. ShowNormalPointer()
  406. Case EVENT_MOUSEENTER
  407. If (intBehavior&(SPLIT_RESIZABLE|SPLIT_CLICKTOTOGGLE)) Then
  408. SetPanelPixmap(pnlSplitHandle, pixHandle[1])
  409. EndIf
  410. ShowActivePointer()
  411. EndSelect
  412. Case pnlPanes[SPLITPANEL_MAIN], pnlPanes[SPLITPANEL_SIDEPANE], gadParent
  413. 'Don't show these events to the other hooks!
  414. Default
  415. Select tmpEvent.id
  416. Case EVENT_WINDOWSIZE
  417. If (intBehavior&SPLIT_RESIZABLE) And TGadget(tmpEvent.source).HasDescendant(gadParent) Then
  418. Local tmpLimit% = [ClientHeight(),ClientWidth()][intOrientation&SPLIT_VERTICAL]
  419. If (intBehavior&SPLIT_LIMITPANESIZE) Then tmpLimit:Shr 1 Else tmpLimit:-intGutterSize
  420. If GetPanelSpace(SPLITPANEL_SIDEPANE) > tmpLimit Then SetPanelSpace( tmpLimit, True )
  421. EndIf
  422. EndSelect
  423. Return pData
  424. EndSelect
  425. EndMethod
  426. 'Mouse Cursor
  427. Function ShowNormalPointer()
  428. SetPointer(POINTER_DEFAULT)
  429. EndFunction
  430. Method ShowActivePointer()
  431. If (intBehavior&SPLIT_RESIZABLE) Then
  432. Select intOrientation&SPLIT_VERTICAL
  433. Case SPLIT_HORIZONTAL;SetPointer(POINTER_SIZENS)
  434. Case SPLIT_VERTICAL;SetPointer(POINTER_SIZEWE)
  435. EndSelect
  436. ElseIf (intBehavior&SPLIT_CLICKTOTOGGLE) Then
  437. SetPointer(POINTER_HAND)
  438. Else
  439. SetPointer(POINTER_DEFAULT)
  440. EndIf
  441. EndMethod
  442. Method ShowDragPointer()
  443. If (intBehavior&SPLIT_RESIZABLE) Then
  444. Select intOrientation&SPLIT_VERTICAL
  445. Case SPLIT_HORIZONTAL;SetPointer(POINTER_SIZENS)
  446. Case SPLIT_VERTICAL;SetPointer(POINTER_SIZEWE)
  447. EndSelect
  448. ElseIf (intBehavior&(SPLIT_CANFLIP|SPLIT_CANORIENTATE))
  449. SetPointer(POINTER_SIZEALL)
  450. Else
  451. SetPointer(POINTER_DEFAULT)
  452. EndIf
  453. EndMethod
  454. 'Helper Functions
  455. Function eventHandler:Object( pID%, pData:Object, pContext:Object)
  456. If TSplitter(pContext) Then Return TSplitter(pContext).eventHook( pID, pData ) Else Return pData
  457. EndFunction
  458. Function RotatePixmap:TPixmap( pSrcPixmap:TPixmap )
  459. Local tmpDestPixmap:TPixmap = CreatePixmap(pSrcPixmap.height, pSrcPixmap.width, pSrcPixmap.format)
  460. For Local y% = 0 Until pSrcPixmap.height
  461. For Local x% = 0 Until pSrcPixmap.width
  462. WritePixel( tmpDestPixmap, y, x, ReadPixel(pSrcPixmap, x, y) )
  463. Next
  464. Next
  465. Return tmpDestPixmap
  466. EndFunction
  467. Function BrightenPixmap:TPixmap( pSrcPixmap:TPixmap, pBrightness# = 1.05 )
  468. Local tmpDestPixmap:TPixmap = CreatePixmap(pSrcPixmap.width, pSrcPixmap.height, pSrcPixmap.format)
  469. For Local y% = 0 Until pSrcPixmap.height
  470. For Local x% = 0 Until pSrcPixmap.width
  471. WritePixel( tmpDestPixmap, x, y, BrightenPixel(ReadPixel(pSrcPixmap, x, y), pBrightness) )
  472. Next
  473. Next
  474. Return tmpDestPixmap
  475. EndFunction
  476. Function BrightenPixel%( pARGB%, pBrightness# = 1.05 )
  477. Local tmpHSV:TColorHSV = New TColorHSV.fromARGB(pARGB)
  478. tmpHSV.v=Min(tmpHSV.v*pBrightness,1)
  479. Return tmpHSV.toARGB()
  480. EndFunction
  481. Function WhitenPixel%( pARGB%, pWhiteness# = 0.8 )
  482. Local tmpHSV:TColorHSV = New TColorHSV.fromARGB(pARGB)
  483. tmpHSV.s=Min(tmpHSV.s*pWhiteness,1)
  484. Return tmpHSV.toARGB()
  485. EndFunction
  486. Function MakeColourHandlePixmap:TPixmap( pRed%, pGreen%, pBlue%, pWidth% )
  487. Local tmpPixmap:TPixmap = CreatePixmap(1,pWidth,PF_RGB888)
  488. Local tmpPixel% = (pRed Shl 16)|(pGreen Shl 8)|pBlue
  489. For Local i% = 0 To pWidth/2
  490. Local tmpCalculatedPixel% = BrightenPixel(tmpPixel,1.05^i)
  491. WritePixel(tmpPixmap,0,i,tmpCalculatedPixel)
  492. WritePixel(tmpPixmap,0,pWidth-1-i,tmpCalculatedPixel)
  493. Next
  494. Return tmpPixmap
  495. EndFunction
  496. EndType
  497. Private
  498. 'Some type declarations from fredborg's pub.color module
  499. 'http://www.blitzbasic.com/codearcs/codearcs.php?code=1749
  500. Type TColor
  501. Method toARGB:Int() Abstract
  502. End Type
  503. Type TColorHSV Extends TColor
  504. Field h:Float,s:Float,v:Float,a:Float=1.0
  505. Method toRGB:TColorRGB()
  506. Local temph:Float = Self.h
  507. Local temps:Float = Self.s
  508. Local tempv:Float = Self.v
  509. Local rgb:TColorRGB = New TColorRGB
  510. If temph=>360.0 Or temph<0.0 Then temph = 0.0
  511. If temps = 0 Then
  512. rgb.r = v
  513. rgb.g = v
  514. rgb.b = v
  515. Else
  516. temph = temph / 60.0
  517. Local i:Int = Floor(temph)
  518. Local f:Float = temph - i
  519. Local p:Float = tempv * (1 - temps)
  520. Local q:Float = tempv * (1 - temps * f)
  521. Local t:Float = tempv * (1 - temps * (1 - f))
  522. Select i
  523. Case 0
  524. rgb.r = v
  525. rgb.g = t
  526. rgb.b = p
  527. Case 1
  528. rgb.r = q
  529. rgb.g = v
  530. rgb.b = p
  531. Case 2
  532. rgb.r = p
  533. rgb.g = v
  534. rgb.b = t
  535. Case 3
  536. rgb.r = p
  537. rgb.g = q
  538. rgb.b = v
  539. Case 4
  540. rgb.r = t
  541. rgb.g = p
  542. rgb.b = v
  543. Default
  544. rgb.r = v
  545. rgb.g = p
  546. rgb.b = q
  547. End Select
  548. EndIf
  549. rgb.a = a
  550. Return rgb
  551. EndMethod
  552. Function fromARGB:TColorHSV(argb:Int)
  553. Return TColorRGB.fromARGB(argb).toHSV()
  554. EndFunction
  555. Method toARGB:Int()
  556. Return Self.toRGB().toARGB()
  557. EndMethod
  558. EndType
  559. Type TColorRGB Extends TColor
  560. Field r:Float,g:Float,b:Float,a:Float=1.0
  561. Method toHSV:TColorHSV()
  562. Local tempr:Float = Min(1.0,Max(0.0,Self.r))
  563. Local tempg:Float = Min(1.0,Max(0.0,Self.g))
  564. Local tempb:Float = Min(1.0,Max(0.0,Self.b))
  565. Local minVal:Float = Min(Min(tempr,tempg),tempb)
  566. Local maxVal:Float = Max(Max(tempr,tempg),tempb)
  567. Local diff:Float = maxVal - minVal
  568. Local hsv:TColorHSV = New TColorHSV
  569. hsv.v = maxVal
  570. If maxVal = 0.0 Then
  571. hsv.s = 0.0
  572. hsv.h = 0.0
  573. Else
  574. hsv.s = diff / maxVal
  575. If tempr = maxVal
  576. hsv.h = (tempg - tempb) / diff
  577. ElseIf tempg = maxVal
  578. hsv.h = 2.0 + (tempb - tempr) / diff
  579. Else
  580. hsv.h = 4.0 + (tempr - tempg) / diff
  581. EndIf
  582. hsv.h = hsv.h * 60.0
  583. If hsv.h < 0 Then hsv.h = hsv.h + 360.0
  584. EndIf
  585. If hsv.h< 0.0 Then hsv.h = 0.0
  586. If hsv.h>360.0 Then hsv.h = 0.0
  587. hsv.a = a
  588. Return hsv
  589. EndMethod
  590. Function fromARGB:TColorRGB(argb:Int,alpha:Int=True)
  591. Local rgb:TColorRGB = New TColorRGB
  592. If alpha
  593. rgb.a = ((argb Shr 24) & $FF)/255.0
  594. EndIf
  595. rgb.r = ((argb Shr 16) & $FF)/255.0
  596. rgb.g = ((argb Shr 8) & $FF)/255.0
  597. rgb.b = (argb & $FF)/255.0
  598. Return rgb
  599. EndFunction
  600. Function fromBGR:TColorRGB(argb:Int)
  601. Local rgb:TColorRGB = New TColorRGB
  602. rgb.r = (argb & $000000FF)/255.0
  603. rgb.g = ((argb Shr 8) & $000000FF)/255.0
  604. rgb.b = ((argb Shr 16) & $000000FF)/255.0
  605. Return rgb
  606. EndFunction
  607. Method toARGB:Int()
  608. Local tempr:Int = Min(255,Max(0,Int(Self.r*255)))
  609. Local tempg:Int = Min(255,Max(0,Int(Self.g*255)))
  610. Local tempb:Int = Min(255,Max(0,Int(Self.b*255)))
  611. Local tempa:Int = Min(255,Max(0,Int(Self.a*255)))
  612. Return (tempa Shl 24) | (tempr Shl 16) | (tempg Shl 8) | tempb
  613. EndMethod
  614. EndType