The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

273 lines
8.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../jucedemo_headers.h"
  19. //==============================================================================
  20. class TreeViewDemoItem : public TreeViewItem
  21. {
  22. public:
  23. TreeViewDemoItem (XmlElement& xml_)
  24. : xml (xml_)
  25. {
  26. }
  27. ~TreeViewDemoItem()
  28. {
  29. }
  30. int getItemWidth() const
  31. {
  32. return xml.getIntAttribute ("width", -1);
  33. }
  34. const String getUniqueName() const
  35. {
  36. return xml.getTagName();
  37. }
  38. bool mightContainSubItems()
  39. {
  40. return xml.getFirstChildElement() != 0;
  41. }
  42. void paintItem (Graphics& g, int width, int height)
  43. {
  44. // if this item is selected, fill it with a background colour..
  45. if (isSelected())
  46. g.fillAll (Colours::blue.withAlpha (0.3f));
  47. // use a "colour" attribute in the xml tag for this node to set the text colour..
  48. g.setColour (Colour (xml.getStringAttribute ("colour", "ff000000").getHexValue32()));
  49. g.setFont (height * 0.7f);
  50. // draw the xml element's tag name..
  51. g.drawText (xml.getTagName(),
  52. 4, 0, width - 4, height,
  53. Justification::centredLeft, true);
  54. }
  55. void itemOpennessChanged (bool isNowOpen)
  56. {
  57. if (isNowOpen)
  58. {
  59. // if we've not already done so, we'll now add the tree's sub-items. You could
  60. // also choose to delete the existing ones and refresh them if that's more suitable
  61. // in your app.
  62. if (getNumSubItems() == 0)
  63. {
  64. // create and add sub-items to this node of the tree, corresponding to
  65. // each sub-element in the XML..
  66. forEachXmlChildElement (xml, child)
  67. {
  68. jassert (child != 0);
  69. addSubItem (new TreeViewDemoItem (*child));
  70. }
  71. }
  72. }
  73. else
  74. {
  75. // in this case, we'll leave any sub-items in the tree when the node gets closed,
  76. // though you could choose to delete them if that's more appropriate for
  77. // your application.
  78. }
  79. }
  80. const var getDragSourceDescription()
  81. {
  82. return "TreeView Items";
  83. }
  84. private:
  85. XmlElement& xml;
  86. };
  87. //==============================================================================
  88. class TreeViewDemo : public Component,
  89. public DragAndDropContainer,
  90. public ButtonListener
  91. {
  92. public:
  93. //==============================================================================
  94. TreeViewDemo()
  95. : treeView (0),
  96. thread ("Demo file tree thread"),
  97. typeButton ("Type of treeview...")
  98. {
  99. setName ("Tree Views");
  100. {
  101. const String treeXmlString (BinaryData::treedemo_xml);
  102. XmlDocument parser (treeXmlString);
  103. treeXml = parser.getDocumentElement();
  104. jassert (treeXml != nullptr);
  105. }
  106. rootItem = new TreeViewDemoItem (*treeXml);
  107. rootItem->setOpen (true);
  108. // find the root of the user's home drive, and set that as our root..
  109. File folder (File::getSpecialLocation (File::userHomeDirectory));
  110. while (folder.getParentDirectory() != folder)
  111. folder = folder.getParentDirectory();
  112. directoryList = new DirectoryContentsList (0, thread);
  113. directoryList->setDirectory (folder, true, true);
  114. thread.startThread (3);
  115. addAndMakeVisible (&typeButton);
  116. typeButton.addListener (this);
  117. typeButton.setAlwaysOnTop (true);
  118. typeButton.setTriggeredOnMouseDown (true);
  119. showCustomTreeView();
  120. }
  121. ~TreeViewDemo()
  122. {
  123. treeView = nullptr;
  124. fileTreeComp = nullptr;
  125. directoryList = nullptr; // (need to make sure this is deleted before the TimeSliceThread)
  126. }
  127. void paint (Graphics& g)
  128. {
  129. g.setColour (Colours::grey);
  130. if (treeView != nullptr)
  131. g.drawRect (treeView->getX(), treeView->getY(),
  132. treeView->getWidth(), treeView->getHeight());
  133. if (fileTreeComp != nullptr)
  134. g.drawRect (fileTreeComp->getX(), fileTreeComp->getY(),
  135. fileTreeComp->getWidth(), fileTreeComp->getHeight());
  136. }
  137. void resized()
  138. {
  139. if (treeView != nullptr)
  140. treeView->setBoundsInset (BorderSize<int> (40, 10, 10, 10));
  141. else if (fileTreeComp != nullptr)
  142. fileTreeComp->setBoundsInset (BorderSize<int> (40, 10, 10, 10));
  143. typeButton.changeWidthToFitText (22);
  144. typeButton.setTopLeftPosition (10, 10);
  145. }
  146. void showCustomTreeView()
  147. {
  148. treeView = nullptr;
  149. fileTreeComp = nullptr;
  150. addAndMakeVisible (treeView = new TreeView());
  151. treeView->setRootItem (rootItem);
  152. treeView->setMultiSelectEnabled (true);
  153. resized();
  154. }
  155. void showFileTreeComp()
  156. {
  157. treeView = nullptr;
  158. fileTreeComp = nullptr;
  159. addAndMakeVisible (fileTreeComp = new FileTreeComponent (*directoryList));
  160. resized();
  161. }
  162. void buttonClicked (Button*)
  163. {
  164. PopupMenu m;
  165. m.addItem (1, "Custom treeview showing an XML tree");
  166. m.addItem (2, "FileTreeComponent showing the file system");
  167. m.addSeparator();
  168. m.addItem (3, "Show root item", true,
  169. treeView != nullptr ? treeView->isRootItemVisible()
  170. : fileTreeComp->isRootItemVisible());
  171. m.addItem (4, "Show open/close buttons", true,
  172. treeView != nullptr ? treeView->areOpenCloseButtonsVisible()
  173. : fileTreeComp->areOpenCloseButtonsVisible());
  174. m.showMenuAsync (PopupMenu::Options().withTargetComponent (&typeButton),
  175. ModalCallbackFunction::forComponent (menuItemChosenCallback, this));
  176. }
  177. static void menuItemChosenCallback (int result, TreeViewDemo* demoComponent)
  178. {
  179. if (demoComponent != nullptr)
  180. demoComponent->menuItemChosenCallback (result);
  181. }
  182. void menuItemChosenCallback (int result)
  183. {
  184. if (result == 1)
  185. {
  186. showCustomTreeView();
  187. }
  188. else if (result == 2)
  189. {
  190. showFileTreeComp();
  191. }
  192. else if (result == 3)
  193. {
  194. if (treeView != nullptr)
  195. treeView->setRootItemVisible (! treeView->isRootItemVisible());
  196. else if (fileTreeComp != nullptr)
  197. fileTreeComp->setRootItemVisible (! fileTreeComp->isRootItemVisible());
  198. }
  199. else if (result == 4)
  200. {
  201. if (treeView != nullptr)
  202. treeView->setOpenCloseButtonsVisible (! treeView->areOpenCloseButtonsVisible());
  203. else if (fileTreeComp != nullptr)
  204. fileTreeComp->setOpenCloseButtonsVisible (! fileTreeComp->areOpenCloseButtonsVisible());
  205. }
  206. }
  207. private:
  208. ScopedPointer <XmlElement> treeXml;
  209. ScopedPointer <TreeViewItem> rootItem;
  210. ScopedPointer <TreeView> treeView;
  211. ScopedPointer <FileTreeComponent> fileTreeComp;
  212. ScopedPointer <DirectoryContentsList> directoryList;
  213. TimeSliceThread thread;
  214. TextButton typeButton;
  215. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeViewDemo);
  216. };
  217. //==============================================================================
  218. Component* createTreeViewDemo()
  219. {
  220. return new TreeViewDemo();
  221. }