1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-14 00:14:18 +00:00

Added Animated App template and examples

This commit is contained in:
Felix Faire 2014-10-29 15:55:23 +00:00
parent fefcf7aca6
commit ff6520a89a
1141 changed files with 438491 additions and 94 deletions

View file

@ -0,0 +1,85 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
BooleanPropertyComponent::BooleanPropertyComponent (const String& name,
const String& buttonTextWhenTrue,
const String& buttonTextWhenFalse)
: PropertyComponent (name),
onText (buttonTextWhenTrue),
offText (buttonTextWhenFalse)
{
addAndMakeVisible (button);
button.setClickingTogglesState (false);
button.addListener (this);
}
BooleanPropertyComponent::BooleanPropertyComponent (const Value& valueToControl,
const String& name,
const String& buttonText)
: PropertyComponent (name),
onText (buttonText),
offText (buttonText)
{
addAndMakeVisible (button);
button.setClickingTogglesState (false);
button.setButtonText (buttonText);
button.getToggleStateValue().referTo (valueToControl);
button.setClickingTogglesState (true);
}
BooleanPropertyComponent::~BooleanPropertyComponent()
{
}
void BooleanPropertyComponent::setState (const bool newState)
{
button.setToggleState (newState, sendNotification);
}
bool BooleanPropertyComponent::getState() const
{
return button.getToggleState();
}
void BooleanPropertyComponent::paint (Graphics& g)
{
PropertyComponent::paint (g);
g.setColour (findColour (backgroundColourId));
g.fillRect (button.getBounds());
g.setColour (findColour (ComboBox::outlineColourId));
g.drawRect (button.getBounds());
}
void BooleanPropertyComponent::refresh()
{
button.setToggleState (getState(), dontSendNotification);
button.setButtonText (button.getToggleState() ? onText : offText);
}
void BooleanPropertyComponent::buttonClicked (Button*)
{
setState (! getState());
}

View file

@ -0,0 +1,111 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_BOOLEANPROPERTYCOMPONENT_H_INCLUDED
#define JUCE_BOOLEANPROPERTYCOMPONENT_H_INCLUDED
//==============================================================================
/**
A PropertyComponent that contains an on/off toggle button.
This type of property component can be used if you have a boolean value to
toggle on/off.
@see PropertyComponent
*/
class JUCE_API BooleanPropertyComponent : public PropertyComponent,
private ButtonListener // (can't use Button::Listener due to idiotic VC2005 bug)
{
protected:
//==============================================================================
/** Creates a button component.
If you use this constructor, you must override the getState() and setState()
methods.
@param propertyName the property name to be passed to the PropertyComponent
@param buttonTextWhenTrue the text shown in the button when the value is true
@param buttonTextWhenFalse the text shown in the button when the value is false
*/
BooleanPropertyComponent (const String& propertyName,
const String& buttonTextWhenTrue,
const String& buttonTextWhenFalse);
public:
/** Creates a button component.
Note that if you call this constructor then you must use the Value to interact with the
button state, and you can't override the class with your own setState or getState methods.
If you want to use getState and setState, call the other constructor instead.
@param valueToControl a Value object that this property should refer to.
@param propertyName the property name to be passed to the PropertyComponent
@param buttonText the text shown in the ToggleButton component
*/
BooleanPropertyComponent (const Value& valueToControl,
const String& propertyName,
const String& buttonText);
/** Destructor. */
~BooleanPropertyComponent();
//==============================================================================
/** Called to change the state of the boolean value. */
virtual void setState (bool newState);
/** Must return the current value of the property. */
virtual bool getState() const;
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the component.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x100e801, /**< The colour to fill the background of the button area. */
outlineColourId = 0x100e803, /**< The colour to use to draw an outline around the text area. */
};
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void refresh() override;
/** @internal */
void buttonClicked (Button*) override;
private:
ToggleButton button;
String onText, offText;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BooleanPropertyComponent)
};
#endif // JUCE_BOOLEANPROPERTYCOMPONENT_H_INCLUDED

View file

@ -0,0 +1,46 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
ButtonPropertyComponent::ButtonPropertyComponent (const String& name,
const bool triggerOnMouseDown)
: PropertyComponent (name)
{
addAndMakeVisible (button);
button.setTriggeredOnMouseDown (triggerOnMouseDown);
button.addListener (this);
}
ButtonPropertyComponent::~ButtonPropertyComponent()
{
}
void ButtonPropertyComponent::refresh()
{
button.setButtonText (getButtonText());
}
void ButtonPropertyComponent::buttonClicked (Button*)
{
buttonClicked();
}

