treeview.monkey2 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. Namespace mojox
  2. #rem monkeydoc The TreeView class.
  3. #end
  4. Class TreeView Extends ScrollableView
  5. #rem monkeydoc Invoked when a node is clicked.
  6. #end
  7. Field NodeClicked:Void( node:Node )
  8. #rem monkeydoc Invoked when a node is right clicked.
  9. #end
  10. Field NodeRightClicked:Void( node:Node )
  11. #rem monkeydoc Invoked when a node is double clicked.
  12. #end
  13. Field NodeDoubleClicked:Void( node:Node)
  14. #rem monkeydoc Invoked when a node is expanded.
  15. #end
  16. Field NodeExpanded:Void( node:Node )
  17. #rem monkeydoc Invoked when a node is collapsed.
  18. #end
  19. Field NodeCollapsed:Void( node:Node )
  20. Class Node
  21. #rem monkeydoc Creates a new node.
  22. #end
  23. Method New( text:String,parent:Node=Null,index:Int=-1 )
  24. If parent parent.AddChild( Self,index )
  25. Text=text
  26. End
  27. #rem monkeydoc Node style.
  28. If null, the node uses the tree view's style.
  29. #end
  30. Property Style:Style()
  31. Return _style
  32. Setter( style:Style )
  33. _style=style
  34. Dirty()
  35. End
  36. #rem monkeydoc Node text.
  37. #end
  38. Property Text:String()
  39. Return _text
  40. Setter( text:String )
  41. If text=_text Return
  42. _text=text
  43. Dirty()
  44. End
  45. #rem monkeydoc Node icon.
  46. #end
  47. Property Icon:Image()
  48. Return _icon
  49. Setter( icon:Image )
  50. If icon=_icon Return
  51. _icon=icon
  52. Dirty()
  53. End
  54. #rem monkeydoc Node parent.
  55. #end
  56. Property Parent:Node()
  57. Return _parent
  58. End
  59. #rem monkeydoc Number of children.
  60. #end
  61. Property NumChildren:Int()
  62. Return _children.Length
  63. End
  64. #rem monkeydoc Child nodes.
  65. #end
  66. Property Children:Node[]()
  67. Return _children.ToArray()
  68. End
  69. #rem monkeydoc Node expanded state.
  70. #end
  71. Property Expanded:Bool()
  72. Return _expanded
  73. Setter( expanded:Bool )
  74. _expanded=expanded
  75. Dirty()
  76. End
  77. #rem monkeydoc @hidden
  78. #end
  79. Property Rect:Recti()
  80. Return _rect
  81. End
  82. #rem monkeydoc @hidden
  83. #end
  84. Property Bounds:Recti()
  85. Return _bounds
  86. End
  87. #rem monkeydoc Expands this node and all child nodes.
  88. #end
  89. Method ExpandAll()
  90. Expanded=True
  91. For Local child:=Eachin _children
  92. child.ExpandAll()
  93. Next
  94. End
  95. #rem monkeydoc Collapses this node and all child nodes.
  96. #end
  97. Method CollapseAll()
  98. Expanded=False
  99. For Local child:=Eachin _children
  100. child.CollapseAll()
  101. Next
  102. End
  103. #rem monkeydoc @hidden
  104. #end
  105. Method AddChild( node:Node,index:Int=-1 )
  106. If node._parent Return
  107. If index=-1
  108. index=_children.Length
  109. Else
  110. Assert( index>=0 And index<=_children.Length )
  111. Endif
  112. node._parent=Self
  113. _children.Insert( index,node )
  114. node.Dirty()
  115. End
  116. #rem monkeydoc @hidden
  117. #end
  118. Method RemoveChildren( index1:Int,index2:Int )
  119. Assert( index1>=0 And index2>=index1 And index1<=_children.Length And index2<=_children.Length )
  120. For Local i:=index1 Until index2
  121. _children[i]._parent=Null
  122. Next
  123. _children.Erase( index1,index2 )
  124. Dirty()
  125. End
  126. #rem monkeydoc Removes a child node.
  127. #end
  128. Method RemoveChild( node:Node )
  129. If node._parent<>Self Return
  130. _children.Remove( node )
  131. node._parent=Null
  132. Dirty()
  133. End
  134. #rem monkeydoc Removes a child node.
  135. #end
  136. Method RemoveChild( index:Int )
  137. RemoveChild( GetChild( index ) )
  138. End
  139. #rem monkeydoc Removes children starting at an index.
  140. #end
  141. Method RemoveChildren( first:Int )
  142. RemoveChildren( first,_children.Length )
  143. End
  144. #rem monkeydoc Removes all children.
  145. #end
  146. Method RemoveAllChildren()
  147. RemoveChildren( 0,_children.Length )
  148. End
  149. #rem monkeydoc Removes this node from it's parent.
  150. #end
  151. Method Remove()
  152. If _parent _parent.RemoveChild( Self )
  153. End
  154. #rem monkeydoc Gets a child node by index.
  155. #end
  156. Method GetChild:Node( index:Int )
  157. If index>=0 And index<_children.Length Return _children[index]
  158. Return Null
  159. End
  160. Private
  161. Field _parent:Node
  162. Field _children:=New Stack<Node> 'should make on demand...
  163. Field _style:Style
  164. Field _text:String
  165. Field _icon:Image
  166. Field _expanded:Bool
  167. Field _bounds:Recti
  168. Field _rect:Recti
  169. Field _dirty:Bool
  170. Method Dirty()
  171. _dirty=True
  172. Local node:=_parent
  173. While node
  174. node._dirty=True
  175. node=node._parent
  176. Wend
  177. End
  178. End
  179. #rem monkeydoc Creates a new tree view.
  180. #end
  181. Method New()
  182. Style=GetStyle( "TreeView" )
  183. Layout="fill"
  184. _rootNode=New Node( Null )
  185. End
  186. #rem monkeydoc Root node of tree.
  187. #end
  188. Property RootNode:Node()
  189. Return _rootNode
  190. Setter( node:Node )
  191. If node=_rootNode Return
  192. _rootNode=node
  193. App.RequestRender()
  194. End
  195. #rem monkeydoc Whether root node is visible.
  196. #end
  197. Property RootNodeVisible:Bool()
  198. Return _rootNodeVisible
  199. Setter( rootNodeVisible:Bool )
  200. If rootNodeVisible=_rootNodeVisible Return
  201. _rootNodeVisible=rootNodeVisible
  202. App.RequestRender()
  203. End
  204. #rem monkeydoc @hidden
  205. #end
  206. Method FindNodeAtPoint:Node( point:Vec2i )
  207. point=TransformPointToView( point,ContentView )
  208. Return FindNodeAtPoint( _rootNode,point )
  209. End
  210. Protected
  211. Method OnValidateStyle() Override
  212. Local style:=RenderStyle
  213. _collapsedIcon=style.Icons[0]
  214. _expandedIcon=style.Icons[1]
  215. _nodeSize=style.Font.Height
  216. _spcWidth=style.Font.TextWidth( " " )
  217. End
  218. Method OnMeasureContent:Vec2i() Override
  219. If Not _rootNode Return New Vec2i( 0,0 )
  220. Local origin:Vec2i
  221. 'If Not _rootNodeVisible origin=New Vec2i( -_nodeSize,-_nodeSize )
  222. MeasureNode( _rootNode,origin,False )
  223. Return _rootNode._bounds.Size
  224. End
  225. Method OnRenderContent( canvas:Canvas ) Override
  226. If Not _rootNode Return
  227. RenderNode( canvas,_rootNode )
  228. End
  229. Method OnContentMouseEvent( event:MouseEvent ) Override
  230. Local p:=event.Location
  231. Select event.Type
  232. Case EventType.MouseDown
  233. Return
  234. Case EventType.MouseClick
  235. Local node:=FindNodeAtPoint( _rootNode,p )
  236. If node
  237. p-=node._rect.Origin
  238. If p.x<_nodeSize And p.y<node.Rect.Height
  239. node.Expanded=Not node.Expanded
  240. App.RequestRender()
  241. If node.Expanded
  242. NodeExpanded( node )
  243. Else
  244. NodeCollapsed( node )
  245. Endif
  246. Else
  247. NodeClicked( node )
  248. Endif
  249. Endif
  250. Case EventType.MouseRightClick
  251. Local node:=FindNodeAtPoint( _rootNode,p )
  252. If node NodeRightClicked( node )
  253. Case EventType.MouseDoubleClick
  254. Local node:=FindNodeAtPoint( _rootNode,p )
  255. If node NodeDoubleClicked( node )
  256. Case EventType.MouseWheel
  257. Return
  258. End
  259. event.Eat()
  260. End
  261. Private
  262. Field _spacing:=2
  263. Field _rootNode:Node
  264. Field _rootNodeVisible:=True
  265. Field _expandedIcon:Image
  266. Field _collapsedIcon:Image
  267. Field _nodeSize:Int
  268. Field _spcWidth:Int
  269. Method FindNodeAtPoint:Node( node:Node,point:Vec2i )
  270. If node._rect.Contains( point ) Return node
  271. If node._expanded And node._bounds.Contains( point )
  272. For Local child:=Eachin node._children
  273. Local cnode:=FindNodeAtPoint( child,point )
  274. If cnode Return cnode
  275. Next
  276. Endif
  277. Return Null
  278. End
  279. Method MeasureNode( node:Node,origin:Vec2i,dirty:Bool )
  280. If Not node._dirty And Not dirty Return
  281. node._dirty=False
  282. Local style:=node.Style
  283. If Not style style=RenderStyle
  284. Local size:Vec2i,nodeSize:=0
  285. If node<>_rootNode Or _rootNodeVisible
  286. Local w:=Int( style.Font.TextWidth( node._text ) )
  287. Local h:=Int( style.Font.Height )
  288. If node._icon
  289. w+=_spcWidth+node._icon.Width
  290. h=Max( h,Int( node._icon.Height ) )
  291. Endif
  292. size=New Vec2i( w+_nodeSize,Max( h,_nodeSize )+_spacing )
  293. nodeSize=_nodeSize
  294. Endif
  295. Local rect:=New Recti( origin,origin+size )
  296. node._rect=rect
  297. If node._expanded
  298. origin.x+=nodeSize
  299. For Local child:=Eachin node._children
  300. origin.y=rect.Bottom
  301. MeasureNode( child,origin,True )
  302. rect|=child._bounds
  303. Next
  304. Endif
  305. node._bounds=rect
  306. End
  307. Method RenderNode( canvas:Canvas,node:Node )
  308. Local clip:=VisibleRect
  309. If Not node._bounds.Intersects( clip ) Return
  310. If _rootNodeVisible Or node<>_rootNode
  311. If node._children.Length
  312. Local icon:=_collapsedIcon
  313. If node._expanded icon=_expandedIcon
  314. Local x:=(_nodeSize-icon.Width)/2
  315. Local y:=(node._rect.Height-icon.Height)/2
  316. RenderStyle.DrawIcon( canvas,icon,node._rect.X+x,node._rect.Y+y )
  317. Endif
  318. Local x:=node._rect.X+_nodeSize
  319. Local style:=node.Style
  320. If Not style style=RenderStyle
  321. If node._icon
  322. Local y:=(node._rect.Height-node._icon.Height)/2
  323. style.DrawIcon( canvas,node._icon,x,node._rect.Y+y )
  324. x+=node._icon.Width+_spcWidth
  325. Endif
  326. Local y:=(node._rect.Height-RenderStyle.Font.Height)/2
  327. style.DrawText( canvas,node._text,x,node._rect.Y+y )
  328. Endif
  329. If node._expanded
  330. For Local child:=Eachin node._children
  331. RenderNode( canvas,child )
  332. Next
  333. Endif
  334. End
  335. End