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.

265 lines
7.9KB

  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. JucerTreeViewBase::JucerTreeViewBase()
  22. : textX (0)
  23. {
  24. setLinesDrawnForSubItems (false);
  25. }
  26. void JucerTreeViewBase::refreshSubItems()
  27. {
  28. WholeTreeOpennessRestorer openness (*this);
  29. clearSubItems();
  30. addSubItems();
  31. }
  32. Font JucerTreeViewBase::getFont() const
  33. {
  34. return Font (getItemHeight() * 0.6f);
  35. }
  36. void JucerTreeViewBase::paintItem (Graphics& g, int width, int height)
  37. {
  38. if (isSelected())
  39. g.fillAll (Colour (0x401111ee));
  40. }
  41. void JucerTreeViewBase::paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver)
  42. {
  43. Path p;
  44. if (isOpen())
  45. p.addTriangle (width * 0.2f, height * 0.25f, width * 0.8f, height * 0.25f, width * 0.5f, height * 0.75f);
  46. else
  47. p.addTriangle (width * 0.25f, height * 0.25f, width * 0.8f, height * 0.5f, width * 0.25f, height * 0.75f);
  48. g.setColour (Colours::lightgrey);
  49. g.fillPath (p);
  50. }
  51. //==============================================================================
  52. class TreeItemComponent : public Component
  53. {
  54. public:
  55. TreeItemComponent (JucerTreeViewBase& item_)
  56. : item (item_)
  57. {
  58. setInterceptsMouseClicks (false, true);
  59. item.createLeftEdgeComponents (leftComps);
  60. for (int i = 0; i < leftComps.size(); ++i)
  61. addAndMakeVisible (leftComps.getUnchecked(i));
  62. addAndMakeVisible (rightHandComponent = item.createRightEdgeComponent());
  63. }
  64. void paint (Graphics& g)
  65. {
  66. g.setColour (Colours::black);
  67. const int height = getHeight();
  68. item.getIcon()->drawWithin (g, Rectangle<float> (0.0f, 2.0f, height + 6.0f, height - 4.0f),
  69. RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, 1.0f);
  70. g.setFont (item.getFont());
  71. g.setColour (item.isMissing() ? Colours::red : Colours::black);
  72. const int right = rightHandComponent != nullptr ? rightHandComponent->getX() - 2
  73. : getWidth();
  74. g.drawFittedText (item.getDisplayName(),
  75. item.textX, 0, right - item.textX, height, Justification::centredLeft, 1, 0.8f);
  76. }
  77. void resized()
  78. {
  79. const int edge = 1;
  80. const int itemSize = getHeight() - edge * 2;
  81. item.textX = (leftComps.size() + 1) * getHeight() + 8;
  82. for (int i = 0; i < leftComps.size(); ++i)
  83. leftComps.getUnchecked(i)->setBounds (5 + (i + 1) * getHeight(), edge, itemSize, itemSize);
  84. if (rightHandComponent != nullptr)
  85. rightHandComponent->setBounds (getWidth() - itemSize - edge, edge, itemSize, itemSize);
  86. }
  87. private:
  88. JucerTreeViewBase& item;
  89. OwnedArray<Component> leftComps;
  90. ScopedPointer<Component> rightHandComponent;
  91. };
  92. Component* JucerTreeViewBase::createItemComponent()
  93. {
  94. return new TreeItemComponent (*this);
  95. }
  96. //==============================================================================
  97. class RenameTreeItemCallback : public ModalComponentManager::Callback,
  98. public TextEditorListener
  99. {
  100. public:
  101. RenameTreeItemCallback (JucerTreeViewBase& item_, Component& parent, const Rectangle<int>& bounds)
  102. : item (item_)
  103. {
  104. ed.setMultiLine (false, false);
  105. ed.setPopupMenuEnabled (false);
  106. ed.setSelectAllWhenFocused (true);
  107. ed.setFont (item.getFont());
  108. ed.addListener (this);
  109. ed.setText (item.getRenamingName());
  110. ed.setBounds (bounds);
  111. parent.addAndMakeVisible (&ed);
  112. ed.enterModalState (true, this);
  113. }
  114. void modalStateFinished (int resultCode)
  115. {
  116. if (resultCode != 0)
  117. item.setName (ed.getText());
  118. }
  119. void textEditorTextChanged (TextEditor&) {}
  120. void textEditorReturnKeyPressed (TextEditor& editor) { editor.exitModalState (1); }
  121. void textEditorEscapeKeyPressed (TextEditor& editor) { editor.exitModalState (0); }
  122. void textEditorFocusLost (TextEditor& editor) { editor.exitModalState (0); }
  123. private:
  124. TextEditor ed;
  125. JucerTreeViewBase& item;
  126. JUCE_DECLARE_NON_COPYABLE (RenameTreeItemCallback);
  127. };
  128. void JucerTreeViewBase::showRenameBox()
  129. {
  130. Rectangle<int> r (getItemPosition (true));
  131. r.setLeft (r.getX() + textX);
  132. r.setHeight (getItemHeight());
  133. new RenameTreeItemCallback (*this, *getOwnerView(), r);
  134. }
  135. void JucerTreeViewBase::itemClicked (const MouseEvent& e)
  136. {
  137. if (e.mods.isPopupMenu())
  138. {
  139. if (getOwnerView()->getNumSelectedItems() > 1)
  140. showMultiSelectionPopupMenu();
  141. else
  142. showPopupMenu();
  143. }
  144. }
  145. void JucerTreeViewBase::deleteItem() {}
  146. void JucerTreeViewBase::deleteAllSelectedItems() {}
  147. void JucerTreeViewBase::showDocument() {}
  148. void JucerTreeViewBase::showPopupMenu() {}
  149. void JucerTreeViewBase::showMultiSelectionPopupMenu() {}
  150. static void treeViewMenuItemChosen (int resultCode, JucerTreeViewBase* item)
  151. {
  152. item->handlePopupMenuResult (resultCode);
  153. }
  154. void JucerTreeViewBase::launchPopupMenu (PopupMenu& m)
  155. {
  156. m.showMenuAsync (PopupMenu::Options(),
  157. ModalCallbackFunction::create (treeViewMenuItemChosen, this));
  158. }
  159. void JucerTreeViewBase::handlePopupMenuResult (int)
  160. {
  161. }
  162. ProjectContentComponent* JucerTreeViewBase::getProjectContentComponent() const
  163. {
  164. Component* c = getOwnerView();
  165. while (c != nullptr)
  166. {
  167. ProjectContentComponent* pcc = dynamic_cast <ProjectContentComponent*> (c);
  168. if (pcc != nullptr)
  169. return pcc;
  170. c = c->getParentComponent();
  171. }
  172. return 0;
  173. }
  174. //==============================================================================
  175. class JucerTreeViewBase::ItemSelectionTimer : public Timer
  176. {
  177. public:
  178. ItemSelectionTimer (JucerTreeViewBase& owner_) : owner (owner_) {}
  179. void timerCallback() { owner.invokeShowDocument(); }
  180. private:
  181. JucerTreeViewBase& owner;
  182. JUCE_DECLARE_NON_COPYABLE (ItemSelectionTimer);
  183. };
  184. void JucerTreeViewBase::itemSelectionChanged (bool isNowSelected)
  185. {
  186. if (isNowSelected)
  187. {
  188. delayedSelectionTimer = new ItemSelectionTimer (*this);
  189. delayedSelectionTimer->startTimer (getMillisecsAllowedForDragGesture());
  190. }
  191. else
  192. {
  193. cancelDelayedSelectionTimer();
  194. }
  195. }
  196. void JucerTreeViewBase::invokeShowDocument()
  197. {
  198. cancelDelayedSelectionTimer();
  199. showDocument();
  200. }
  201. void JucerTreeViewBase::itemDoubleClicked (const MouseEvent& e)
  202. {
  203. invokeShowDocument();
  204. }
  205. void JucerTreeViewBase::cancelDelayedSelectionTimer()
  206. {
  207. delayedSelectionTimer = nullptr;
  208. }