View file

@ -0,0 +1,78 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_BUTTONPROPERTYCOMPONENT_H_INCLUDED
#define JUCE_BUTTONPROPERTYCOMPONENT_H_INCLUDED
//==============================================================================
/**
A PropertyComponent that contains a button.
This type of property component can be used if you need a button to trigger some
kind of action.
@see PropertyComponent
*/
class JUCE_API ButtonPropertyComponent : public PropertyComponent,
private ButtonListener // (can't use Button::Listener due to idiotic VC2005 bug)
{
public:
//==============================================================================
/** Creates a button component.
@param propertyName the property name to be passed to the PropertyComponent
@param triggerOnMouseDown this is passed to the Button::setTriggeredOnMouseDown() method
*/
ButtonPropertyComponent (const String& propertyName,
bool triggerOnMouseDown);
/** Destructor. */
~ButtonPropertyComponent();
//==============================================================================
/** Called when the user clicks the button.
*/
virtual void buttonClicked() = 0;
/** Returns the string that should be displayed in the button.
If you need to change this string, call refresh() to update the component.
*/
virtual String getButtonText() const = 0;
//==============================================================================
/** @internal */
void refresh();
/** @internal */
void buttonClicked (Button*);
private:
TextButton button;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonPropertyComponent)
};
#endif // JUCE_BUTTONPROPERTYCOMPONENT_H_INCLUDED

View file

@ -0,0 +1,152 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
class ChoicePropertyComponent::RemapperValueSource : public Value::ValueSource,
private ValueListener
{
public:
RemapperValueSource (const Value& source, const Array<var>& map)
: sourceValue (source), mappings (map)
{
sourceValue.addListener (this);
}
var getValue() const
{
const var targetValue (sourceValue.getValue());
for (int i = 0; i < mappings.size(); ++i)
if (mappings.getReference(i).equalsWithSameType (targetValue))
return i + 1;
return mappings.indexOf (targetValue) + 1;
}
void setValue (const var& newValue)
{
const var remappedVal (mappings [static_cast <int> (newValue) - 1]);
if (! remappedVal.equalsWithSameType (sourceValue))
sourceValue = remappedVal;
}
protected:
Value sourceValue;
Array<var> mappings;
void valueChanged (Value&)
{
sendChangeMessage (true);
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSource)
};
//==============================================================================
ChoicePropertyComponent::ChoicePropertyComponent (const String& name)
: PropertyComponent (name),
isCustomClass (true)
{
}
ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl,
const String& name,
const StringArray& choiceList,
const Array<var>& correspondingValues)
: PropertyComponent (name),
choices (choiceList),
isCustomClass (false)
{
// The array of corresponding values must contain one value for each of the items in
// the choices array!
jassert (correspondingValues.size() == choices.size());
createComboBox();
comboBox.getSelectedIdAsValue().referTo (Value (new RemapperValueSource (valueToControl,
correspondingValues)));
}
ChoicePropertyComponent::~ChoicePropertyComponent()
{
}
//==============================================================================
void ChoicePropertyComponent::createComboBox()
{
addAndMakeVisible (comboBox);
for (int i = 0; i < choices.size(); ++i)
{
if (choices[i].isNotEmpty())
comboBox.addItem (choices[i], i + 1);
else
comboBox.addSeparator();
}
comboBox.setEditableText (false);
}
void ChoicePropertyComponent::setIndex (const int /*newIndex*/)
{
jassertfalse; // you need to override this method in your subclass!
}
int ChoicePropertyComponent::getIndex() const
{
jassertfalse; // you need to override this method in your subclass!
return -1;
}
const StringArray& ChoicePropertyComponent::getChoices() const
{
return choices;
}
//==============================================================================
void ChoicePropertyComponent::refresh()
{
if (isCustomClass)
{
if (! comboBox.isVisible())
{
createComboBox();
comboBox.addListener (this);
}
comboBox.setSelectedId (getIndex() + 1, dontSendNotification);
}
}
void ChoicePropertyComponent::comboBoxChanged (ComboBox*)
{
if (isCustomClass)
{
const int newIndex = comboBox.getSelectedId() - 1;
if (newIndex != getIndex())
setIndex (newIndex);
}
}

View file

