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.

175 lines
5.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. #pragma once
  19. //==============================================================================
  20. class StartPageTreeHolder : public Component
  21. {
  22. public:
  23. enum class Open { no, yes };
  24. StartPageTreeHolder (const StringArray& headerNames, const std::vector<StringArray>& itemNames,
  25. std::function<void (int, int)>&& selectedCallback, Open shouldBeOpen)
  26. : headers (headerNames),
  27. items (itemNames),
  28. itemSelectedCallback (std::move (selectedCallback))
  29. {
  30. jassert (headers.size() == (int) items.size());
  31. tree.setRootItem (new TreeRootItem (*this));
  32. tree.setRootItemVisible (false);
  33. tree.setIndentSize (15);
  34. tree.setDefaultOpenness (shouldBeOpen == Open::yes);
  35. addAndMakeVisible (tree);
  36. }
  37. ~StartPageTreeHolder() override
  38. {
  39. tree.deleteRootItem();
  40. }
  41. void paint (Graphics& g) override
  42. {
  43. g.fillAll (findColour (secondaryBackgroundColourId));
  44. }
  45. void resized() override
  46. {
  47. tree.setBounds (getLocalBounds());
  48. }
  49. void setSelectedItem (const String& category, int index)
  50. {
  51. auto* root = tree.getRootItem();
  52. for (int i = root->getNumSubItems(); --i >=0;)
  53. {
  54. if (auto* item = root->getSubItem (i))
  55. {
  56. if (item->getUniqueName() == category)
  57. item->getSubItem (index)->setSelected (true, true);
  58. }
  59. }
  60. }
  61. private:
  62. //==============================================================================
  63. class TreeSubItem : public TreeViewItem
  64. {
  65. public:
  66. TreeSubItem (StartPageTreeHolder& o, const String& n, const StringArray& subItems)
  67. : owner (o), name (n), isHeader (subItems.size() > 0)
  68. {
  69. for (auto& s : subItems)
  70. addSubItem (new TreeSubItem (owner, s, {}));
  71. }
  72. bool mightContainSubItems() override { return isHeader; }
  73. bool canBeSelected() const override { return ! isHeader; }
  74. int getItemWidth() const override { return -1; }
  75. int getItemHeight() const override { return 25; }
  76. String getUniqueName() const override { return name; }
  77. void paintOpenCloseButton (Graphics& g, const Rectangle<float>& area, Colour, bool isMouseOver) override
  78. {
  79. g.setColour (getOwnerView()->findColour (isSelected() ? defaultHighlightedTextColourId
  80. : treeIconColourId));
  81. TreeViewItem::paintOpenCloseButton (g, area, getOwnerView()->findColour (defaultIconColourId), isMouseOver);
  82. }
  83. void paintItem (Graphics& g, int w, int h) override
  84. {
  85. Rectangle<int> bounds (w, h);
  86. auto shouldBeHighlighted = isSelected();
  87. if (shouldBeHighlighted)
  88. {
  89. g.setColour (getOwnerView()->findColour (defaultHighlightColourId));
  90. g.fillRect (bounds);
  91. }
  92. g.setColour (shouldBeHighlighted ? getOwnerView()->findColour (defaultHighlightedTextColourId)
  93. : getOwnerView()->findColour (defaultTextColourId));
  94. g.drawFittedText (name, bounds.reduced (5).withTrimmedLeft (10), Justification::centredLeft, 1);
  95. }
  96. void itemClicked (const MouseEvent&) override
  97. {
  98. if (isSelected())
  99. itemSelectionChanged (true);
  100. }
  101. void itemSelectionChanged (bool isNowSelected) override
  102. {
  103. jassert (! isHeader);
  104. if (isNowSelected)
  105. owner.itemSelectedCallback (getParentItem()->getIndexInParent(), getIndexInParent());
  106. }
  107. private:
  108. StartPageTreeHolder& owner;
  109. String name;
  110. bool isHeader = false;
  111. //==============================================================================
  112. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeSubItem)
  113. };
  114. struct TreeRootItem : public TreeViewItem
  115. {
  116. explicit TreeRootItem (StartPageTreeHolder& o)
  117. : owner (o)
  118. {
  119. for (int i = 0; i < owner.headers.size(); ++i)
  120. addSubItem (new TreeSubItem (owner, owner.headers[i], owner.items[(size_t) i]));
  121. }
  122. bool mightContainSubItems() override { return ! owner.headers.isEmpty();}
  123. StartPageTreeHolder& owner;
  124. //==============================================================================
  125. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeRootItem)
  126. };
  127. //==============================================================================
  128. TreeView tree;
  129. StringArray headers;
  130. std::vector<StringArray> items;
  131. std::function<void (int, int)> itemSelectedCallback;
  132. //==============================================================================
  133. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StartPageTreeHolder)
  134. };