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.

269 lines
8.6KB

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