@ -0,0 +1,125 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_CHOICEPROPERTYCOMPONENT_H_INCLUDED
#define JUCE_CHOICEPROPERTYCOMPONENT_H_INCLUDED
//==============================================================================
/**
A PropertyComponent that shows its value as a combo box.
This type of property component contains a list of options and has a
combo box to choose one.
Your subclass's constructor must add some strings to the choices StringArray
and these are shown in the list.
The getIndex() method will be called to find out which option is the currently
selected one. If you call refresh() it will call getIndex() to check whether
the value has changed, and will update the combo box if needed.
If the user selects a different item from the list, setIndex() will be
called to let your class process this.
@see PropertyComponent, PropertyPanel
*/
class JUCE_API ChoicePropertyComponent : public PropertyComponent,
private ComboBoxListener // (can't use ComboBox::Listener due to idiotic VC2005 bug)
{
protected:
/** Creates the component.
Your subclass's constructor must add a list of options to the choices member variable.
*/
ChoicePropertyComponent (const String& propertyName);
public:
/** Creates the component.
Note that if you call this constructor then you must use the Value to interact with the
index, and you can't override the class with your own setIndex or getIndex methods.
If you want to use those methods, call the other constructor instead.
@param valueToControl the value that the combo box will read and control
@param propertyName the name of the property
@param choices the list of possible values that the drop-down list will contain
@param correspondingValues a list of values corresponding to each item in the 'choices' StringArray.
These are the values that will be read and written to the
valueToControl value. This array must contain the same number of items
as the choices array
*/
ChoicePropertyComponent (const Value& valueToControl,
const String& propertyName,
const StringArray& choices,
const Array<var>& correspondingValues);
/** Destructor. */
~ChoicePropertyComponent();
//==============================================================================
/** Called when the user selects an item from the combo box.
Your subclass must use this callback to update the value that this component
represents. The index is the index of the chosen item in the choices
StringArray.
*/
virtual void setIndex (int newIndex);
/** Returns the index of the item that should currently be shown.
This is the index of the item in the choices StringArray that will be shown.
*/
virtual int getIndex() const;
/** Returns the list of options. */
const StringArray& getChoices() const;
//==============================================================================
/** @internal */
void refresh();
protected:
/** The list of options that will be shown in the combo box.
Your subclass must populate this array in its constructor. If any empty
strings are added, these will be replaced with horizontal separators (see
ComboBox::addSeparator() for more info).
*/
StringArray choices;
private:
ComboBox comboBox;
bool isCustomClass;
class RemapperValueSource;
void createComboBox();
void comboBoxChanged (ComboBox*);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChoicePropertyComponent)
};
#endif // JUCE_CHOICEPROPERTYCOMPONENT_H_INCLUDED

View file

@ -0,0 +1,50 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
PropertyComponent::PropertyComponent (const String& name, const int preferredHeight_)
: Component (name), preferredHeight (preferredHeight_)
{
jassert (name.isNotEmpty());
}
PropertyComponent::~PropertyComponent() {}
void PropertyComponent::paint (Graphics& g)
{
LookAndFeel& lf = getLookAndFeel();
lf.drawPropertyComponentBackground (g, getWidth(), getHeight(), *this);
lf.drawPropertyComponentLabel (g, getWidth(), getHeight(), *this);
}
void PropertyComponent::resized()
{
if (Component* const c = getChildComponent(0))
c->setBounds (getLookAndFeel().getPropertyComponentContentPosition (*this));
}
void PropertyComponent::enablementChanged()
{
repaint();
}

View file

