mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
535 lines
20 KiB
C++
535 lines
20 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE framework.
|
|
Copyright (c) Raw Material Software Limited
|
|
|
|
JUCE is an open source framework subject to commercial or open source
|
|
licensing.
|
|
|
|
By downloading, installing, or using the JUCE framework, or combining the
|
|
JUCE framework with any other source code, object code, content or any other
|
|
copyrightable work, you agree to the terms of the JUCE End User Licence
|
|
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
|
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
|
do not agree to the terms of these agreements, we will not license the JUCE
|
|
framework to you, and you must discontinue the installation or download
|
|
process and cease use of the JUCE framework.
|
|
|
|
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
|
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
|
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
|
|
|
Or:
|
|
|
|
You may also use this code under the terms of the AGPLv3:
|
|
https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
|
|
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
|
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
|
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
|
|
//==============================================================================
|
|
class ImageButtonHandler : public ButtonHandler
|
|
{
|
|
public:
|
|
enum ImageRole
|
|
{
|
|
normalImage = 0,
|
|
overImage = 1,
|
|
downImage = 2
|
|
};
|
|
|
|
//==============================================================================
|
|
ImageButtonHandler()
|
|
: ButtonHandler ("Image Button", "juce::ImageButton", typeid (ImageButton), 150, 24)
|
|
{
|
|
}
|
|
|
|
Component* createNewComponent (JucerDocument*) override
|
|
{
|
|
return new ImageButton ("new button");
|
|
}
|
|
|
|
void getEditableProperties (Component* component, JucerDocument& document,
|
|
Array<PropertyComponent*>& props, bool multipleSelected) override
|
|
{
|
|
ButtonHandler::getEditableProperties (component, document, props, multipleSelected);
|
|
|
|
if (multipleSelected)
|
|
return;
|
|
|
|
addColourProperties (component, document, props);
|
|
|
|
if (auto* ib = dynamic_cast<ImageButton*> (component))
|
|
{
|
|
auto& layout = *document.getComponentLayout();
|
|
|
|
props.add (new ImageButtonProportionProperty (layout, ib));
|
|
|
|
props.add (new ImageButtonResourceProperty (layout, ib, normalImage, "normal image"));
|
|
props.add (new ImageButtonOpacityProperty (layout, ib, "opacity", normalImage));
|
|
props.add (new ImageButtonColourProperty (layout, ib, "overlay col.", normalImage));
|
|
|
|
props.add (new ImageButtonResourceProperty (layout, ib, overImage, "over image"));
|
|
props.add (new ImageButtonOpacityProperty (layout, ib, "opacity", overImage));
|
|
props.add (new ImageButtonColourProperty (layout, ib, "overlay col.", overImage));
|
|
|
|
props.add (new ImageButtonResourceProperty (layout, ib, downImage, "down image"));
|
|
props.add (new ImageButtonOpacityProperty (layout, ib, "opacity", downImage));
|
|
props.add (new ImageButtonColourProperty (layout, ib, "overlay col.", downImage));
|
|
}
|
|
}
|
|
|
|
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
|
|
{
|
|
XmlElement* e = ButtonHandler::createXmlFor (comp, layout);
|
|
|
|
ImageButton* const ib = (ImageButton*) comp;
|
|
|
|
e->setAttribute ("keepProportions", doesImageKeepProportions (ib));
|
|
|
|
e->setAttribute ("resourceNormal", getImageResource (ib, normalImage));
|
|
e->setAttribute ("opacityNormal", getImageOpacity (ib, normalImage));
|
|
e->setAttribute ("colourNormal", getImageColour (ib, normalImage).toString());
|
|
|
|
e->setAttribute ("resourceOver", getImageResource (ib, overImage));
|
|
e->setAttribute ("opacityOver", getImageOpacity (ib, overImage));
|
|
e->setAttribute ("colourOver", getImageColour (ib, overImage).toString());
|
|
|
|
e->setAttribute ("resourceDown", getImageResource (ib, downImage));
|
|
e->setAttribute ("opacityDown", getImageOpacity (ib, downImage));
|
|
e->setAttribute ("colourDown", getImageColour (ib, downImage).toString());
|
|
|
|
return e;
|
|
}
|
|
|
|
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
|
|
{
|
|
if (! ButtonHandler::restoreFromXml (xml, comp, layout))
|
|
return false;
|
|
|
|
ImageButton* const ib = (ImageButton*) comp;
|
|
ComponentLayout& l = const_cast<ComponentLayout&> (*layout);
|
|
|
|
setImageKeepProportions (l, ib, xml.getBoolAttribute ("keepProportions", true), false);
|
|
|
|
setImageResource (l, ib, normalImage, xml.getStringAttribute ("resourceNormal", String()), false);
|
|
setImageOpacity (l, ib, normalImage, (float) xml.getDoubleAttribute ("opacityNormal", 1.0f), false);
|
|
setImageColour (l, ib, normalImage, Colour::fromString (xml.getStringAttribute ("colourNormal", "0")), false);
|
|
|
|
setImageResource (l, ib, overImage, xml.getStringAttribute ("resourceOver", String()), false);
|
|
setImageOpacity (l, ib, overImage, (float) xml.getDoubleAttribute ("opacityOver", 1.0f), false);
|
|
setImageColour (l, ib, overImage, Colour::fromString (xml.getStringAttribute ("colourOver", "0")), false);
|
|
|
|
setImageResource (l, ib, downImage, xml.getStringAttribute ("resourceDown", String()), false);
|
|
setImageOpacity (l, ib, downImage, (float) xml.getDoubleAttribute ("opacityDown", 1.0f), false);
|
|
setImageColour (l, ib, downImage, Colour::fromString (xml.getStringAttribute ("colourDown", "0")), false);
|
|
|
|
return true;
|
|
}
|
|
|
|
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
|
|
{
|
|
ButtonHandler::fillInCreationCode (code, component, memberVariableName);
|
|
|
|
ImageButton* const ib = dynamic_cast<ImageButton*> (component);
|
|
|
|
String s;
|
|
|
|
s << getColourIntialisationCode (component, memberVariableName)
|
|
<< '\n';
|
|
|
|
const String indent (String::repeatedString (" ", memberVariableName.length() + 13));
|
|
|
|
s << memberVariableName << "->setImages (false, true, "
|
|
<< CodeHelpers::boolLiteral (doesImageKeepProportions (ib)) << ",\n"
|
|
<< indent
|
|
<< getImageCreationCode (ib, normalImage) << ", "
|
|
<< CodeHelpers::floatLiteral (getImageOpacity (ib, normalImage), 3) << ", "
|
|
<< CodeHelpers::colourToCode (getImageColour (ib, normalImage)) << ",\n"
|
|
<< indent
|
|
<< getImageCreationCode (ib, overImage) << ", "
|
|
<< CodeHelpers::floatLiteral (getImageOpacity (ib, overImage), 3) << ", "
|
|
<< CodeHelpers::colourToCode (getImageColour (ib, overImage)) << ",\n"
|
|
<< indent
|
|
<< getImageCreationCode (ib, downImage) << ", "
|
|
<< CodeHelpers::floatLiteral (getImageOpacity (ib, downImage), 3) << ", "
|
|
<< CodeHelpers::colourToCode (getImageColour (ib, downImage))
|
|
<< ");\n";
|
|
|
|
code.constructorCode += s;
|
|
}
|
|
|
|
static String getImageCreationCode (ImageButton* ib, const ImageRole role)
|
|
{
|
|
const String resName (getImageResource (ib, role));
|
|
|
|
if (resName.isEmpty())
|
|
return "juce::Image()";
|
|
|
|
return "juce::ImageCache::getFromMemory (" + resName + ", " + resName + "Size)";
|
|
}
|
|
|
|
//==============================================================================
|
|
class ImageButtonResourceProperty : public ImageResourceProperty<ImageButton>
|
|
{
|
|
public:
|
|
ImageButtonResourceProperty (ComponentLayout& layout_, ImageButton* const owner_, const ImageRole role_, const String& name)
|
|
: ImageResourceProperty<ImageButton> (*layout_.getDocument(), owner_, name, true),
|
|
role (role_),
|
|
layout (layout_)
|
|
{
|
|
}
|
|
|
|
void setResource (const String& newName) override
|
|
{
|
|
setImageResource (layout, element, role, newName, true);
|
|
}
|
|
|
|
String getResource() const override
|
|
{
|
|
return getImageResource (element, role);
|
|
}
|
|
|
|
private:
|
|
const ImageRole role;
|
|
ComponentLayout& layout;
|
|
};
|
|
|
|
class SetImageResourceAction : public ComponentUndoableAction<ImageButton>
|
|
{
|
|
public:
|
|
SetImageResourceAction (ImageButton* const button,
|
|
ComponentLayout& layout_,
|
|
const ImageRole role_,
|
|
const String& newResource_)
|
|
: ComponentUndoableAction<ImageButton> (button, layout_),
|
|
newResource (newResource_),
|
|
role (role_)
|
|
{
|
|
oldResource = ImageButtonHandler::getImageResource (button, role_);
|
|
}
|
|
|
|
bool perform() override
|
|
{
|
|
showCorrectTab();
|
|
ImageButtonHandler::setImageResource (layout, getComponent(), role, newResource, false);
|
|
return true;
|
|
}
|
|
|
|
bool undo() override
|
|
{
|
|
showCorrectTab();
|
|
ImageButtonHandler::setImageResource (layout, getComponent(), role, oldResource, false);
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
String newResource, oldResource;
|
|
const ImageRole role;
|
|
};
|
|
|
|
//==============================================================================
|
|
static void setImageResource (ComponentLayout& layout, ImageButton* button, const ImageRole role, const String& newName, const bool undoable)
|
|
{
|
|
jassert (role < 3);
|
|
|
|
if (role < 3 && getImageResource (button, role) != newName)
|
|
{
|
|
if (undoable)
|
|
{
|
|
layout.getDocument()->perform (new SetImageResourceAction (button, layout, role, newName),
|
|
"Change image resource");
|
|
}
|
|
else
|
|
{
|
|
button->getProperties().set ("resource" + String ((int) role), newName);
|
|
updateButtonImages (*layout.getDocument(), button);
|
|
layout.changed();
|
|
}
|
|
}
|
|
}
|
|
|
|
static String getImageResource (ImageButton* button, const ImageRole role)
|
|
{
|
|
jassert (role < 3);
|
|
return button->getProperties() ["resource" + String ((int) role)].toString();
|
|
}
|
|
|
|
//==============================================================================
|
|
class SetImageKeepsPropAction : public ComponentUndoableAction<ImageButton>
|
|
{
|
|
public:
|
|
SetImageKeepsPropAction (ImageButton* const button,
|
|
ComponentLayout& layout_,
|
|
const bool newState_)
|
|
: ComponentUndoableAction<ImageButton> (button, layout_),
|
|
newState (newState_)
|
|
{
|
|
oldState = ImageButtonHandler::doesImageKeepProportions (button);
|
|
}
|
|
|
|
bool perform() override
|
|
{
|
|
showCorrectTab();
|
|
ImageButtonHandler::setImageKeepProportions (layout, getComponent(), newState, false);
|
|
return true;
|
|
}
|
|
|
|
bool undo() override
|
|
{
|
|
showCorrectTab();
|
|
ImageButtonHandler::setImageKeepProportions (layout, getComponent(), oldState, false);
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
bool newState, oldState;
|
|
};
|
|
|
|
static bool doesImageKeepProportions (ImageButton* button)
|
|
{
|
|
return button->getProperties().getWithDefault ("keepImageProp", true);
|
|
}
|
|
|
|
static void setImageKeepProportions (ComponentLayout& layout, ImageButton* button, const bool newState, const bool undoable)
|
|
{
|
|
if (undoable)
|
|
{
|
|
layout.perform (std::make_unique<SetImageKeepsPropAction> (button, layout, newState), "change imagebutton proportion mode");
|
|
}
|
|
else
|
|
{
|
|
button->getProperties().set ("keepImageProp", newState);
|
|
updateButtonImages (*layout.getDocument(), button);
|
|
layout.changed();
|
|
}
|
|
}
|
|
|
|
class ImageButtonProportionProperty : public ComponentBooleanProperty<ImageButton>
|
|
{
|
|
public:
|
|
ImageButtonProportionProperty (ComponentLayout& layout_, ImageButton* const owner_)
|
|
: ComponentBooleanProperty<ImageButton> ("proportional", "maintain image proportions", "scale to fit",
|
|
owner_, *layout_.getDocument()),
|
|
layout (layout_)
|
|
{
|
|
}
|
|
|
|
void setState (bool newState) override
|
|
{
|
|
setImageKeepProportions (layout, component, newState, true);
|
|
}
|
|
|
|
bool getState() const override
|
|
{
|
|
return doesImageKeepProportions (component);
|
|
}
|
|
|
|
private:
|
|
ComponentLayout& layout;
|
|
};
|
|
|
|
//==============================================================================
|
|
class SetImageOpacityAction : public ComponentUndoableAction<ImageButton>
|
|
{
|
|
public:
|
|
SetImageOpacityAction (ImageButton* const button,
|
|
ComponentLayout& layout_,
|
|
const ImageRole role_,
|
|
const float newState_)
|
|
: ComponentUndoableAction<ImageButton> (button, layout_),
|
|
role (role_),
|
|
newState (newState_)
|
|
{
|
|
oldState = ImageButtonHandler::getImageOpacity (button, role_);
|
|
}
|
|
|
|
bool perform() override
|
|
{
|
|
showCorrectTab();
|
|
ImageButtonHandler::setImageOpacity (layout, getComponent(), role, newState, false);
|
|
return true;
|
|
}
|
|
|
|
bool undo() override
|
|
{
|
|
showCorrectTab();
|
|
ImageButtonHandler::setImageOpacity (layout, getComponent(), role, oldState, false);
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
const ImageRole role;
|
|
float newState, oldState;
|
|
};
|
|
|
|
static float getImageOpacity (ImageButton* button, const ImageRole role)
|
|
{
|
|
return (float) button->getProperties().getWithDefault ("imageOpacity" + String ((int) role), 1.0f);
|
|
}
|
|
|
|
static void setImageOpacity (ComponentLayout& layout, ImageButton* button, const ImageRole role, const float opacity, const bool undoable)
|
|
{
|
|
if (undoable)
|
|
{
|
|
layout.perform (std::make_unique<SetImageOpacityAction> (button, layout, role, opacity), "change imagebutton opacity");
|
|
}
|
|
else
|
|
{
|
|
button->getProperties().set ("imageOpacity" + String ((int) role), opacity);
|
|
updateButtonImages (*layout.getDocument(), button);
|
|
layout.changed();
|
|
}
|
|
}
|
|
|
|
class ImageButtonOpacityProperty : public SliderPropertyComponent
|
|
{
|
|
public:
|
|
ImageButtonOpacityProperty (ComponentLayout& layout_, ImageButton* const owner_,
|
|
const String& name, const ImageRole role_)
|
|
: SliderPropertyComponent (name, 0.0, 1.0, 0.0),
|
|
owner (owner_),
|
|
layout (layout_),
|
|
role (role_)
|
|
{
|
|
}
|
|
|
|
void setValue (double newValue) override
|
|
{
|
|
setImageOpacity (layout, owner, role, (float) newValue, true);
|
|
}
|
|
|
|
double getValue() const override
|
|
{
|
|
return getImageOpacity (owner, role);
|
|
}
|
|
|
|
private:
|
|
ImageButton* const owner;
|
|
ComponentLayout& layout;
|
|
const ImageRole role;
|
|
};
|
|
|
|
//==============================================================================
|
|
class SetImageColourAction : public ComponentUndoableAction<ImageButton>
|
|
{
|
|
public:
|
|
SetImageColourAction (ImageButton* const button,
|
|
ComponentLayout& layout_,
|
|
const ImageRole role_,
|
|
Colour newState_)
|
|
: ComponentUndoableAction<ImageButton> (button, layout_),
|
|
role (role_),
|
|
newState (newState_)
|
|
{
|
|
oldState = ImageButtonHandler::getImageColour (button, role_);
|
|
}
|
|
|
|
bool perform() override
|
|
{
|
|
showCorrectTab();
|
|
ImageButtonHandler::setImageColour (layout, getComponent(), role, newState, false);
|
|
return true;
|
|
}
|
|
|
|
bool undo() override
|
|
{
|
|
showCorrectTab();
|
|
ImageButtonHandler::setImageColour (layout, getComponent(), role, oldState, false);
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
const ImageRole role;
|
|
Colour newState, oldState;
|
|
};
|
|
|
|
static Colour getImageColour (ImageButton* button, const ImageRole role)
|
|
{
|
|
return Colour::fromString (button->getProperties().getWithDefault ("imageColour" + String ((int) role), "0").toString());
|
|
}
|
|
|
|
static void setImageColour (ComponentLayout& layout, ImageButton* button,
|
|
const ImageRole role, Colour colour, const bool undoable)
|
|
{
|
|
if (undoable)
|
|
{
|
|
layout.perform (std::make_unique<SetImageColourAction> (button, layout, role, colour), "change imagebutton colour");
|
|
}
|
|
else
|
|
{
|
|
button->getProperties().set ("imageColour" + String ((int) role), colour.toString());
|
|
updateButtonImages (*layout.getDocument(), button);
|
|
layout.changed();
|
|
}
|
|
}
|
|
|
|
class ImageButtonColourProperty : public JucerColourPropertyComponent,
|
|
private ChangeListener
|
|
{
|
|
public:
|
|
ImageButtonColourProperty (ComponentLayout& layout_, ImageButton* const owner_,
|
|
const String& name, const ImageRole role_)
|
|
: JucerColourPropertyComponent (name, false),
|
|
owner (owner_),
|
|
layout (layout_),
|
|
role (role_)
|
|
{
|
|
layout_.getDocument()->addChangeListener (this);
|
|
}
|
|
|
|
~ImageButtonColourProperty() override
|
|
{
|
|
layout.getDocument()->removeChangeListener (this);
|
|
}
|
|
|
|
void setColour (Colour newColour) override
|
|
{
|
|
setImageColour (layout, owner, role, newColour, true);
|
|
}
|
|
|
|
Colour getColour() const override
|
|
{
|
|
return getImageColour (owner, role);
|
|
}
|
|
|
|
void resetToDefault() override {}
|
|
|
|
private:
|
|
void changeListenerCallback (ChangeBroadcaster*) override
|
|
{
|
|
refresh();
|
|
}
|
|
|
|
ImageButton* const owner;
|
|
ComponentLayout& layout;
|
|
const ImageRole role;
|
|
};
|
|
|
|
//==============================================================================
|
|
static void updateButtonImages (JucerDocument& document, ImageButton* const ib)
|
|
{
|
|
Image norm = document.getResources().getImageFromCache (getImageResource (ib, normalImage));
|
|
Image over = document.getResources().getImageFromCache (getImageResource (ib, overImage));
|
|
Image down = document.getResources().getImageFromCache (getImageResource (ib, downImage));
|
|
|
|
ib->setImages (false, true, doesImageKeepProportions (ib),
|
|
norm,
|
|
getImageOpacity (ib, normalImage),
|
|
getImageColour (ib, normalImage),
|
|
over,
|
|
getImageOpacity (ib, overImage),
|
|
getImageColour (ib, overImage),
|
|
down,
|
|
getImageOpacity (ib, downImage),
|
|
getImageColour (ib, downImage));
|
|
}
|
|
};
|