|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2015 - ROLI 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.
-
- ==============================================================================
- */
-
- #include "../../jucer_Headers.h"
- #include "jucer_ButtonDocument.h"
- #include "../jucer_UtilityFunctions.h"
-
- //==============================================================================
- static const int normalOff = 0;
- static const int overOff = 1;
- static const int downOff = 2;
- static const int normalOn = 3;
- static const int overOn = 4;
- static const int downOn = 5;
- static const int background = 6;
-
-
- //==============================================================================
- ButtonDocument::ButtonDocument (SourceCodeDocument* c)
- : JucerDocument (c)
- {
- paintStatesEnabled [normalOff] = true;
- paintStatesEnabled [overOff] = true;
- paintStatesEnabled [downOff] = true;
- paintStatesEnabled [normalOn] = false;
- paintStatesEnabled [overOn] = false;
- paintStatesEnabled [downOn] = false;
- paintStatesEnabled [background] = false;
-
- parentClasses = "public Button";
-
- for (int i = 7; --i >= 0;)
- {
- paintRoutines[i] = new PaintRoutine();
- paintRoutines[i]->setDocument (this);
- paintRoutines[i]->setBackgroundColour (Colours::transparentBlack);
- }
- }
-
- ButtonDocument::~ButtonDocument()
- {
- }
-
- static const char* const stateNames[] =
- {
- "normal", "over", "down",
- "normal on", "over on", "down on",
- "common background"
- };
-
- int stateNameToIndex (const String& name)
- {
- for (int i = 7; --i >= 0;)
- if (name.equalsIgnoreCase (stateNames[i]))
- return i;
-
- jassertfalse;
- return normalOff;
- }
-
-
- int ButtonDocument::getNumPaintRoutines() const
- {
- int n = 0;
-
- for (int i = 7; --i >= 0;)
- if (paintStatesEnabled [i])
- ++n;
-
- return n;
- }
-
- StringArray ButtonDocument::getPaintRoutineNames() const
- {
- StringArray s;
-
- for (int i = 0; i < 7; ++i)
- if (paintStatesEnabled [i])
- s.add (stateNames [i]);
-
- return s;
- }
-
- PaintRoutine* ButtonDocument::getPaintRoutine (const int index) const
- {
- int n = 0;
-
- for (int i = 0; i < 7; ++i)
- {
- if (paintStatesEnabled [i])
- {
- if (index == n)
- return paintRoutines [i];
- else
- ++n;
- }
- }
-
- jassertfalse;
- return 0;
- }
-
- void ButtonDocument::setStatePaintRoutineEnabled (const int index, bool b)
- {
- jassert (index > 0 && index < 7);
-
- if (paintStatesEnabled [index] != b)
- {
- paintStatesEnabled [index] = b;
- changed();
- }
- }
-
- bool ButtonDocument::isStatePaintRoutineEnabled (const int index) const
- {
- return paintStatesEnabled [index];
- }
-
- int ButtonDocument::chooseBestEnabledPaintRoutine (int paintRoutineWanted) const
- {
- switch (paintRoutineWanted)
- {
- case normalOff: return normalOff;
- case overOff: return paintStatesEnabled [overOff] ? overOff : normalOff;
- case downOff: return paintStatesEnabled [downOff] ? downOff : chooseBestEnabledPaintRoutine (overOff);
- case normalOn: return paintStatesEnabled [normalOn] ? normalOn : normalOff;
- case overOn: return paintStatesEnabled [overOn] ? overOn : (paintStatesEnabled [normalOn] ? normalOn : chooseBestEnabledPaintRoutine (overOff));
- case downOn: return paintStatesEnabled [downOn] ? downOn : ((paintStatesEnabled [overOn] || paintStatesEnabled [normalOn])
- ? chooseBestEnabledPaintRoutine (overOn)
- : chooseBestEnabledPaintRoutine (downOff));
- default: jassertfalse; break;
- }
-
- return normalOff;
- }
-
- //==============================================================================
- String ButtonDocument::getTypeName() const
- {
- return "Button";
- }
-
- JucerDocument* ButtonDocument::createCopy()
- {
- ButtonDocument* newOne = new ButtonDocument (cpp);
- newOne->resources = resources;
-
- ScopedPointer<XmlElement> xml (createXml());
- newOne->loadFromXml (*xml);
-
- return newOne;
- }
-
- XmlElement* ButtonDocument::createXml() const
- {
- XmlElement* const doc = JucerDocument::createXml();
-
- for (int i = 0; i < 7; ++i)
- {
- XmlElement* e = paintRoutines [i]->createXml();
- e->setAttribute ("buttonState", stateNames [i]);
- e->setAttribute ("enabled", paintStatesEnabled [i]);
-
- doc->addChildElement (e);
- }
-
- return doc;
- }
-
- bool ButtonDocument::loadFromXml (const XmlElement& xml)
- {
- if (JucerDocument::loadFromXml (xml))
- {
- for (int i = 7; --i >= 0;)
- paintStatesEnabled [i] = false;
-
- forEachXmlChildElementWithTagName (xml, e, PaintRoutine::xmlTagName)
- {
- const int stateIndex = stateNameToIndex (e->getStringAttribute ("buttonState"));
-
- paintRoutines [stateIndex]->loadFromXml (*e);
- paintStatesEnabled [stateIndex] = e->getBoolAttribute ("enabled", stateIndex < normalOn);
- }
-
- changed();
- getUndoManager().clearUndoHistory();
- return true;
- }
-
- return false;
- }
-
- void ButtonDocument::getOptionalMethods (StringArray& baseClasses,
- StringArray& returnValues,
- StringArray& methods,
- StringArray& initialContents) const
- {
- JucerDocument::getOptionalMethods (baseClasses, returnValues, methods, initialContents);
-
- addMethod ("Button", "void", "clicked()", "", baseClasses, returnValues, methods, initialContents);
- addMethod ("Button", "void", "buttonStateChanged()", "", baseClasses, returnValues, methods, initialContents);
- }
-
- //==============================================================================
- class ButtonStatePaintEnabledProperty : public BooleanPropertyComponent,
- private ChangeListener
- {
- public:
- ButtonStatePaintEnabledProperty (const String& name, ButtonDocument& doc, const int stateMethod_)
- : BooleanPropertyComponent (name, "enabled", "disabled"),
- document (doc),
- stateMethod (stateMethod_)
- {
- document.addChangeListener (this);
- }
-
- ~ButtonStatePaintEnabledProperty()
- {
- document.removeChangeListener (this);
- }
-
- void setState (bool newState)
- {
- document.setStatePaintRoutineEnabled (stateMethod, newState);
- }
-
- bool getState() const
- {
- return document.isStatePaintRoutineEnabled (stateMethod);
- }
-
- private:
- void changeListenerCallback (ChangeBroadcaster*)
- {
- refresh();
- }
-
- ButtonDocument& document;
- const int stateMethod;
- };
-
- void ButtonDocument::addExtraClassProperties (PropertyPanel& panel)
- {
- Array <PropertyComponent*> props;
-
- for (int i = 1; i < 7; ++i)
- props.add (new ButtonStatePaintEnabledProperty (stateNames[i], *this, i));
-
- panel.addSection ("Button paint routines", props);
- }
-
- //==============================================================================
- class ButtonTestComponent : public Button
- {
- public:
- ButtonTestComponent (ButtonDocument* const doc, const bool fillBackground)
- : Button (String()),
- document (doc),
- alwaysFillBackground (fillBackground)
- {
- setClickingTogglesState (true);
- }
-
- void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) override
- {
- if (document->paintStatesEnabled [background])
- {
- document->paintRoutines [background]->fillWithBackground (g, alwaysFillBackground);
- document->paintRoutines [background]->drawElements (g, getLocalBounds());
- }
-
- const int stateIndex
- = getToggleState()
- ? (isButtonDown ? document->chooseBestEnabledPaintRoutine (downOn)
- : (isMouseOverButton ? document->chooseBestEnabledPaintRoutine (overOn)
- : document->chooseBestEnabledPaintRoutine (normalOn)))
- : (isButtonDown ? document->chooseBestEnabledPaintRoutine (downOff)
- : (isMouseOverButton ? document->chooseBestEnabledPaintRoutine (overOff)
- : normalOff));
-
- document->paintRoutines [stateIndex]->fillWithBackground (g, ! document->paintStatesEnabled [background]);
- document->paintRoutines [stateIndex]->drawElements (g, getLocalBounds());
- }
-
- private:
- ButtonDocument* const document;
- const bool alwaysFillBackground;
- };
-
- Component* ButtonDocument::createTestComponent (const bool alwaysFillBackground)
- {
- return new ButtonTestComponent (this, alwaysFillBackground);
- }
-
- //==============================================================================
- void ButtonDocument::fillInGeneratedCode (GeneratedCode& code) const
- {
- JucerDocument::fillInGeneratedCode (code);
-
- code.parentClassInitialiser = "Button (" + quotedString (code.componentName, false) + ")";
- code.removeCallback ("void", "paint (Graphics& g)");
- }
-
- void ButtonDocument::fillInPaintCode (GeneratedCode& code) const
- {
- jassert (paintStatesEnabled [normalOff]);
- String paintCode [7];
-
- for (int i = 0; i < 7; ++i)
- if (paintStatesEnabled [i])
- paintRoutines[i]->fillInGeneratedCode (code, paintCode [i]);
-
- String& s = code.getCallbackCode ("public Button",
- "void",
- "paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown)",
- false);
-
- int numPaintRoutines = getNumPaintRoutines();
-
- if (paintStatesEnabled [background])
- {
- s << paintCode [background] << "\n";
- --numPaintRoutines;
- }
-
- if (numPaintRoutines == 1)
- {
- s << paintCode [normalOff];
- }
- else if (numPaintRoutines == downOff && (paintStatesEnabled [overOff] || paintStatesEnabled [downOff] || paintStatesEnabled [normalOn]))
- {
- if (paintStatesEnabled [normalOn])
- {
- s << "if (getToggleState())\n{\n "
- << CodeHelpers::indent (paintCode [normalOn], 4, false).trimEnd();
- }
- else if (paintStatesEnabled [overOff])
- {
- s << "if (isButtonDown || isMouseOverButton)\n{\n "
- << CodeHelpers::indent (paintCode [overOff], 4, false).trimEnd();
- }
- else
- {
- s << "if (isButtonDown)\n{\n "
- << CodeHelpers::indent (paintCode [downOff], 4, false).trimEnd();
- }
-
- s << "\n}\nelse\n{\n "
- << CodeHelpers::indent (paintCode [normalOff], 4, false).trimEnd()
- << "\n}\n";
- }
- else if (numPaintRoutines == normalOn && paintStatesEnabled [overOff] && paintStatesEnabled [downOff])
- {
- s << "if (isButtonDown)\n{\n "
- << CodeHelpers::indent (paintCode [downOff], 4, false).trimEnd()
- << "\n}\nelse if (isMouseOverButton)\n{\n "
- << CodeHelpers::indent (paintCode [overOff], 4, false).trimEnd()
- << "\n}\nelse\n{\n "
- << CodeHelpers::indent (paintCode [normalOff], 4, false).trimEnd()
- << "\n}\n";
- }
- else
- {
- if (paintStatesEnabled [normalOn] || paintStatesEnabled [overOn] || paintStatesEnabled [downOn])
- {
- s << "switch (getToggleState() ? (isButtonDown ? "
- << chooseBestEnabledPaintRoutine (downOn) << " : (isMouseOverButton ? "
- << chooseBestEnabledPaintRoutine (overOn) << " : "
- << chooseBestEnabledPaintRoutine (normalOn) << "))\n : (isButtonDown ? "
- << chooseBestEnabledPaintRoutine (downOff) << " : (isMouseOverButton ? "
- << chooseBestEnabledPaintRoutine (overOff) << " : 0)))\n{\n";
- }
- else
- {
- s << "switch (isButtonDown ? " << chooseBestEnabledPaintRoutine (downOff)
- << " : (isMouseOverButton ? " << chooseBestEnabledPaintRoutine (overOff)
- << " : 0))\n{\n";
- }
-
- for (int i = 0; i < 6; ++i)
- {
- if (paintStatesEnabled [i])
- {
- s << "case " << i << ":\n {\n "
- << CodeHelpers::indent (paintCode [i], 8, false).trimEnd()
- << "\n break;\n }\n\n";
- }
- }
-
- s << "default:\n break;\n}\n";
- }
- }
|