@ -0,0 +1,145 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_PROPERTYCOMPONENT_H_INCLUDED
#define JUCE_PROPERTYCOMPONENT_H_INCLUDED
//==============================================================================
/**
A base class for a component that goes in a PropertyPanel and displays one of
an item's properties.
Subclasses of this are used to display a property in various forms, e.g. a
ChoicePropertyComponent shows its value as a combo box; a SliderPropertyComponent
shows its value as a slider; a TextPropertyComponent as a text box, etc.
A subclass must implement the refresh() method which will be called to tell the
component to update itself, and is also responsible for calling this it when the
item that it refers to is changed.
@see PropertyPanel, TextPropertyComponent, SliderPropertyComponent,
ChoicePropertyComponent, ButtonPropertyComponent, BooleanPropertyComponent
*/
class JUCE_API PropertyComponent : public Component,
public SettableTooltipClient
{
public:
//==============================================================================
/** Creates a PropertyComponent.
@param propertyName the name is stored as this component's name, and is
used as the name displayed next to this component in
a property panel
@param preferredHeight the height that the component should be given - some
items may need to be larger than a normal row height.
This value can also be set if a subclass changes the
preferredHeight member variable.
*/
PropertyComponent (const String& propertyName,
int preferredHeight = 25);
/** Destructor. */
~PropertyComponent();
//==============================================================================
/** Returns this item's preferred height.
This value is specified either in the constructor or by a subclass changing the
preferredHeight member variable.
*/
int getPreferredHeight() const noexcept { return preferredHeight; }
void setPreferredHeight (int newHeight) noexcept { preferredHeight = newHeight; }
//==============================================================================
/** Updates the property component if the item it refers to has changed.
A subclass must implement this method, and other objects may call it to
force it to refresh itself.
The subclass should be economical in the amount of work is done, so for
example it should check whether it really needs to do a repaint rather than
just doing one every time this method is called, as it may be called when
the value being displayed hasn't actually changed.
*/
virtual void refresh() = 0;
/** The default paint method fills the background and draws a label for the
item's name.
@see LookAndFeel::drawPropertyComponentBackground(), LookAndFeel::drawPropertyComponentLabel()
*/
void paint (Graphics&) override;
/** The default resize method positions any child component to the right of this
one, based on the look and feel's default label size.
*/
void resized() override;
/** By default, this just repaints the component. */
void enablementChanged() override;
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the combo box.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
To change the colours of the menu that pops up
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1008300, /**< The background colour to fill the component with. */
labelTextColourId = 0x1008301, /**< The colour for the property's label text. */
};
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes. */
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() {}
virtual void drawPropertyPanelSectionHeader (Graphics&, const String& name, bool isOpen, int width, int height) = 0;
virtual void drawPropertyComponentBackground (Graphics&, int width, int height, PropertyComponent&) = 0;
virtual void drawPropertyComponentLabel (Graphics&, int width, int height, PropertyComponent&) = 0;
virtual Rectangle<int> getPropertyComponentContentPosition (PropertyComponent&) = 0;
};
protected:
/** Used by the PropertyPanel to determine how high this component needs to be.
A subclass can update this value in its constructor but shouldn't alter it later
as changes won't necessarily be picked up.
*/
int preferredHeight;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyComponent)
};
#endif // JUCE_PROPERTYCOMPONENT_H_INCLUDED

View file

