/* ============================================================================== This file is part of the JUCE 6 technical preview. Copyright (c) 2020 - Raw Material Software Limited You may use this code under the terms of the GPL v3 (see www.gnu.org/licenses). For this technical preview, this file is not subject to commercial licensing. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ #pragma once //============================================================================== class StartPageTreeHolder : public Component { public: enum class Open { no, yes }; StartPageTreeHolder (const StringArray& headerNames, const std::vector& itemNames, std::function&& selectedCallback, Open shouldBeOpen) : headers (headerNames), items (itemNames), itemSelectedCallback (std::move (selectedCallback)) { jassert (headers.size() == (int) items.size()); tree.setRootItem (new TreeRootItem (*this)); tree.setRootItemVisible (false); tree.setIndentSize (15); tree.setDefaultOpenness (shouldBeOpen == Open::yes); addAndMakeVisible (tree); } ~StartPageTreeHolder() override { tree.deleteRootItem(); } void paint (Graphics& g) override { g.fillAll (findColour (secondaryBackgroundColourId)); } void resized() override { tree.setBounds (getLocalBounds()); } void setSelectedItem (const String& category, int index) { auto* root = tree.getRootItem(); for (int i = root->getNumSubItems(); --i >=0;) { if (auto* item = root->getSubItem (i)) { if (item->getUniqueName() == category) item->getSubItem (index)->setSelected (true, true); } } } private: //============================================================================== class TreeSubItem : public TreeViewItem { public: TreeSubItem (StartPageTreeHolder& o, const String& n, const StringArray& subItems) : owner (o), name (n), isHeader (subItems.size() > 0) { for (auto& s : subItems) addSubItem (new TreeSubItem (owner, s, {})); } bool mightContainSubItems() override { return isHeader; } bool canBeSelected() const override { return ! isHeader; } int getItemWidth() const override { return -1; } int getItemHeight() const override { return 25; } String getUniqueName() const override { return name; } void paintOpenCloseButton (Graphics& g, const Rectangle& area, Colour, bool isMouseOver) override { g.setColour (getOwnerView()->findColour (isSelected() ? defaultHighlightedTextColourId : treeIconColourId)); TreeViewItem::paintOpenCloseButton (g, area, getOwnerView()->findColour (defaultIconColourId), isMouseOver); } void paintItem (Graphics& g, int w, int h) override { Rectangle bounds (w, h); auto shouldBeHighlighted = isSelected(); if (shouldBeHighlighted) { g.setColour (getOwnerView()->findColour (defaultHighlightColourId)); g.fillRect (bounds); } g.setColour (shouldBeHighlighted ? getOwnerView()->findColour (defaultHighlightedTextColourId) : getOwnerView()->findColour (defaultTextColourId)); g.drawFittedText (name, bounds.reduced (5).withTrimmedLeft (10), Justification::centredLeft, 1); } void itemClicked (const MouseEvent&) override { if (isSelected()) itemSelectionChanged (true); } void itemSelectionChanged (bool isNowSelected) override { jassert (! isHeader); if (isNowSelected) owner.itemSelectedCallback (getParentItem()->getIndexInParent(), getIndexInParent()); } private: StartPageTreeHolder& owner; String name; bool isHeader = false; //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeSubItem) }; struct TreeRootItem : public TreeViewItem { explicit TreeRootItem (StartPageTreeHolder& o) : owner (o) { for (int i = 0; i < owner.headers.size(); ++i) addSubItem (new TreeSubItem (owner, owner.headers[i], owner.items[(size_t) i])); } bool mightContainSubItems() override { return ! owner.headers.isEmpty();} StartPageTreeHolder& owner; //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeRootItem) }; //============================================================================== TreeView tree; StringArray headers; std::vector items; std::function itemSelectedCallback; //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StartPageTreeHolder) };