treeview.monkey2 8.6 KB

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