1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12 
13    End User License Agreement: www.juce.com/juce-6-licence
14    Privacy Policy: www.juce.com/juce-privacy-policy
15 
16    Or: You may also use this code under the terms of the GPL v3 (see
17    www.gnu.org/licenses).
18 
19    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21    DISCLAIMED.
22 
23   ==============================================================================
24 */
25 
26 
27 namespace juce
28 {
29 
30 //==============================================================================
31 /**
32     A PropertyComponent that shows its value as an expandable list of ToggleButtons.
33 
34     This type of property component contains a list of options where multiple options
35     can be selected at once.
36 
37     @see PropertyComponent, PropertyPanel
38 
39     @tags{GUI}
40 */
41 class MultiChoicePropertyComponent    : public PropertyComponent
42 {
43 private:
44     /** Delegating constructor. */
45     MultiChoicePropertyComponent (const String&, const StringArray&, const Array<var>&);
46 
47 public:
48     /** Creates the component. Note that the underlying var object that the Value refers to must be an array.
49 
50         @param valueToControl       the value that the ToggleButtons will read and control
51         @param propertyName         the name of the property
52         @param choices              the list of possible values that will be represented
53         @param correspondingValues  a list of values corresponding to each item in the 'choices' StringArray.
54                                     These are the values that will be read and written to the
55                                     valueToControl value. This array must contain the same number of items
56                                     as the choices array
57         @param maxChoices           the maximum number of values which can be selected at once. The default of
58                                     -1 will not limit the number that can be selected
59     */
60     MultiChoicePropertyComponent (const Value& valueToControl,
61                                   const String& propertyName,
62                                   const StringArray& choices,
63                                   const Array<var>& correspondingValues,
64                                   int maxChoices = -1);
65 
66     /** Creates the component using a ValueWithDefault object. This will select the default options.
67 
68         @param valueToControl       the ValueWithDefault object that contains the Value object that the ToggleButtons will read and control.
69         @param propertyName         the name of the property
70         @param choices              the list of possible values that will be represented
71         @param correspondingValues  a list of values corresponding to each item in the 'choices' StringArray.
72                                     These are the values that will be read and written to the
73                                     valueToControl value. This array must contain the same number of items
74                                     as the choices array
75         @param maxChoices           the maximum number of values which can be selected at once. The default of
76                                     -1 will not limit the number that can be selected
77     */
78     MultiChoicePropertyComponent (ValueWithDefault& valueToControl,
79                                   const String& propertyName,
80                                   const StringArray& choices,
81                                   const Array<var>& correspondingValues,
82                                   int maxChoices = -1);
83 
84     ~MultiChoicePropertyComponent() override;
85 
86     //==============================================================================
87     /** Returns true if the list of options is expanded. */
isExpanded()88     bool isExpanded() const noexcept    { return expanded; }
89 
90     /** Returns true if the list of options has been truncated and can be expanded. */
isExpandable()91     bool isExpandable() const noexcept  { return expandable; }
92 
93     /** Expands or shrinks the list of options if they are not all visible.
94 
95         N.B. This will just set the preferredHeight value of the PropertyComponent and attempt to
96         call PropertyPanel::resized(), so if you are not displaying this object in a PropertyPanel
97         then you should use the onHeightChange callback to resize it when the height changes.
98 
99         @see onHeightChange
100     */
101     void setExpanded (bool expanded) noexcept;
102 
103     /** You can assign a lambda to this callback object to have it called when the MultiChoicePropertyComponent height changes. */
104     std::function<void()> onHeightChange;
105 
106     //==============================================================================
107     /** @internal */
108     void paint (Graphics& g) override;
109     /** @internal */
110     void resized() override;
111     /** @internal */
refresh()112     void refresh() override {}
113 
114 private:
115     //==============================================================================
116     class MultiChoiceRemapperSource;
117     class MultiChoiceRemapperSourceWithDefault;
118 
119     //==============================================================================
120     static int getTotalButtonsHeight (int);
121     void lookAndFeelChanged() override;
122 
123     //==============================================================================
124     WeakReference<ValueWithDefault> valueWithDefault;
125 
126     static constexpr int collapsedHeight = 125;
127     static constexpr int buttonHeight = 25;
128     static constexpr int expandAreaHeight = 20;
129 
130     int maxHeight = 0, numHidden = 0;
131     bool expandable = false, expanded = false;
132 
133     OwnedArray<ToggleButton> choiceButtons;
134     ShapeButton expandButton { "Expand", Colours::transparentBlack, Colours::transparentBlack, Colours::transparentBlack };
135 
136     //==============================================================================
137     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultiChoicePropertyComponent)
138 };
139 
140 } // namespace juce
141