Browse Source

Various improvements to MultiChoicePropertyComponent such as setting a max number of selectable values and displaying the default values

tags/2021-05-28
ed 7 years ago
parent
commit
51ff1daf60
2 changed files with 89 additions and 19 deletions
  1. +81
    -17
      modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.cpp
  2. +8
    -2
      modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.h

+ 81
- 17
modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.cpp View File

@@ -48,9 +48,10 @@ class MultiChoicePropertyComponent::MultiChoiceRemapperSource : public Value:
private Value::Listener private Value::Listener
{ {
public: public:
MultiChoiceRemapperSource (const Value& source, var v)
MultiChoiceRemapperSource (const Value& source, var v, int c)
: sourceValue (source), : sourceValue (source),
varToControl (v)
varToControl (v),
maxChoices (c)
{ {
sourceValue.addListener (this); sourceValue.addListener (this);
} }
@@ -71,9 +72,14 @@ public:
auto temp = *arr; auto temp = *arr;
if (static_cast<bool> (newValue)) if (static_cast<bool> (newValue))
temp.addIfNotAlreadyThere (varToControl);
{
if (temp.addIfNotAlreadyThere (varToControl) && (maxChoices != -1) && (temp.size() > maxChoices))
temp.remove (temp.size() - 2);
}
else else
{
temp.remove (arr->indexOf (varToControl)); temp.remove (arr->indexOf (varToControl));
}
StringComparator c; StringComparator c;
temp.sort (c); temp.sort (c);
@@ -86,6 +92,9 @@ private:
Value sourceValue; Value sourceValue;
var varToControl; var varToControl;
int maxChoices;
//==============================================================================
void valueChanged (Value&) override { sendChangeMessage (true); } void valueChanged (Value&) override { sendChangeMessage (true); }
//============================================================================== //==============================================================================
@@ -97,48 +106,98 @@ class MultiChoicePropertyComponent::MultiChoiceRemapperSourceWithDefault : pu
private Value::Listener private Value::Listener
{ {
public: public:
MultiChoiceRemapperSourceWithDefault (ValueWithDefault& vwd, var v)
MultiChoiceRemapperSourceWithDefault (ValueWithDefault& vwd, var v, int c, ToggleButton* b)
: valueWithDefault (vwd), : valueWithDefault (vwd),
varToControl (v),
sourceValue (valueWithDefault.getPropertyAsValue()), sourceValue (valueWithDefault.getPropertyAsValue()),
varToControl (v)
maxChoices (c),
buttonToControl (b)
{ {
sourceValue.addListener (this); sourceValue.addListener (this);
} }
var getValue() const override var getValue() const override
{ {
if (auto* arr = valueWithDefault.get().getArray())
auto v = valueWithDefault.get();
if (auto* arr = v.getArray())
{
if (arr->contains (varToControl)) if (arr->contains (varToControl))
{
updateButtonTickColour();
return true; return true;
}
}
return false; return false;
} }
void setValue (const var& newValue) override void setValue (const var& newValue) override
{ {
if (auto* arr = valueWithDefault.get().getArray())
{
auto temp = *arr;
auto v = valueWithDefault.get();
if (static_cast<bool> (newValue))
temp.addIfNotAlreadyThere (varToControl);
OptionalScopedPointer<Array<var>> arrayToControl;
if (valueWithDefault.isUsingDefault())
arrayToControl.set (new Array<var>(), true); // use an empty array so the default values are overwritten
else
arrayToControl.set (v.getArray(), false);
if (arrayToControl != nullptr)
{
auto temp = *arrayToControl;
bool newState = newValue;
if (valueWithDefault.isUsingDefault())
{
if (auto* defaultArray = v.getArray())
{
if (defaultArray->contains (varToControl))
newState = true; // force the state as the user is setting it explicitly
}
}
if (newState)
{
if (temp.addIfNotAlreadyThere (varToControl) && (maxChoices != -1) && (temp.size() > maxChoices))
temp.remove (temp.size() - 2);
}
else else
temp.remove (arr->indexOf (varToControl));
{
temp.remove (temp.indexOf (varToControl));
}
StringComparator c; StringComparator c;
temp.sort (c); temp.sort (c);
valueWithDefault = temp; valueWithDefault = temp;
if (temp.size() == 0)
valueWithDefault.resetToDefault();
} }
} }
private: private:
ValueWithDefault& valueWithDefault; ValueWithDefault& valueWithDefault;
Value sourceValue;
var varToControl; var varToControl;
Value sourceValue;
int maxChoices;
ToggleButton* buttonToControl;
//==============================================================================
void valueChanged (Value&) override { sendChangeMessage (true); } void valueChanged (Value&) override { sendChangeMessage (true); }
void updateButtonTickColour() const noexcept
{
auto alpha = valueWithDefault.isUsingDefault() ? 0.4f : 1.0f;
auto baseColour = buttonToControl->findColour (ToggleButton::tickColourId);
buttonToControl->setColour (ToggleButton::tickColourId, baseColour.withAlpha (alpha));
}
//============================================================================== //==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultiChoiceRemapperSourceWithDefault) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultiChoiceRemapperSourceWithDefault)
}; };
@@ -175,7 +234,8 @@ MultiChoicePropertyComponent::MultiChoicePropertyComponent (const String& proper
MultiChoicePropertyComponent::MultiChoicePropertyComponent (const Value& valueToControl, MultiChoicePropertyComponent::MultiChoicePropertyComponent (const Value& valueToControl,
const String& propertyName, const String& propertyName,
const StringArray& choices, const StringArray& choices,
const Array<var>& correspondingValues)
const Array<var>& correspondingValues,
int maxChoices)
: MultiChoicePropertyComponent (propertyName, choices, correspondingValues) : MultiChoicePropertyComponent (propertyName, choices, correspondingValues)
{ {
// The value to control must be an array! // The value to control must be an array!
@@ -183,13 +243,15 @@ MultiChoicePropertyComponent::MultiChoicePropertyComponent (const Value& valueTo
for (int i = 0; i < choiceButtons.size(); ++i) for (int i = 0; i < choiceButtons.size(); ++i)
choiceButtons[i]->getToggleStateValue().referTo (Value (new MultiChoiceRemapperSource (valueToControl, choiceButtons[i]->getToggleStateValue().referTo (Value (new MultiChoiceRemapperSource (valueToControl,
correspondingValues[i])));
correspondingValues[i],
maxChoices)));
} }
MultiChoicePropertyComponent::MultiChoicePropertyComponent (ValueWithDefault& valueToControl, MultiChoicePropertyComponent::MultiChoicePropertyComponent (ValueWithDefault& valueToControl,
const String& propertyName, const String& propertyName,
const StringArray& choices, const StringArray& choices,
const Array<var>& correspondingValues)
const Array<var>& correspondingValues,
int maxChoices)
: MultiChoicePropertyComponent (propertyName, choices, correspondingValues) : MultiChoicePropertyComponent (propertyName, choices, correspondingValues)
{ {
// The value to control must be an array! // The value to control must be an array!
@@ -197,7 +259,9 @@ MultiChoicePropertyComponent::MultiChoicePropertyComponent (ValueWithDefault& va
for (int i = 0; i < choiceButtons.size(); ++i) for (int i = 0; i < choiceButtons.size(); ++i)
choiceButtons[i]->getToggleStateValue().referTo (Value (new MultiChoiceRemapperSourceWithDefault (valueToControl, choiceButtons[i]->getToggleStateValue().referTo (Value (new MultiChoiceRemapperSourceWithDefault (valueToControl,
correspondingValues[i])));
correspondingValues[i],
maxChoices,
choiceButtons[i])));
valueToControl.onDefaultChange = [this] { repaint(); }; valueToControl.onDefaultChange = [this] { repaint(); };
} }


+ 8
- 2
modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.h View File

@@ -51,11 +51,14 @@ public:
These are the values that will be read and written to the These are the values that will be read and written to the
valueToControl value. This array must contain the same number of items valueToControl value. This array must contain the same number of items
as the choices array as the choices array
@param maxChoice the maxmimum number of values which can be selected at once. The default of
-1 will not limit the number that can be selected
*/ */
MultiChoicePropertyComponent (const Value& valueToControl, MultiChoicePropertyComponent (const Value& valueToControl,
const String& propertyName, const String& propertyName,
const StringArray& choices, const StringArray& choices,
const Array<var>& correspondingValues);
const Array<var>& correspondingValues,
int maxChoices = -1);
/** Creates the component using a ValueWithDefault object. This will select the default options. /** Creates the component using a ValueWithDefault object. This will select the default options.
@@ -66,11 +69,14 @@ public:
These are the values that will be read and written to the These are the values that will be read and written to the
valueToControl value. This array must contain the same number of items valueToControl value. This array must contain the same number of items
as the choices array as the choices array
@param maxChoice the maxmimum number of values which can be selected at once. The default of
-1 will not limit the number that can be selected
*/ */
MultiChoicePropertyComponent (ValueWithDefault& valueToControl, MultiChoicePropertyComponent (ValueWithDefault& valueToControl,
const String& propertyName, const String& propertyName,
const StringArray& choices, const StringArray& choices,
const Array<var>& correspondingValues);
const Array<var>& correspondingValues,
int maxChoices = -1);
//============================================================================== //==============================================================================
/** Returns true if the list of options is expanded. */ /** Returns true if the list of options is expanded. */


Loading…
Cancel
Save