@ -0,0 +1,414 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
class PropertyPanel::SectionComponent : public Component
{
public:
SectionComponent (const String& sectionTitle,
const Array <PropertyComponent*>& newProperties,
const bool sectionIsOpen_)
: Component (sectionTitle),
titleHeight (sectionTitle.isNotEmpty() ? 22 : 0),
sectionIsOpen (sectionIsOpen_)
{
propertyComps.addArray (newProperties);
for (int i = propertyComps.size(); --i >= 0;)
{
addAndMakeVisible (propertyComps.getUnchecked(i));
propertyComps.getUnchecked(i)->refresh();
}
}
~SectionComponent()
{
propertyComps.clear();
}
void paint (Graphics& g) override
{
if (titleHeight > 0)
getLookAndFeel().drawPropertyPanelSectionHeader (g, getName(), isOpen(), getWidth(), titleHeight);
}
void resized() override
{
int y = titleHeight;
for (int i = 0; i < propertyComps.size(); ++i)
{
PropertyComponent* const pec = propertyComps.getUnchecked (i);
pec->setBounds (1, y, getWidth() - 2, pec->getPreferredHeight());
y = pec->getBottom();
}
}
int getPreferredHeight() const
{
int y = titleHeight;
if (isOpen())
{
for (int i = propertyComps.size(); --i >= 0;)
y += propertyComps.getUnchecked(i)->getPreferredHeight();
}
return y;
}
void setOpen (const bool open)
{
if (sectionIsOpen != open)
{
sectionIsOpen = open;
for (int i = propertyComps.size(); --i >= 0;)
propertyComps.getUnchecked(i)->setVisible (open);
if (PropertyPanel* const pp = findParentComponentOfClass<PropertyPanel>())
pp->resized();
}
}
bool isOpen() const
{
return sectionIsOpen;
}
void refreshAll() const
{
for (int i = propertyComps.size(); --i >= 0;)
propertyComps.getUnchecked (i)->refresh();
}
void mouseUp (const MouseEvent& e) override
{
if (e.getMouseDownX() < titleHeight
&& e.x < titleHeight
&& e.y < titleHeight
&& e.getNumberOfClicks() != 2)
{
setOpen (! isOpen());
}
}
void mouseDoubleClick (const MouseEvent& e) override
{
if (e.y < titleHeight)
setOpen (! isOpen());
}
private:
OwnedArray <PropertyComponent> propertyComps;
int titleHeight;
bool sectionIsOpen;
JUCE_DECLARE_NON_COPYABLE (SectionComponent)
};
//==============================================================================
class PropertyPanel::PropertyHolderComponent : public Component
{
public:
PropertyHolderComponent() {}
void paint (Graphics&) override {}
void updateLayout (int width)
{
int y = 0;
for (int i = 0; i < sections.size(); ++i)
{
SectionComponent* const section = sections.getUnchecked(i);
section->setBounds (0, y, width, section->getPreferredHeight());
y = section->getBottom();
}
setSize (width, y);
repaint();
}
void refreshAll() const
{
for (int i = 0; i < sections.size(); ++i)
sections.getUnchecked(i)->refreshAll();
}
void clear()
{
sections.clear();
}
void addSection (SectionComponent* newSection)
{
sections.add (newSection);
addAndMakeVisible (newSection, 0);
}
int getNumSections() const noexcept { return sections.size(); }
SectionComponent* getSection (const int index) const { return sections [index]; }
private:
OwnedArray<SectionComponent> sections;
JUCE_DECLARE_NON_COPYABLE (PropertyHolderComponent)
};
//==============================================================================
PropertyPanel::PropertyPanel()
{
init();
}
PropertyPanel::PropertyPanel (const String& name) : Component (name)
{
init();
}
void PropertyPanel::init()
{
messageWhenEmpty = TRANS("(nothing selected)");
addAndMakeVisible (viewport);
viewport.setViewedComponent (propertyHolderComponent = new PropertyHolderComponent());
viewport.setFocusContainer (true);
}
PropertyPanel::~PropertyPanel()
{
clear();
}
//==============================================================================
void PropertyPanel::paint (Graphics& g)
{
if (isEmpty())
{
g.setColour (Colours::black.withAlpha (0.5f));
g.setFont (14.0f);
g.drawText (messageWhenEmpty, getLocalBounds().withHeight (30),
Justification::centred, true);
}
}
void PropertyPanel::resized()
{
viewport.setBounds (getLocalBounds());
updatePropHolderLayout();
}
//==============================================================================
void PropertyPanel::clear()
{
if (! isEmpty())
{
propertyHolderComponent->clear();
updatePropHolderLayout();
}
}
bool PropertyPanel::isEmpty() const
{
return propertyHolderComponent->getNumSections() == 0;
}
int PropertyPanel::getTotalContentHeight() const
{
return propertyHolderComponent->getHeight();
}
void PropertyPanel::addProperties (const Array <PropertyComponent*>& newProperties)
{
if (isEmpty())
repaint();
propertyHolderComponent->addSection (new SectionComponent (String::empty, newProperties, true));
updatePropHolderLayout();
}
void PropertyPanel::addSection (const String& sectionTitle,
const Array <PropertyComponent*>& newProperties,
const bool shouldBeOpen)
{
jassert (sectionTitle.isNotEmpty());
if (isEmpty())
repaint();
propertyHolderComponent->addSection (new SectionComponent (sectionTitle, newProperties, shouldBeOpen));
updatePropHolderLayout();
}
void PropertyPanel::updatePropHolderLayout() const
{
const int maxWidth = viewport.getMaximumVisibleWidth();
propertyHolderComponent->updateLayout (maxWidth);
const int newMaxWidth = viewport.getMaximumVisibleWidth();
if (maxWidth != newMaxWidth)
{
// need to do this twice because of scrollbars changing the size, etc.
propertyHolderComponent->updateLayout (newMaxWidth);
}
}
void PropertyPanel::refreshAll() const
{
propertyHolderComponent->refreshAll();
}
//==============================================================================
StringArray PropertyPanel::getSectionNames() const
{
StringArray s;
for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i)
{
SectionComponent* const section = propertyHolderComponent->getSection (i);
if (section->getName().isNotEmpty())
s.add (section->getName());
}
return s;
}
bool PropertyPanel::isSectionOpen (const int sectionIndex) const
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i)
{
SectionComponent* const section = propertyHolderComponent->getSection (i);
if (section->getName().isNotEmpty())
{
if (index == sectionIndex)
return section->isOpen();
++index;
}
}
return false;
}
void PropertyPanel::setSectionOpen (const int sectionIndex, const bool shouldBeOpen)
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i)
{
SectionComponent* const section = propertyHolderComponent->getSection (i);
if (section->getName().isNotEmpty())
{
if (index == sectionIndex)
{
section->setOpen (shouldBeOpen);
break;
}
++index;
}
}
}
void PropertyPanel::setSectionEnabled (const int sectionIndex, const bool shouldBeEnabled)
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i)
{
SectionComponent* const section = propertyHolderComponent->getSection (i);
if (section->getName().isNotEmpty())
{
if (index == sectionIndex)
{
section->setEnabled (shouldBeEnabled);
break;
}
++index;
}
}
}
//==============================================================================
XmlElement* PropertyPanel::getOpennessState() const
{
XmlElement* const xml = new XmlElement ("PROPERTYPANELSTATE");
xml->setAttribute ("scrollPos", viewport.getViewPositionY());
const StringArray sections (getSectionNames());
for (int i = 0; i < sections.size(); ++i)
{
if (sections[i].isNotEmpty())
{
XmlElement* const e = xml->createNewChildElement ("SECTION");
e->setAttribute ("name", sections[i]);
e->setAttribute ("open", isSectionOpen (i) ? 1 : 0);
}
}
return xml;
}
void PropertyPanel::restoreOpennessState (const XmlElement& xml)
{
if (xml.hasTagName ("PROPERTYPANELSTATE"))
{
const StringArray sections (getSectionNames());
forEachXmlChildElementWithTagName (xml, e, "SECTION")
{
setSectionOpen (sections.indexOf (e->getStringAttribute ("name")),
e->getBoolAttribute ("open"));
}
viewport.setViewPosition (viewport.getViewPositionX(),
xml.getIntAttribute ("scrollPos", viewport.getViewPositionY()));
}
}
//==============================================================================
void PropertyPanel::setMessageWhenEmpty (const String& newMessage)
{
if (messageWhenEmpty != newMessage)
{
messageWhenEmpty = newMessage;
repaint();
}
}
const String& PropertyPanel::getMessageWhenEmpty() const
{
return messageWhenEmpty;
}

