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.

276 lines
8.5KB

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