TreeNode.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. GWEN
  3. Copyright (c) 2010 Facepunch Studios
  4. See license in Gwen.h
  5. */
  6. #include "Gwen/Controls/TreeNode.h"
  7. #include "Gwen/Controls/TreeControl.h"
  8. #include "Gwen/Utility.h"
  9. using namespace Gwen;
  10. using namespace Gwen::Controls;
  11. class OpenToggleButton : public Button
  12. {
  13. GWEN_CONTROL_INLINE ( OpenToggleButton, Button )
  14. {
  15. SetIsToggle( true );
  16. SetTabable( false );
  17. }
  18. virtual void RenderFocus( Skin::Base* /*skin*/ ) {}
  19. virtual void Render( Skin::Base* skin )
  20. {
  21. skin->DrawTreeButton( this, GetToggleState() );
  22. }
  23. };
  24. const int TreeIndentation = 14;
  25. const int BranchLength = 16;
  26. GWEN_CONTROL_CONSTRUCTOR( TreeNode )
  27. {
  28. m_TreeControl = NULL;
  29. m_ToggleButton = new OpenToggleButton( this );
  30. m_ToggleButton->SetBounds( 2, 2, 13, 13 );
  31. m_ToggleButton->onToggle.Add( this, &TreeNode::OnToggleButtonPress );
  32. m_Title = new Button( this );
  33. m_Title->Dock( Pos::Top );
  34. m_Title->SetMargin( Margin( BranchLength, 0, 0, 0 ) );
  35. m_Title->SetAlignment( Pos::Left | Pos::CenterV );
  36. m_Title->SetShouldDrawBackground( false );
  37. m_Title->onDoubleClick.Add( this, &TreeNode::OnDoubleClickName );
  38. m_Title->onDown.Add( this, &TreeNode::OnClickName );
  39. m_Title->SetHeight( 16 );
  40. m_InnerPanel = new Base( this );
  41. m_InnerPanel->Dock( Pos::Top );
  42. m_InnerPanel->SetHeight( 100 );
  43. m_InnerPanel->SetMargin( Margin( TreeIndentation, 1, 0, 0 ) );
  44. m_InnerPanel->Hide();
  45. m_bRoot = false;
  46. m_bSelected = false;
  47. m_bSelectable = true;
  48. }
  49. void TreeNode::Render( Skin::Base* skin )
  50. {
  51. int iBottom = 0;
  52. if ( m_InnerPanel->Children.size() > 0 )
  53. {
  54. iBottom = m_InnerPanel->Children.back()->Y() + m_InnerPanel->Y();
  55. }
  56. skin->DrawTreeNode( this, m_InnerPanel->Visible(), IsSelected(), m_Title->Height(), m_Title->TextRight(), m_ToggleButton->Y() + m_ToggleButton->Height() * 0.5, iBottom, GetParent() == m_TreeControl );
  57. }
  58. TreeNode* TreeNode::AddNode( const UnicodeString& strLabel )
  59. {
  60. // int sz = sizeof(TreeNode);
  61. TreeNode* node = new TreeNode( this );
  62. node->SetText( strLabel );
  63. node->Dock( Pos::Top );
  64. node->SetRoot( this->DynamicCastTreeControl() != NULL );
  65. node->SetTreeControl( m_TreeControl );
  66. if ( m_TreeControl )
  67. {
  68. m_TreeControl->OnNodeAdded( node );
  69. }
  70. return node;
  71. }
  72. TreeNode* TreeNode::AddNode( const String& strLabel )
  73. {
  74. return AddNode( Utility::StringToUnicode( strLabel ) );
  75. }
  76. void TreeNode::Layout( Skin::Base* skin )
  77. {
  78. if ( m_ToggleButton )
  79. {
  80. if ( m_InnerPanel->NumChildren() == 0 )
  81. {
  82. m_ToggleButton->Hide();
  83. m_ToggleButton->SetToggleState( false );
  84. m_InnerPanel->Hide();
  85. }
  86. else
  87. {
  88. m_ToggleButton->Show();
  89. m_InnerPanel->SizeToChildren( false, true );
  90. }
  91. }
  92. BaseClass::Layout( skin );
  93. }
  94. //too many calls to PostLayout...
  95. //int numCalls = 0xfd;
  96. void TreeNode::PostLayout( Skin::Base* /*skin*/ )
  97. {
  98. //int bla = numCalls&0xffff;
  99. //if (bla==0)
  100. // printf("TreeNode::PostLayout numCalls = %d\n", numCalls);
  101. //numCalls++;
  102. if ( SizeToChildren( false, true ) )
  103. {
  104. InvalidateParent();
  105. }
  106. }
  107. void TreeNode::SetText( const UnicodeString& text ){ m_Title->SetText( text ); };
  108. void TreeNode::SetText( const String& text ){ m_Title->SetText( text ); };
  109. UnicodeString TreeNode::GetText() const
  110. {
  111. UnicodeString bla = m_Title->GetText();
  112. return bla;
  113. }
  114. void TreeNode::Open()
  115. {
  116. m_InnerPanel->Show();
  117. if ( m_ToggleButton ) m_ToggleButton->SetToggleState( true );
  118. Invalidate();
  119. if (m_TreeControl)
  120. m_TreeControl->ForceUpdateScrollBars();
  121. }
  122. void TreeNode::Close()
  123. {
  124. m_InnerPanel->Hide();
  125. if ( m_ToggleButton ) m_ToggleButton->SetToggleState( false );
  126. Invalidate();
  127. if (m_TreeControl)
  128. m_TreeControl->ForceUpdateScrollBars();
  129. }
  130. void TreeNode::ExpandAll()
  131. {
  132. Open();
  133. Base::List& children = m_InnerPanel->GetChildren();
  134. for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
  135. {
  136. TreeNode* pChild = (*iter)->DynamicCastTreeNode();
  137. if ( !pChild ) continue;
  138. pChild->ExpandAll();
  139. }
  140. }
  141. Button* TreeNode::GetButton(){ return m_Title; }
  142. void TreeNode::OnToggleButtonPress( Base* /*control*/ )
  143. {
  144. if ( m_ToggleButton->GetToggleState() )
  145. {
  146. Open();
  147. }
  148. else
  149. {
  150. Close();
  151. }
  152. }
  153. void TreeNode::OnDoubleClickName( Base* /*control*/ )
  154. {
  155. if ( !m_ToggleButton->Visible() ) return;
  156. m_ToggleButton->Toggle();
  157. }
  158. void TreeNode::OnClickName( Base* /*control*/ )
  159. {
  160. onNamePress.Call( this );
  161. SetSelected( !IsSelected() );
  162. }
  163. void TreeNode::SetSelected( bool b )
  164. {
  165. if ( !m_bSelectable ) return;
  166. if ( m_bSelected == b ) return;
  167. m_bSelected = b;
  168. onSelectChange.Call( this );
  169. if ( m_bSelected )
  170. onSelect.Call( this );
  171. else
  172. onUnselect.Call( this );
  173. }
  174. void TreeNode::DeselectAll()
  175. {
  176. m_bSelected = false;
  177. Base::List& children = m_InnerPanel->GetChildren();
  178. for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
  179. {
  180. TreeNode* pChild = (*iter)->DynamicCastTreeNode();
  181. if ( !pChild ) continue;
  182. pChild->DeselectAll( );
  183. }
  184. }
  185. void TreeNode::iterate(int action, int* curIndex, int* targetIndex)
  186. {
  187. Gwen::String name = Gwen::Utility::UnicodeToString(m_Title->GetText());
  188. // int actualIndex = curIndex? *curIndex : -1;
  189. //printf("iterated over item %d with name = %s\n", actualIndex, name.c_str());
  190. if (action==ITERATE_ACTION_SELECT)
  191. {
  192. if (curIndex && targetIndex)
  193. {
  194. if ((*curIndex)==(*targetIndex))
  195. {
  196. SetSelected(true);
  197. *targetIndex=-1;
  198. }
  199. }
  200. }
  201. if (IsSelected())
  202. {
  203. //printf("current selected: name = %s\n", name.c_str());
  204. switch (action)
  205. {
  206. case ITERATE_ACTION_DESELECT_INDEX:
  207. {
  208. if (targetIndex && curIndex)
  209. {
  210. if (*targetIndex == *curIndex)
  211. SetSelected(false);
  212. }
  213. break;
  214. }
  215. case ITERATE_ACTION_FIND_SELECTED_INDEX:
  216. {
  217. if (targetIndex && curIndex)
  218. {
  219. *targetIndex = *curIndex;
  220. }
  221. break;
  222. }
  223. case ITERATE_ACTION_OPEN:
  224. {
  225. Open();
  226. break;
  227. }
  228. case ITERATE_ACTION_CLOSE:
  229. {
  230. //either close or select parent
  231. if (this->GetChildren().size())
  232. {
  233. if (m_ToggleButton && m_ToggleButton->GetToggleState())
  234. {
  235. Close();
  236. } else
  237. {
  238. TreeNode* pChild = (GetParent())->DynamicCastTreeNode();
  239. TreeControl* pChild2 = (GetParent())->DynamicCastTreeControl();
  240. if (pChild && !pChild2)
  241. {
  242. SetSelected(false);
  243. pChild->SetSelected(true);
  244. }
  245. }
  246. }
  247. else
  248. {
  249. TreeNode* pChild = (GetParent())->DynamicCastTreeNode();
  250. TreeControl* pChild2 = (GetParent())->DynamicCastTreeControl();
  251. if (pChild && !pChild2)
  252. {
  253. SetSelected(false);
  254. pChild->SetSelected(true);
  255. }
  256. }
  257. break;
  258. }
  259. default:
  260. {
  261. }
  262. };
  263. }
  264. if (curIndex)
  265. (*curIndex)++;
  266. bool needsRecursion = true;
  267. if (action == ITERATE_ACTION_FIND_SELECTED_INDEX || action==ITERATE_ACTION_SELECT || action==ITERATE_ACTION_DESELECT_INDEX)
  268. {
  269. if (m_ToggleButton && !m_ToggleButton->GetToggleState())
  270. {
  271. needsRecursion=false;
  272. }
  273. }
  274. if (needsRecursion)
  275. {
  276. Base::List& children = m_InnerPanel->GetChildren();
  277. for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
  278. {
  279. TreeNode* pChild = (*iter)->DynamicCastTreeNode();
  280. if ( !pChild )
  281. continue;
  282. pChild->iterate(action , curIndex, targetIndex);
  283. }
  284. }
  285. }