View file

@ -0,0 +1,167 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_PROPERTYPANEL_H_INCLUDED
#define JUCE_PROPERTYPANEL_H_INCLUDED
//==============================================================================
/**
A panel that holds a list of PropertyComponent objects.
This panel displays a list of PropertyComponents, and allows them to be organised
into collapsible sections.
To use, simply create one of these and add your properties to it with addProperties()
or addSection().
@see PropertyComponent
*/
class JUCE_API PropertyPanel : public Component
{
public:
//==============================================================================
/** Creates an empty property panel. */
PropertyPanel();
/** Creates an empty property panel. */
PropertyPanel (const String& name);
/** Destructor. */
~PropertyPanel();
//==============================================================================
/** Deletes all property components from the panel. */
void clear();
/** Adds a set of properties to the panel.
The components in the list will be owned by this object and will be automatically
deleted later on when no longer needed.
These properties are added without them being inside a named section. If you
want them to be kept together in a collapsible section, use addSection() instead.
*/
void addProperties (const Array<PropertyComponent*>& newPropertyComponents);
/** Adds a set of properties to the panel.
These properties are added at the bottom of the list, under a section heading with
a plus/minus button that allows it to be opened and closed.
The components in the list will be owned by this object and will be automatically
deleted later on when no longer needed.
To add properies without them being in a section, use addProperties().
*/
void addSection (const String& sectionTitle,
const Array<PropertyComponent*>& newPropertyComponents,
bool shouldSectionInitiallyBeOpen = true);
/** Calls the refresh() method of all PropertyComponents in the panel */
void refreshAll() const;
/** Returns true if the panel contains no properties. */
bool isEmpty() const;
/** Returns the height that the panel needs in order to display all of its content
without scrolling.
*/
int getTotalContentHeight() const;
//==============================================================================
/** Returns a list of all the names of sections in the panel.
These are the sections that have been added with addSection().
*/
StringArray getSectionNames() const;
/** Returns true if the section at this index is currently open.
The index is from 0 up to the number of items returned by getSectionNames().
*/
bool isSectionOpen (int sectionIndex) const;
/** Opens or closes one of the sections.
The index is from 0 up to the number of items returned by getSectionNames().
*/
void setSectionOpen (int sectionIndex, bool shouldBeOpen);
/** Enables or disables one of the sections.
The index is from 0 up to the number of items returned by getSectionNames().
*/
void setSectionEnabled (int sectionIndex, bool shouldBeEnabled);
//==============================================================================
/** Saves the current state of open/closed sections so it can be restored later.
The caller is responsible for deleting the object that is returned.
To restore this state, use restoreOpennessState().
@see restoreOpennessState
*/
XmlElement* getOpennessState() const;
/** Restores a previously saved arrangement of open/closed sections.
This will try to restore a snapshot of the panel's state that was created by
the getOpennessState() method. If any of the sections named in the original
XML aren't present, they will be ignored.
@see getOpennessState
*/
void restoreOpennessState (const XmlElement& newState);
//==============================================================================
/** Sets a message to be displayed when there are no properties in the panel.
The default message is "nothing selected".
*/
void setMessageWhenEmpty (const String& newMessage);
/** Returns the message that is displayed when there are no properties.
@see setMessageWhenEmpty
*/
const String& getMessageWhenEmpty() const;
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
private:
class SectionComponent;
Viewport viewport;
class PropertyHolderComponent;
PropertyHolderComponent* propertyHolderComponent;
String messageWhenEmpty;
void init();
void updatePropHolderLayout() const;
void updatePropHolderLayout (int width) const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyPanel)
};
#endif // JUCE_PROPERTYPANEL_H_INCLUDED

