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.

288 lines
8.6KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 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 "jucer_JucerTreeViewBase.h"
  19. #include "../Project/jucer_ProjectContentComponent.h"
  20. //==============================================================================
  21. void TreePanelBase::setRoot (JucerTreeViewBase* root)
  22. {
  23. rootItem = root;
  24. tree.setRootItem (root);
  25. tree.getRootItem()->setOpen (true);
  26. if (project != nullptr)
  27. {
  28. const ScopedPointer<XmlElement> treeOpenness (project->getStoredProperties()
  29. .getXmlValue (opennessStateKey));
  30. if (treeOpenness != nullptr)
  31. {
  32. tree.restoreOpennessState (*treeOpenness, true);
  33. for (int i = tree.getNumSelectedItems(); --i >= 0;)
  34. {
  35. JucerTreeViewBase* item = dynamic_cast<JucerTreeViewBase*> (tree.getSelectedItem (i));
  36. if (item != nullptr)
  37. item->cancelDelayedSelectionTimer();
  38. }
  39. }
  40. }
  41. }
  42. void TreePanelBase::saveOpenness()
  43. {
  44. if (project != nullptr)
  45. {
  46. const ScopedPointer<XmlElement> opennessState (tree.getOpennessState (true));
  47. if (opennessState != nullptr)
  48. project->getStoredProperties().setValue (opennessStateKey, opennessState);
  49. else
  50. project->getStoredProperties().removeValue (opennessStateKey);
  51. }
  52. }
  53. //==============================================================================
  54. JucerTreeViewBase::JucerTreeViewBase() : textX (0)
  55. {
  56. setLinesDrawnForSubItems (false);
  57. }
  58. JucerTreeViewBase::~JucerTreeViewBase()
  59. {
  60. masterReference.clear();
  61. }
  62. void JucerTreeViewBase::refreshSubItems()
  63. {
  64. WholeTreeOpennessRestorer openness (*this);
  65. clearSubItems();
  66. addSubItems();
  67. }
  68. Font JucerTreeViewBase::getFont() const
  69. {
  70. return Font (getItemHeight() * 0.6f);
  71. }
  72. void JucerTreeViewBase::paintItem (Graphics& g, int width, int height)
  73. {
  74. if (isSelected())
  75. g.fillAll (getOwnerView()->findColour (treeviewHighlightColourId));
  76. }
  77. float JucerTreeViewBase::getIconSize() const
  78. {
  79. return jmin (getItemHeight() - 4.0f, 18.0f);
  80. }
  81. void JucerTreeViewBase::paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver)
  82. {
  83. Path p;
  84. if (isOpen())
  85. p.addTriangle (width * 0.2f, height * 0.25f, width * 0.8f, height * 0.25f, width * 0.5f, height * 0.75f);
  86. else
  87. p.addTriangle (width * 0.25f, height * 0.25f, width * 0.8f, height * 0.5f, width * 0.25f, height * 0.75f);
  88. g.setColour (getOwnerView()->findColour (mainBackgroundColourId).contrasting (0.3f));
  89. g.fillPath (p);
  90. }
  91. Colour JucerTreeViewBase::getBackgroundColour() const
  92. {
  93. Colour background (getOwnerView()->findColour (mainBackgroundColourId));
  94. if (isSelected())
  95. background = background.overlaidWith (getOwnerView()->findColour (treeviewHighlightColourId));
  96. return background;
  97. }
  98. Colour JucerTreeViewBase::getContrastingColour (float contrast) const
  99. {
  100. return getBackgroundColour().contrasting (contrast);
  101. }
  102. Colour JucerTreeViewBase::getContrastingColour (const Colour& target, float minContrast) const
  103. {
  104. return getBackgroundColour().contrasting (target, minContrast);
  105. }
  106. void JucerTreeViewBase::paintContent (Graphics& g, const Rectangle<int>& area)
  107. {
  108. g.setFont (getFont());
  109. g.setColour (isMissing() ? getContrastingColour (Colours::red, 0.8f)
  110. : getContrastingColour (0.8f));
  111. g.drawFittedText (getDisplayName(), area, Justification::centredLeft, 1, 0.8f);
  112. }
  113. Component* JucerTreeViewBase::createItemComponent()
  114. {
  115. return new TreeItemComponent (*this);
  116. }
  117. //==============================================================================
  118. class RenameTreeItemCallback : public ModalComponentManager::Callback,
  119. public TextEditorListener
  120. {
  121. public:
  122. RenameTreeItemCallback (JucerTreeViewBase& item_, Component& parent, const Rectangle<int>& bounds)
  123. : item (item_)
  124. {
  125. ed.setMultiLine (false, false);
  126. ed.setPopupMenuEnabled (false);
  127. ed.setSelectAllWhenFocused (true);
  128. ed.setFont (item.getFont());
  129. ed.addListener (this);
  130. ed.setText (item.getRenamingName());
  131. ed.setBounds (bounds);
  132. parent.addAndMakeVisible (&ed);
  133. ed.enterModalState (true, this);
  134. }
  135. void modalStateFinished (int resultCode)
  136. {
  137. if (resultCode != 0)
  138. item.setName (ed.getText());
  139. }
  140. void textEditorTextChanged (TextEditor&) {}
  141. void textEditorReturnKeyPressed (TextEditor& editor) { editor.exitModalState (1); }
  142. void textEditorEscapeKeyPressed (TextEditor& editor) { editor.exitModalState (0); }
  143. void textEditorFocusLost (TextEditor& editor) { editor.exitModalState (0); }
  144. private:
  145. TextEditor ed;
  146. JucerTreeViewBase& item;
  147. JUCE_DECLARE_NON_COPYABLE (RenameTreeItemCallback);
  148. };
  149. void JucerTreeViewBase::showRenameBox()
  150. {
  151. Rectangle<int> r (getItemPosition (true));
  152. r.setLeft (r.getX() + textX);
  153. r.setHeight (getItemHeight());
  154. new RenameTreeItemCallback (*this, *getOwnerView(), r);
  155. }
  156. void JucerTreeViewBase::itemClicked (const MouseEvent& e)
  157. {
  158. if (e.mods.isPopupMenu())
  159. {
  160. if (getOwnerView()->getNumSelectedItems() > 1)
  161. showMultiSelectionPopupMenu();
  162. else
  163. showPopupMenu();
  164. }
  165. }
  166. void JucerTreeViewBase::deleteItem() {}
  167. void JucerTreeViewBase::deleteAllSelectedItems() {}
  168. void JucerTreeViewBase::showDocument() {}
  169. void JucerTreeViewBase::showPopupMenu() {}
  170. void JucerTreeViewBase::showMultiSelectionPopupMenu() {}
  171. static void treeViewMenuItemChosen (int resultCode, WeakReference<JucerTreeViewBase> item)
  172. {
  173. if (item != nullptr)
  174. item->handlePopupMenuResult (resultCode);
  175. }
  176. void JucerTreeViewBase::launchPopupMenu (PopupMenu& m)
  177. {
  178. m.showMenuAsync (PopupMenu::Options(),
  179. ModalCallbackFunction::create (treeViewMenuItemChosen, WeakReference<JucerTreeViewBase> (this)));
  180. }
  181. void JucerTreeViewBase::handlePopupMenuResult (int)
  182. {
  183. }
  184. ProjectContentComponent* JucerTreeViewBase::getProjectContentComponent() const
  185. {
  186. Component* c = getOwnerView();
  187. while (c != nullptr)
  188. {
  189. ProjectContentComponent* pcc = dynamic_cast <ProjectContentComponent*> (c);
  190. if (pcc != nullptr)
  191. return pcc;
  192. c = c->getParentComponent();
  193. }
  194. return nullptr;
  195. }
  196. //==============================================================================
  197. class JucerTreeViewBase::ItemSelectionTimer : public Timer
  198. {
  199. public:
  200. ItemSelectionTimer (JucerTreeViewBase& owner_) : owner (owner_) {}
  201. void timerCallback() { owner.invokeShowDocument(); }
  202. private:
  203. JucerTreeViewBase& owner;
  204. JUCE_DECLARE_NON_COPYABLE (ItemSelectionTimer);
  205. };
  206. void JucerTreeViewBase::itemSelectionChanged (bool isNowSelected)
  207. {
  208. if (isNowSelected)
  209. {
  210. delayedSelectionTimer = new ItemSelectionTimer (*this);
  211. delayedSelectionTimer->startTimer (getMillisecsAllowedForDragGesture());
  212. }
  213. else
  214. {
  215. cancelDelayedSelectionTimer();
  216. }
  217. }
  218. void JucerTreeViewBase::invokeShowDocument()
  219. {
  220. cancelDelayedSelectionTimer();
  221. showDocument();
  222. }
  223. void JucerTreeViewBase::itemDoubleClicked (const MouseEvent& e)
  224. {
  225. invokeShowDocument();
  226. }
  227. void JucerTreeViewBase::cancelDelayedSelectionTimer()
  228. {
  229. delayedSelectionTimer = nullptr;
  230. }