dockingview.monkey2 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. Namespace mojox
  2. #rem monkeydoc @hidden
  3. #end
  4. Class DockKnob Extends View
  5. Field Dragged:Void( v:Vec2i )
  6. Method New( vertical:Bool )
  7. Style=GetStyle( "DockKnob" )
  8. _vertical=vertical
  9. End
  10. Protected
  11. Method OnMeasure:Vec2i() Override
  12. Return New Vec2i( 0,0 )
  13. End
  14. Method OnMouseEvent( event:MouseEvent ) Override
  15. Select event.Type
  16. Case EventType.MouseDown
  17. _drag=True
  18. _org=event.Location
  19. Case EventType.MouseUp
  20. _drag=False
  21. Case EventType.MouseEnter
  22. _hover=True
  23. _storedCursor=Mouse.Cursor
  24. Mouse.Cursor=_vertical ? MouseCursor.SizeWE Else MouseCursor.SizeNS
  25. Case EventType.MouseLeave
  26. _hover=False
  27. Mouse.Cursor=_storedCursor
  28. Case EventType.MouseMove
  29. If _drag Dragged( event.Location-_org )
  30. End
  31. If _drag
  32. StyleState="active"
  33. Else If _hover
  34. StyleState="hover"
  35. Else
  36. StyleState=""
  37. Endif
  38. End
  39. Private
  40. Field _org:Vec2i
  41. Field _drag:Bool
  42. Field _hover:Bool
  43. Field _storedCursor:MouseCursor
  44. Field _vertical:Bool
  45. End
  46. #rem monkeydoc @hidden
  47. #end
  48. Class DockedView Extends View
  49. Method New( view:View,location:String,size:String,resizable:Bool )
  50. Style=GetStyle( "DockedView" )
  51. _view=view
  52. _location=location
  53. _size=size
  54. _resizable=resizable
  55. If _size.EndsWith( "%" )
  56. _sizeMode=SizeMode.Relative
  57. _relSize=Float( _size.Slice( 0,-1 ) )/100
  58. Else If String( Int( _size ) )=_size
  59. _sizeMode=SizeMode.Absolute
  60. _absSize=Int( _size )
  61. Else
  62. _sizeMode=SizeMode.Natural
  63. Endif
  64. AddChildView( _view )
  65. If _sizeMode=SizeMode.Absolute And _resizable
  66. Local vertical:=(location="left" Or location="right")
  67. _knob=New DockKnob( vertical )
  68. _knob.Dragged=Lambda( v:Vec2i )
  69. Select _location
  70. Case "top"
  71. AbsoluteSize+=v.y
  72. Case "bottom"
  73. AbsoluteSize-=v.y
  74. Case "left"
  75. AbsoluteSize+=v.x
  76. Case "right"
  77. AbsoluteSize-=v.x
  78. End
  79. End
  80. AddChildView( _knob )
  81. Endif
  82. End
  83. Property View:View()
  84. Return _view
  85. Setter( view:View )
  86. If _view RemoveChildView( _view )
  87. _view=view
  88. If _view AddChildView( _view )
  89. End
  90. Property Location:String()
  91. Return _location
  92. End
  93. Property Size:String()
  94. Return _size
  95. Setter( size:String )
  96. If size=_size Return
  97. If size.EndsWith( "%" )
  98. RelativeSize=Float( size.Slice( 0,-1 ) )/100.0
  99. Else If String( Int( size ) )=size
  100. AbsoluteSize=Int( size )
  101. Endif
  102. End
  103. Property Resizable:Bool()
  104. Return _resizable
  105. End
  106. Property RelativeSize:Float()
  107. Return _relSize
  108. Setter( size:Float )
  109. If _sizeMode<>SizeMode.Relative Return
  110. size=Max( size,0.0 )
  111. If size=_relSize Return
  112. _relSize=size
  113. _size=String( Int( _relSize*100.0 ) )+"%"
  114. App.RequestRender()
  115. End
  116. Property AbsoluteSize:Int()
  117. Return _absSize
  118. Setter( size:Int )
  119. If _sizeMode<>SizeMode.Absolute Return
  120. size=Max( size,0 )
  121. If size=_absSize Return
  122. _absSize=size
  123. _size=String( _absSize )
  124. App.RequestRender()
  125. End
  126. Method RealSize:Int( size:Int )
  127. Select _sizeMode
  128. Case SizeMode.Natural,SizeMode.Absolute
  129. If _location="left" Or _location="right" Return LayoutSize.x
  130. Return LayoutSize.y
  131. Case SizeMode.Relative
  132. Return _relSize * size
  133. End
  134. Return 0
  135. End
  136. Private
  137. Field _view:View
  138. Field _knob:DockKnob
  139. Field _location:String
  140. Field _size:String
  141. Field _resizable:Bool
  142. Field _sizeMode:SizeMode
  143. Field _relSize:Float
  144. Field _absSize:Int
  145. Enum SizeMode
  146. Natural
  147. Absolute
  148. Relative
  149. End
  150. Method OnMeasure:Vec2i() Override
  151. Local size:=_view.LayoutSize
  152. If _sizeMode=SizeMode.Absolute
  153. Select _location
  154. Case "top","bottom"
  155. size.y=_absSize
  156. If _knob size.y+=_knob.LayoutSize.y
  157. Case "left","right"
  158. size.x=_absSize
  159. If _knob size.x+=_knob.LayoutSize.x
  160. End
  161. #rem
  162. Else If _sizeMode=SizeMode.Relative
  163. Select _location
  164. Case "top","bottom"
  165. size.y=size.y/_relSize
  166. Case "left","right"
  167. size.x=size.x/_relSize
  168. End
  169. #end
  170. Endif
  171. Return size
  172. End
  173. Method OnLayout:Void() Override
  174. Local rect:=Rect
  175. If _knob
  176. Local w:=_knob.LayoutSize.x
  177. Local h:=_knob.LayoutSize.y
  178. Select _location
  179. Case "top"
  180. _knob.Frame=New Recti( 0,Height-h,Width,Height )
  181. rect.Bottom-=h
  182. Case "bottom"
  183. _knob.Frame=New Recti( 0,0,Width,h )
  184. rect.Top+=h
  185. Case "left"
  186. _knob.Frame=New Recti( Width-w,0,Width,Height )
  187. rect.Right-=w
  188. Case "right"
  189. _knob.Frame=New Recti( 0,0,w,Height )
  190. rect.Left+=w
  191. End
  192. Endif
  193. _view.Frame=rect
  194. End
  195. End
  196. #rem monkeydoc The DockingView class.
  197. #end
  198. Class DockingView Extends View
  199. #rem monkeydoc Creates a new docking view.
  200. #end
  201. Method New()
  202. Style=GetStyle( "DockingView" )
  203. End
  204. #rem monkeydoc The content view.
  205. #end
  206. Property ContentView:View()
  207. Return _contentView
  208. Setter( contentView:View )
  209. If contentView=_contentView Return
  210. If _content RemoveChildView( _content )
  211. _contentView=contentView
  212. _content=ContentViewContainer( _contentView )
  213. If _content AddChildView( _content )
  214. App.RequestRender()
  215. End
  216. #rem monkeydoc Adds a view.
  217. `location` should be one of "left", "right", "top", "bottom".
  218. `size` can be either an integer number of pixels or a percentage. If no size is specified, the view's layout size is used.
  219. If `resizable` is true, the view can be resizable. Note: this must be used with `size` set to a non-0 integer.
  220. #end
  221. Method AddView( view:View,location:String )
  222. AddView( view,location,"",False )
  223. End
  224. Method AddView( view:View,location:String,size:String )
  225. AddView( view,location,size,False )
  226. End
  227. Method AddView( view:View,location:String,size:String,resizable:Bool )
  228. Local dock:=New DockedView( view,location,size,resizable )
  229. _docks.Add( dock )
  230. AddChildView( dock )
  231. End
  232. #rem monkeydoc Removes a view.
  233. #end
  234. Method RemoveView( view:View )
  235. Local dock:=FindView( view )
  236. If Not dock Return
  237. dock.View=Null
  238. _docks.Remove( dock )
  239. RemoveChildView( dock )
  240. End
  241. #rem monkeydoc Gets size of a view.
  242. #end
  243. Method GetViewSize:String( view:View )
  244. Return FindView( view ).Size
  245. End
  246. #rem monkeydoc Sets size of a view.
  247. #end
  248. Method SetViewSize( view:View,size:String )
  249. FindView( view ).Size=size
  250. End
  251. #rem monkeydoc Removes all views.
  252. #end
  253. Method RemoveAllViews()
  254. For Local dock:=Eachin _docks
  255. dock.View=Null
  256. RemoveChildView( dock )
  257. Next
  258. _docks.Clear()
  259. App.RequestRender()
  260. End
  261. Protected
  262. Method OnMeasure:Vec2i() Override
  263. Local size:=New Vec2i
  264. If _content size=_content.LayoutSize
  265. _docksSize=New Vec2i
  266. For Local dock:=Eachin _docks
  267. 'FIXME - silly place to do this...
  268. dock.Visible=dock.View.Visible
  269. If Not dock.Visible Continue
  270. Select dock.Location
  271. Case "top","bottom"
  272. _docksSize.y+=dock.LayoutSize.y
  273. size.x=Max( size.x,dock.LayoutSize.x )
  274. size.y+=dock.LayoutSize.y
  275. Case "left","right"
  276. _docksSize.x+=dock.LayoutSize.x
  277. size.y=Max( size.y,dock.LayoutSize.y )
  278. size.x+=dock.LayoutSize.x
  279. End
  280. Next
  281. Return size
  282. End
  283. Method OnLayout() Override
  284. Local rect:=OnLayoutContent( Rect.Size-_docksSize )
  285. Local fsize:=rect.Size
  286. For Local dock:=Eachin _docks
  287. If Not dock.Visible Continue
  288. Select dock.Location
  289. Case "top"
  290. Local top:=rect.Top+dock.RealSize( fsize.y )
  291. If dock.Resizable And top>rect.Bottom top=rect.Bottom
  292. ' If top>rect.Bottom top=rect.Bottom
  293. dock.Frame=New Recti( rect.Left,rect.Top,rect.Right,top )
  294. rect.Top=top
  295. Case "bottom"
  296. Local bottom:=rect.Bottom-dock.RealSize( fsize.y )
  297. If dock.Resizable And bottom<rect.Top bottom=rect.Top
  298. ' If bottom<rect.Top bottom=rect.Top
  299. dock.Frame=New Recti( rect.Left,bottom,rect.Right,rect.Bottom )
  300. rect.Bottom=bottom
  301. Case "left"
  302. Local left:=rect.Left+dock.RealSize( fsize.x )
  303. If dock.Resizable And left>rect.Right left=rect.Right
  304. ' If left>rect.Right left=rect.Right
  305. dock.Frame=New Recti( rect.Left,rect.Top,left,rect.Bottom )
  306. rect.Left=left
  307. Case "right"
  308. Local right:=rect.Right-dock.RealSize( fsize.x )
  309. If dock.Resizable And right<rect.Left right=rect.Left
  310. ' If right<rect.Left right=rect.Left
  311. dock.Frame=New Recti( right,rect.Top,rect.Right,rect.Bottom )
  312. rect.Right=right
  313. End
  314. Next
  315. If _content _content.Frame=rect
  316. End
  317. Method OnLayoutContent:Recti( contentSize:Vec2i ) Virtual
  318. Return Rect
  319. End
  320. Method ContentViewContainer:View( contentView:View ) Virtual
  321. Return contentView
  322. End
  323. Private
  324. Field _content:View
  325. Field _contentView:View
  326. Field _docksSize:Vec2i
  327. Field _docks:=New Stack<DockedView>
  328. Method FindView:DockedView( view:View )
  329. For Local dock:=Eachin _docks
  330. If dock.View=view Return dock
  331. Next
  332. Return Null
  333. End
  334. End