View file

@ -0,0 +1,80 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
SliderPropertyComponent::SliderPropertyComponent (const String& name,
const double rangeMin,
const double rangeMax,
const double interval,
const double skewFactor)
: PropertyComponent (name)
{
addAndMakeVisible (slider);
slider.setRange (rangeMin, rangeMax, interval);
slider.setSkewFactor (skewFactor);
slider.setSliderStyle (Slider::LinearBar);
slider.addListener (this);
}
SliderPropertyComponent::SliderPropertyComponent (const Value& valueToControl,
const String& name,
const double rangeMin,
const double rangeMax,
const double interval,
const double skewFactor)
: PropertyComponent (name)
{
addAndMakeVisible (slider);
slider.setRange (rangeMin, rangeMax, interval);
slider.setSkewFactor (skewFactor);
slider.setSliderStyle (Slider::LinearBar);
slider.getValueObject().referTo (valueToControl);
}
SliderPropertyComponent::~SliderPropertyComponent()
{
}
void SliderPropertyComponent::setValue (const double /*newValue*/)
{
}
double SliderPropertyComponent::getValue() const
{
return slider.getValue();
}
void SliderPropertyComponent::refresh()
{
slider.setValue (getValue(), dontSendNotification);
}
void SliderPropertyComponent::sliderValueChanged (Slider*)
{
if (getValue() != slider.getValue())
setValue (slider.getValue());
}

View file

@ -0,0 +1,107 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_SLIDERPROPERTYCOMPONENT_H_INCLUDED
#define JUCE_SLIDERPROPERTYCOMPONENT_H_INCLUDED
//==============================================================================
/**
A PropertyComponent that shows its value as a slider.
@see PropertyComponent, Slider
*/
class JUCE_API SliderPropertyComponent : public PropertyComponent,
private SliderListener // (can't use Slider::Listener due to idiotic VC2005 bug)
{
protected:
//==============================================================================
/** Creates the property component.
The ranges, interval and skew factor are passed to the Slider component.
If you need to customise the slider in other ways, your constructor can
access the slider member variable and change it directly.
*/
SliderPropertyComponent (const String& propertyName,
double rangeMin,
double rangeMax,
double interval,
double skewFactor = 1.0);
public:
//==============================================================================
/** Creates the property component.
The ranges, interval and skew factor are passed to the Slider component.
If you need to customise the slider in other ways, your constructor can
access the slider member variable and change it directly.
Note that if you call this constructor then you must use the Value to interact with
the value, and you can't override the class with your own setValue or getValue methods.
If you want to use those methods, call the other constructor instead.
*/
SliderPropertyComponent (const Value& valueToControl,
const String& propertyName,
double rangeMin,
double rangeMax,
double interval,
double skewFactor = 1.0);
/** Destructor. */
~SliderPropertyComponent();
//==============================================================================
/** Called when the user moves the slider to change its value.
Your subclass must use this method to update whatever item this property
represents.
*/
virtual void setValue (double newValue);
/** Returns the value that the slider should show. */
virtual double getValue() const;
//==============================================================================
/** @internal */
void refresh();
/** @internal */
void sliderValueChanged (Slider*);
protected:
/** The slider component being used in this component.
Your subclass has access to this in case it needs to customise it in some way.
*/
Slider slider;
private:
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderPropertyComponent)
};
#endif // JUCE_SLIDERPROPERTYCOMPONENT_H_INCLUDED

View file

