/* ============================================================================== 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 LabelHandler : public ComponentTypeHandler { public: LabelHandler() : ComponentTypeHandler ("Label", "juce::Label", typeid (Label), 150, 24) { registerColour (Label::backgroundColourId, "background", "bkgCol"); registerColour (Label::textColourId, "text", "textCol"); registerColour (Label::outlineColourId, "outline", "outlineCol"); registerColour (TextEditor::textColourId, "editor text", "edTextCol"); registerColour (TextEditor::backgroundColourId, "editor bkg", "edBkgCol"); registerColour (TextEditor::highlightColourId, "highlight", "hiliteCol"); } Component* createNewComponent (JucerDocument*) override { return new Label ("new label", "label text"); } XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { Label* const l = dynamic_cast (comp); XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout); e->setAttribute ("labelText", l->getText()); e->setAttribute ("editableSingleClick", l->isEditableOnSingleClick()); e->setAttribute ("editableDoubleClick", l->isEditableOnDoubleClick()); e->setAttribute ("focusDiscardsChanges", l->doesLossOfFocusDiscardChanges()); e->setAttribute ("fontname", l->getProperties().getWithDefault ("typefaceName", FontPropertyComponent::getDefaultFont()).toString()); e->setAttribute ("fontsize", roundToInt (l->getFont().getHeight() * 100.0) / 100.0); e->setAttribute ("kerning", roundToInt (l->getFont().getExtraKerningFactor() * 1000.0) / 1000.0); e->setAttribute ("bold", l->getFont().isBold()); e->setAttribute ("italic", l->getFont().isItalic()); e->setAttribute ("justification", l->getJustificationType().getFlags()); if (l->getFont().getTypefaceStyle() != "Regular") { e->setAttribute ("typefaceStyle", l->getFont().getTypefaceStyle()); } return e; } bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { Label* const l = dynamic_cast (comp); if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout)) return false; Label defaultLabel; Font font; font.setHeight ((float) xml.getDoubleAttribute ("fontsize", 15.0)); font.setBold (xml.getBoolAttribute ("bold", false)); font.setItalic (xml.getBoolAttribute ("italic", false)); font.setExtraKerningFactor ((float) xml.getDoubleAttribute ("kerning", 0.0)); auto fontStyle = xml.getStringAttribute ("typefaceStyle"); if (! fontStyle.isEmpty()) font.setTypefaceStyle (fontStyle); l->setFont (font); l->getProperties().set ("typefaceName", xml.getStringAttribute ("fontname", FontPropertyComponent::getDefaultFont())); updateLabelFont (l); l->setJustificationType (Justification (xml.getIntAttribute ("justification", Justification::centred))); l->setText (xml.getStringAttribute ("labelText", "Label Text"), dontSendNotification); l->setEditable (xml.getBoolAttribute ("editableSingleClick", defaultLabel.isEditableOnSingleClick()), xml.getBoolAttribute ("editableDoubleClick", defaultLabel.isEditableOnDoubleClick()), xml.getBoolAttribute ("focusDiscardsChanges", defaultLabel.doesLossOfFocusDiscardChanges())); return true; } static void updateLabelFont (Label* label) { Font f (label->getFont()); f = FontPropertyComponent::applyNameToFont (label->getProperties().getWithDefault ("typefaceName", FontPropertyComponent::getDefaultFont()), f); label->setFont (f); } String getCreationParameters (GeneratedCode& code, Component* component) override { Label* const l = dynamic_cast (component); return quotedString (component->getName(), false) + ",\n" + quotedString (l->getText(), code.shouldUseTransMacro()); } void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName); Label* const l = dynamic_cast (component); String s; s << memberVariableName << "->setFont (" << FontPropertyComponent::getCompleteFontCode (l->getFont(), l->getProperties().getWithDefault ("typefaceName", FontPropertyComponent::getDefaultFont())) << ");\n" << memberVariableName << "->setJustificationType (" << CodeHelpers::justificationToCode (l->getJustificationType()) << ");\n" << memberVariableName << "->setEditable (" << CodeHelpers::boolLiteral (l->isEditableOnSingleClick()) << ", " << CodeHelpers::boolLiteral (l->isEditableOnDoubleClick()) << ", " << CodeHelpers::boolLiteral (l->doesLossOfFocusDiscardChanges()) << ");\n" << getColourIntialisationCode (component, memberVariableName); if (needsCallback (component)) s << memberVariableName << "->addListener (this);\n"; s << '\n'; code.constructorCode += s; } void fillInGeneratedCode (Component* component, GeneratedCode& code) override { ComponentTypeHandler::fillInGeneratedCode (component, code); if (needsCallback (component)) { String& callback = code.getCallbackCode ("public juce::Label::Listener", "void", "labelTextChanged (juce::Label* labelThatHasChanged)", true); if (callback.trim().isNotEmpty()) callback << "else "; const String memberVariableName (code.document->getComponentLayout()->getComponentMemberVariableName (component)); const String userCodeComment ("UserLabelCode_" + memberVariableName); callback << "if (labelThatHasChanged == " << memberVariableName << ".get())\n" << "{\n //[" << userCodeComment << "] -- add your label text handling code here..\n //[/" << userCodeComment << "]\n}\n"; } } void getEditableProperties (Component* component, JucerDocument& document, Array& props, bool multipleSelected) override { ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); if (multipleSelected) return; if (auto* const l = dynamic_cast (component)) { props.add (new LabelTextProperty (l, document)); props.add (new LabelJustificationProperty (l, document)); props.add (new FontNameProperty (l, document)); props.add (new FontStyleProperty (l, document)); props.add (new FontSizeProperty (l, document)); props.add (new FontKerningProperty (l, document)); props.add (new LabelEditableProperty (l, document)); if (l->isEditableOnDoubleClick() || l->isEditableOnSingleClick()) props.add (new LabelLossOfFocusProperty (l, document)); } addColourProperties (component, document, props); } static bool needsCallback (Component* label) { return ((Label*) label)->isEditableOnSingleClick() || ((Label*) label)->isEditableOnDoubleClick(); // xxx should be configurable } private: //============================================================================== class LabelTextProperty : public ComponentTextProperty