/* ============================================================================== This file is part of the JUCE 6 technical preview. Copyright (c) 2020 - Raw Material Software Limited You may use this code under the terms of the GPL v3 (see www.gnu.org/licenses). For this technical preview, this file is not subject to commercial licensing. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ #pragma once //============================================================================== class ButtonHandler : public ComponentTypeHandler { public: ButtonHandler (const String& typeDescription_, const String& className_, const std::type_info& componentClass, const int defaultWidth_, const int defaultHeight_) : ComponentTypeHandler (typeDescription_, className_, componentClass, defaultWidth_, defaultHeight_) {} void getEditableProperties (Component* component, JucerDocument& document, Array& props, bool multipleSelected) override { ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); if (multipleSelected) return; if (auto* b = dynamic_cast (component)) { props.add (new ButtonTextProperty (b, document)); props.add (new ButtonCallbackProperty (b, document)); props.add (new ButtonRadioGroupProperty (b, document)); props.add (new ButtonConnectedEdgeProperty ("connected left", Button::ConnectedOnLeft, b, document)); props.add (new ButtonConnectedEdgeProperty ("connected right", Button::ConnectedOnRight, b, document)); props.add (new ButtonConnectedEdgeProperty ("connected top", Button::ConnectedOnTop, b, document)); props.add (new ButtonConnectedEdgeProperty ("connected bottom", Button::ConnectedOnBottom, b, document)); } } XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { Button* const b = dynamic_cast (comp); XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout); e->setAttribute ("buttonText", b->getButtonText()); e->setAttribute ("connectedEdges", b->getConnectedEdgeFlags()); e->setAttribute ("needsCallback", needsButtonListener (b)); e->setAttribute ("radioGroupId", b->getRadioGroupId()); return e; } bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { Button* const b = dynamic_cast (comp); if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout)) return false; b->setButtonText (xml.getStringAttribute ("buttonText", b->getButtonText())); b->setConnectedEdges (xml.getIntAttribute ("connectedEdges", 0)); setNeedsButtonListener (b, xml.getBoolAttribute ("needsCallback", true)); b->setRadioGroupId (xml.getIntAttribute ("radioGroupId", 0)); return true; } String getCreationParameters (GeneratedCode&, Component* component) override { return quotedString (component->getName(), false); } void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName); Button* const b = dynamic_cast (component); if (b->getButtonText() != b->getName()) { code.constructorCode << memberVariableName << "->setButtonText (" << quotedString (b->getButtonText(), code.shouldUseTransMacro()) << ");\n"; } if (b->getConnectedEdgeFlags() != 0) { StringArray flags; if (b->isConnectedOnLeft()) flags.add ("juce::Button::ConnectedOnLeft"); if (b->isConnectedOnRight()) flags.add ("juce::Button::ConnectedOnRight"); if (b->isConnectedOnTop()) flags.add ("juce::Button::ConnectedOnTop"); if (b->isConnectedOnBottom()) flags.add ("juce::Button::ConnectedOnBottom"); String s; s << memberVariableName << "->setConnectedEdges (" << flags.joinIntoString (" | ") << ");\n"; code.constructorCode += s; } if (b->getRadioGroupId() != 0) code.constructorCode << memberVariableName << "->setRadioGroupId (" << b->getRadioGroupId() << ");\n"; if (needsButtonListener (component)) code.constructorCode << memberVariableName << "->addListener (this);\n"; } void fillInGeneratedCode (Component* component, GeneratedCode& code) override { ComponentTypeHandler::fillInGeneratedCode (component, code); if (needsButtonListener (component)) { String& callback = code.getCallbackCode ("public juce::Button::Listener", "void", "buttonClicked (juce::Button* buttonThatWasClicked)", true); if (callback.isNotEmpty()) callback << "else "; const String memberVariableName (code.document->getComponentLayout()->getComponentMemberVariableName (component)); const String userCodeComment ("UserButtonCode_" + memberVariableName); callback << "if (buttonThatWasClicked == " << memberVariableName << ".get())\n" << "{\n //[" << userCodeComment << "] -- add your button handler code here..\n //[/" << userCodeComment << "]\n}\n"; } } static bool needsButtonListener (Component* button) { return button->getProperties().getWithDefault ("generateListenerCallback", true); } static void setNeedsButtonListener (Component* button, const bool shouldDoCallback) { button->getProperties().set ("generateListenerCallback", shouldDoCallback); } private: //============================================================================== class ButtonTextProperty : public ComponentTextProperty