@ -0,0 +1,134 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
class TextPropertyComponent::LabelComp : public Label,
public FileDragAndDropTarget
{
public:
LabelComp (TextPropertyComponent& tpc, const int charLimit, const bool multiline)
: Label (String::empty, String::empty),
owner (tpc),
maxChars (charLimit),
isMultiline (multiline)
{
setEditable (true, true, false);
setColour (backgroundColourId, owner.findColour (TextPropertyComponent::backgroundColourId));
setColour (outlineColourId, owner.findColour (TextPropertyComponent::outlineColourId));
setColour (textColourId, owner.findColour (TextPropertyComponent::textColourId));
}
bool isInterestedInFileDrag (const StringArray&) override
{
return true;
}
void filesDropped (const StringArray& files, int, int) override
{
setText (getText() + files.joinIntoString (isMultiline ? "\n" : ", "), sendNotificationSync);
showEditor();
}
TextEditor* createEditorComponent() override
{
TextEditor* const ed = Label::createEditorComponent();
ed->setInputRestrictions (maxChars);
if (isMultiline)
{
ed->setMultiLine (true, true);
ed->setReturnKeyStartsNewLine (true);
}
return ed;
}
void textWasEdited() override
{
owner.textWasEdited();
}
private:
TextPropertyComponent& owner;
int maxChars;
bool isMultiline;
};
//==============================================================================
TextPropertyComponent::TextPropertyComponent (const String& name,
const int maxNumChars,
const bool isMultiLine)
: PropertyComponent (name)
{
createEditor (maxNumChars, isMultiLine);
}
TextPropertyComponent::TextPropertyComponent (const Value& valueToControl,
const String& name,
const int maxNumChars,
const bool isMultiLine)
: PropertyComponent (name)
{
createEditor (maxNumChars, isMultiLine);
textEditor->getTextValue().referTo (valueToControl);
}
TextPropertyComponent::~TextPropertyComponent()
{
}
void TextPropertyComponent::setText (const String& newText)
{
textEditor->setText (newText, sendNotificationSync);
}
String TextPropertyComponent::getText() const
{
return textEditor->getText();
}
void TextPropertyComponent::createEditor (const int maxNumChars, const bool isMultiLine)
{
addAndMakeVisible (textEditor = new LabelComp (*this, maxNumChars, isMultiLine));
if (isMultiLine)
{
textEditor->setJustificationType (Justification::topLeft);
preferredHeight = 100;
}
}
void TextPropertyComponent::refresh()
{
textEditor->setText (getText(), dontSendNotification);
}
void TextPropertyComponent::textWasEdited()
{
const String newText (textEditor->getText());
if (getText() != newText)
setText (newText);
}

View file

@ -0,0 +1,109 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_TEXTPROPERTYCOMPONENT_H_INCLUDED
#define JUCE_TEXTPROPERTYCOMPONENT_H_INCLUDED
//==============================================================================
/**
A PropertyComponent that shows its value as editable text.
@see PropertyComponent
*/
class JUCE_API TextPropertyComponent : public PropertyComponent
{
protected:
//==============================================================================
/** Creates a text property component.
The maxNumChars is used to set the length of string allowable, and isMultiLine
sets whether the text editor allows carriage returns.
@see TextEditor
*/
TextPropertyComponent (const String& propertyName,
int maxNumChars,
bool isMultiLine);
public:
/** Creates a text property component.
The maxNumChars is used to set the length of string allowable, and isMultiLine
sets whether the text editor allows carriage returns.
@see TextEditor
*/
TextPropertyComponent (const Value& valueToControl,
const String& propertyName,
int maxNumChars,
bool isMultiLine);
/** Destructor. */
~TextPropertyComponent();
//==============================================================================
/** Called when the user edits the text.
Your subclass must use this callback to change the value of whatever item
this property component represents.
*/
virtual void setText (const String& newText);
/** Returns the text that should be shown in the text editor. */
virtual String getText() const;
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the component.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x100e401, /**< The colour to fill the background of the text area. */
textColourId = 0x100e402, /**< The colour to use for the editable text. */
outlineColourId = 0x100e403, /**< The colour to use to draw an outline around the text area. */
};
//==============================================================================
/** @internal */
void refresh();
private:
ScopedPointer<Label> textEditor;
class LabelComp;
friend class LabelComp;
void textWasEdited();
void createEditor (int maxNumChars, bool isMultiLine);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextPropertyComponent)
};
#endif // JUCE_TEXTPROPERTYCOMPONENT_H_INCLUDED