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.

176 lines
6.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 7 technical preview.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. You may use this code under the terms of the GPL v3
  6. (see www.gnu.org/licenses).
  7. For the technical preview this file cannot be licensed commercially.
  8. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  9. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  10. DISCLAIMED.
  11. ==============================================================================
  12. */
  13. #pragma once
  14. //==============================================================================
  15. class StartPageTreeHolder : public Component
  16. {
  17. public:
  18. enum class Open { no, yes };
  19. StartPageTreeHolder (const String& title,
  20. const StringArray& headerNames,
  21. const std::vector<StringArray>& itemNames,
  22. std::function<void (int, int)>&& selectedCallback,
  23. Open shouldBeOpen)
  24. : headers (headerNames),
  25. items (itemNames),
  26. itemSelectedCallback (std::move (selectedCallback))
  27. {
  28. jassert (headers.size() == (int) items.size());
  29. tree.setTitle (title);
  30. tree.setRootItem (new TreeRootItem (*this));
  31. tree.setRootItemVisible (false);
  32. tree.setIndentSize (15);
  33. tree.setDefaultOpenness (shouldBeOpen == Open::yes);
  34. addAndMakeVisible (tree);
  35. }
  36. ~StartPageTreeHolder() override
  37. {
  38. tree.deleteRootItem();
  39. }
  40. void paint (Graphics& g) override
  41. {
  42. g.fillAll (findColour (secondaryBackgroundColourId));
  43. }
  44. void resized() override
  45. {
  46. tree.setBounds (getLocalBounds());
  47. }
  48. void setSelectedItem (const String& category, int index)
  49. {
  50. auto* root = tree.getRootItem();
  51. for (int i = root->getNumSubItems(); --i >=0;)
  52. {
  53. if (auto* item = root->getSubItem (i))
  54. {
  55. if (item->getUniqueName() == category)
  56. item->getSubItem (index)->setSelected (true, true);
  57. }
  58. }
  59. }
  60. private:
  61. //==============================================================================
  62. class TreeSubItem : public TreeViewItem
  63. {
  64. public:
  65. TreeSubItem (StartPageTreeHolder& o, const String& n, const StringArray& subItemsIn)
  66. : owner (o), name (n), isHeader (subItemsIn.size() > 0)
  67. {
  68. for (auto& s : subItemsIn)
  69. addSubItem (new TreeSubItem (owner, s, {}));
  70. }
  71. bool mightContainSubItems() override { return isHeader; }
  72. bool canBeSelected() const override { return ! isHeader; }
  73. int getItemWidth() const override { return -1; }
  74. int getItemHeight() const override { return 25; }
  75. String getUniqueName() const override { return name; }
  76. String getAccessibilityName() override { return getUniqueName(); }
  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& e) override
  97. {
  98. if (isSelected())
  99. itemSelectionChanged (true);
  100. if (e.mods.isPopupMenu() && mightContainSubItems())
  101. setOpen (! isOpen());
  102. }
  103. void itemSelectionChanged (bool isNowSelected) override
  104. {
  105. jassert (! isHeader);
  106. if (isNowSelected)
  107. owner.itemSelectedCallback (getParentItem()->getIndexInParent(), getIndexInParent());
  108. }
  109. private:
  110. StartPageTreeHolder& owner;
  111. String name;
  112. bool isHeader = false;
  113. //==============================================================================
  114. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeSubItem)
  115. };
  116. struct TreeRootItem : public TreeViewItem
  117. {
  118. explicit TreeRootItem (StartPageTreeHolder& o)
  119. : owner (o)
  120. {
  121. for (int i = 0; i < owner.headers.size(); ++i)
  122. addSubItem (new TreeSubItem (owner, owner.headers[i], owner.items[(size_t) i]));
  123. }
  124. bool mightContainSubItems() override { return ! owner.headers.isEmpty();}
  125. StartPageTreeHolder& owner;
  126. //==============================================================================
  127. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeRootItem)
  128. };
  129. //==============================================================================
  130. TreeView tree;
  131. StringArray headers;
  132. std::vector<StringArray> items;
  133. std::function<void (int, int)> itemSelectedCallback;
  134. //==============================================================================
  135. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StartPageTreeHolder)
  136. };