migrating to the latest JUCE version

This commit is contained in:
2022-11-04 23:11:33 +01:00
committed by Nikolai Rodionov
parent 4257a0f8ba
commit faf8f18333
2796 changed files with 888518 additions and 784244 deletions

View File

@ -1,389 +1,389 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* b = dynamic_cast<Button*> (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<Button*> (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<Button*> (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<Button*> (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 <Button>
{
public:
ButtonTextProperty (Button* button_, JucerDocument& doc)
: ComponentTextProperty <Button> ("text", 100, false, button_, doc)
{
}
void setText (const String& newText) override
{
document.perform (new ButtonTextChangeAction (component, *document.getComponentLayout(), newText),
"Change button text");
}
String getText() const override
{
return component->getButtonText();
}
private:
class ButtonTextChangeAction : public ComponentUndoableAction <Button>
{
public:
ButtonTextChangeAction (Button* const comp, ComponentLayout& l, const String& newName_)
: ComponentUndoableAction <Button> (comp, l),
newName (newName_)
{
oldName = comp->getButtonText();
}
bool perform()
{
showCorrectTab();
getComponent()->setButtonText (newName);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setButtonText (oldName);
changed();
return true;
}
String newName, oldName;
};
};
class ButtonCallbackProperty : public ComponentBooleanProperty <Button>
{
public:
ButtonCallbackProperty (Button* b, JucerDocument& doc)
: ComponentBooleanProperty <Button> ("callback", "Generate ButtonListener", "Generate ButtonListener", b, doc)
{
}
void setState (bool newState)
{
document.perform (new ButtonCallbackChangeAction (component, *document.getComponentLayout(), newState),
"Change button callback");
}
bool getState() const { return needsButtonListener (component); }
private:
class ButtonCallbackChangeAction : public ComponentUndoableAction <Button>
{
public:
ButtonCallbackChangeAction (Button* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <Button> (comp, l),
newState (newState_)
{
oldState = needsButtonListener (comp);
}
bool perform()
{
showCorrectTab();
setNeedsButtonListener (getComponent(), newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
setNeedsButtonListener (getComponent(), oldState);
changed();
return true;
}
bool newState, oldState;
};
};
class ButtonRadioGroupProperty : public ComponentTextProperty <Button>
{
public:
ButtonRadioGroupProperty (Button* const button_, JucerDocument& doc)
: ComponentTextProperty <Button> ("radio group", 10, false, button_, doc)
{
}
void setText (const String& newText) override
{
document.perform (new ButtonRadioGroupChangeAction (component, *document.getComponentLayout(), newText.getIntValue()),
"Change radio group ID");
}
String getText() const override
{
return String (component->getRadioGroupId());
}
private:
class ButtonRadioGroupChangeAction : public ComponentUndoableAction <Button>
{
public:
ButtonRadioGroupChangeAction (Button* const comp, ComponentLayout& l, const int newId_)
: ComponentUndoableAction <Button> (comp, l),
newId (newId_)
{
oldId = comp->getRadioGroupId();
}
bool perform()
{
showCorrectTab();
getComponent()->setRadioGroupId (newId);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setRadioGroupId (oldId);
changed();
return true;
}
int newId, oldId;
};
};
class ButtonConnectedEdgeProperty : public ComponentBooleanProperty <Button>
{
public:
ButtonConnectedEdgeProperty (const String& name, const int flag_,
Button* b, JucerDocument& doc)
: ComponentBooleanProperty <Button> (name, "Connected", "Connected", b, doc),
flag (flag_)
{
}
void setState (bool newState)
{
document.perform (new ButtonConnectedChangeAction (component, *document.getComponentLayout(), flag, newState),
"Change button connected edges");
}
bool getState() const
{
return (component->getConnectedEdgeFlags() & flag) != 0;
}
private:
const int flag;
class ButtonConnectedChangeAction : public ComponentUndoableAction <Button>
{
public:
ButtonConnectedChangeAction (Button* const comp, ComponentLayout& l, const int flag_, const bool newState_)
: ComponentUndoableAction <Button> (comp, l),
flag (flag_),
newState (newState_)
{
oldState = ((comp->getConnectedEdgeFlags() & flag) != 0);
}
bool perform()
{
showCorrectTab();
if (newState)
getComponent()->setConnectedEdges (getComponent()->getConnectedEdgeFlags() | flag);
else
getComponent()->setConnectedEdges (getComponent()->getConnectedEdgeFlags() & ~flag);
changed();
return true;
}
bool undo()
{
showCorrectTab();
if (oldState)
getComponent()->setConnectedEdges (getComponent()->getConnectedEdgeFlags() | flag);
else
getComponent()->setConnectedEdges (getComponent()->getConnectedEdgeFlags() & ~flag);
changed();
return true;
}
const int flag;
bool newState, oldState;
};
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* b = dynamic_cast<Button*> (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<Button*> (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<Button*> (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<Button*> (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 <Button>
{
public:
ButtonTextProperty (Button* button_, JucerDocument& doc)
: ComponentTextProperty <Button> ("text", 100, false, button_, doc)
{
}
void setText (const String& newText) override
{
document.perform (new ButtonTextChangeAction (component, *document.getComponentLayout(), newText),
"Change button text");
}
String getText() const override
{
return component->getButtonText();
}
private:
class ButtonTextChangeAction : public ComponentUndoableAction <Button>
{
public:
ButtonTextChangeAction (Button* const comp, ComponentLayout& l, const String& newName_)
: ComponentUndoableAction <Button> (comp, l),
newName (newName_)
{
oldName = comp->getButtonText();
}
bool perform()
{
showCorrectTab();
getComponent()->setButtonText (newName);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setButtonText (oldName);
changed();
return true;
}
String newName, oldName;
};
};
class ButtonCallbackProperty : public ComponentBooleanProperty <Button>
{
public:
ButtonCallbackProperty (Button* b, JucerDocument& doc)
: ComponentBooleanProperty <Button> ("callback", "Generate ButtonListener", "Generate ButtonListener", b, doc)
{
}
void setState (bool newState)
{
document.perform (new ButtonCallbackChangeAction (component, *document.getComponentLayout(), newState),
"Change button callback");
}
bool getState() const { return needsButtonListener (component); }
private:
class ButtonCallbackChangeAction : public ComponentUndoableAction <Button>
{
public:
ButtonCallbackChangeAction (Button* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <Button> (comp, l),
newState (newState_)
{
oldState = needsButtonListener (comp);
}
bool perform()
{
showCorrectTab();
setNeedsButtonListener (getComponent(), newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
setNeedsButtonListener (getComponent(), oldState);
changed();
return true;
}
bool newState, oldState;
};
};
class ButtonRadioGroupProperty : public ComponentTextProperty <Button>
{
public:
ButtonRadioGroupProperty (Button* const button_, JucerDocument& doc)
: ComponentTextProperty <Button> ("radio group", 10, false, button_, doc)
{
}
void setText (const String& newText) override
{
document.perform (new ButtonRadioGroupChangeAction (component, *document.getComponentLayout(), newText.getIntValue()),
"Change radio group ID");
}
String getText() const override
{
return String (component->getRadioGroupId());
}
private:
class ButtonRadioGroupChangeAction : public ComponentUndoableAction <Button>
{
public:
ButtonRadioGroupChangeAction (Button* const comp, ComponentLayout& l, const int newId_)
: ComponentUndoableAction <Button> (comp, l),
newId (newId_)
{
oldId = comp->getRadioGroupId();
}
bool perform()
{
showCorrectTab();
getComponent()->setRadioGroupId (newId);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setRadioGroupId (oldId);
changed();
return true;
}
int newId, oldId;
};
};
class ButtonConnectedEdgeProperty : public ComponentBooleanProperty <Button>
{
public:
ButtonConnectedEdgeProperty (const String& name, const int flag_,
Button* b, JucerDocument& doc)
: ComponentBooleanProperty <Button> (name, "Connected", "Connected", b, doc),
flag (flag_)
{
}
void setState (bool newState)
{
document.perform (new ButtonConnectedChangeAction (component, *document.getComponentLayout(), flag, newState),
"Change button connected edges");
}
bool getState() const
{
return (component->getConnectedEdgeFlags() & flag) != 0;
}
private:
const int flag;
class ButtonConnectedChangeAction : public ComponentUndoableAction <Button>
{
public:
ButtonConnectedChangeAction (Button* const comp, ComponentLayout& l, const int flag_, const bool newState_)
: ComponentUndoableAction <Button> (comp, l),
flag (flag_),
newState (newState_)
{
oldState = ((comp->getConnectedEdgeFlags() & flag) != 0);
}
bool perform()
{
showCorrectTab();
if (newState)
getComponent()->setConnectedEdges (getComponent()->getConnectedEdgeFlags() | flag);
else
getComponent()->setConnectedEdges (getComponent()->getConnectedEdgeFlags() & ~flag);
changed();
return true;
}
bool undo()
{
showCorrectTab();
if (oldState)
getComponent()->setConnectedEdges (getComponent()->getConnectedEdgeFlags() | flag);
else
getComponent()->setConnectedEdges (getComponent()->getConnectedEdgeFlags() & ~flag);
changed();
return true;
}
const int flag;
bool newState, oldState;
};
};
};

View File

@ -1,446 +1,446 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 ComboBoxHandler : public ComponentTypeHandler
{
public:
ComboBoxHandler()
: ComponentTypeHandler ("Combo Box", "juce::ComboBox", typeid (ComboBox), 150, 24)
{}
Component* createNewComponent (JucerDocument*) override
{
return new ComboBox ("new combo box");
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
if (auto* const c = dynamic_cast<ComboBox*> (comp))
{
if (auto* e = ComponentTypeHandler::createXmlFor (comp, layout))
{
e->setAttribute ("editable", c->isTextEditable());
e->setAttribute ("layout", c->getJustificationType().getFlags());
e->setAttribute ("items", c->getProperties() ["items"].toString());
e->setAttribute ("textWhenNonSelected", c->getTextWhenNothingSelected());
e->setAttribute ("textWhenNoItems", c->getTextWhenNoChoicesAvailable());
return e;
}
}
return nullptr;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
ComboBox defaultBox;
if (ComboBox* const c = dynamic_cast<ComboBox*> (comp))
{
c->setEditableText (xml.getBoolAttribute ("editable", defaultBox.isTextEditable()));
c->setJustificationType (Justification (xml.getIntAttribute ("layout", defaultBox.getJustificationType().getFlags())));
c->getProperties().set ("items", xml.getStringAttribute ("items", String()));
c->setTextWhenNothingSelected (xml.getStringAttribute ("textWhenNonSelected", defaultBox.getTextWhenNothingSelected()));
c->setTextWhenNoChoicesAvailable (xml.getStringAttribute ("textWhenNoItems", defaultBox.getTextWhenNoChoicesAvailable()));
updateItems (c);
return true;
}
return false;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* c = dynamic_cast<ComboBox*> (component))
{
props.add (new ComboItemsProperty (c, document));
props.add (new ComboEditableProperty (c, document));
props.add (new ComboJustificationProperty (c, document));
props.add (new ComboTextWhenNoneSelectedProperty (c, document));
props.add (new ComboTextWhenNoItemsProperty (c, document));
}
}
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);
ComboBox* const c = dynamic_cast<ComboBox*> (component);
if (c == nullptr)
{
jassertfalse;
return;
}
String s;
s << memberVariableName << "->setEditableText (" << CodeHelpers::boolLiteral (c->isTextEditable()) << ");\n"
<< memberVariableName << "->setJustificationType (" << CodeHelpers::justificationToCode (c->getJustificationType()) << ");\n"
<< memberVariableName << "->setTextWhenNothingSelected (" << quotedString (c->getTextWhenNothingSelected(), code.shouldUseTransMacro()) << ");\n"
<< memberVariableName << "->setTextWhenNoChoicesAvailable (" << quotedString (c->getTextWhenNoChoicesAvailable(), code.shouldUseTransMacro()) << ");\n";
StringArray lines;
lines.addLines (c->getProperties() ["items"].toString());
int itemId = 1;
for (int i = 0; i < lines.size(); ++i)
{
if (lines[i].trim().isEmpty())
s << memberVariableName << "->addSeparator();\n";
else
s << memberVariableName << "->addItem ("
<< quotedString (lines[i], code.shouldUseTransMacro()) << ", " << itemId++ << ");\n";
}
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::ComboBox::Listener",
"void",
"comboBoxChanged (juce::ComboBox* comboBoxThatHasChanged)",
true);
if (callback.trim().isNotEmpty())
callback << "else ";
const String memberVariableName (code.document->getComponentLayout()->getComponentMemberVariableName (component));
const String userCodeComment ("UserComboBoxCode_" + memberVariableName);
callback
<< "if (comboBoxThatHasChanged == " << memberVariableName << ".get())\n"
<< "{\n //[" << userCodeComment << "] -- add your combo box handling code here..\n //[/" << userCodeComment << "]\n}\n";
}
}
static void updateItems (ComboBox* c)
{
StringArray lines;
lines.addLines (c->getProperties() ["items"].toString());
c->clear();
int itemId = 1;
for (int i = 0; i < lines.size(); ++i)
{
if (lines[i].trim().isEmpty())
c->addSeparator();
else
c->addItem (lines[i], itemId++);
}
}
static bool needsCallback (Component*)
{
return true; // xxx should be configurable
}
private:
class ComboEditableProperty : public ComponentBooleanProperty <ComboBox>
{
public:
ComboEditableProperty (ComboBox* comp, JucerDocument& doc)
: ComponentBooleanProperty <ComboBox> ("editable", "Text is editable", "Text is editable", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new ComboEditableChangeAction (component, *document.getComponentLayout(), newState),
"Change combo box editability");
}
bool getState() const
{
return component->isTextEditable();
}
private:
class ComboEditableChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboEditableChangeAction (ComboBox* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_)
{
oldState = comp->isTextEditable();
}
bool perform()
{
showCorrectTab();
getComponent()->setEditableText (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setEditableText (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class ComboJustificationProperty : public JustificationProperty
{
public:
ComboJustificationProperty (ComboBox* comp, JucerDocument& doc)
: JustificationProperty ("text layout", false),
component (comp),
document (doc)
{
}
void setJustification (Justification newJustification)
{
document.perform (new ComboJustifyChangeAction (component, *document.getComponentLayout(), newJustification),
"Change combo box justification");
}
Justification getJustification() const { return component->getJustificationType(); }
private:
ComboBox* const component;
JucerDocument& document;
class ComboJustifyChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboJustifyChangeAction (ComboBox* const comp, ComponentLayout& l, Justification newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_),
oldState (comp->getJustificationType())
{
}
bool perform()
{
showCorrectTab();
getComponent()->setJustificationType (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setJustificationType (oldState);
changed();
return true;
}
Justification newState, oldState;
};
};
//==============================================================================
class ComboItemsProperty : public ComponentTextProperty <ComboBox>
{
public:
ComboItemsProperty (ComboBox* comp, JucerDocument& doc)
: ComponentTextProperty <ComboBox> ("items", 10000, true, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new ComboItemsChangeAction (component, *document.getComponentLayout(), newText),
"Change combo box items");
}
String getText() const override
{
return component->getProperties() ["items"];
}
private:
class ComboItemsChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboItemsChangeAction (ComboBox* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_)
{
oldState = comp->getProperties() ["items"];
}
bool perform()
{
showCorrectTab();
getComponent()->getProperties().set ("items", newState);
ComboBoxHandler::updateItems (getComponent());
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->getProperties().set ("items", oldState);
ComboBoxHandler::updateItems (getComponent());
changed();
return true;
}
String newState, oldState;
};
};
//==============================================================================
class ComboTextWhenNoneSelectedProperty : public ComponentTextProperty <ComboBox>
{
public:
ComboTextWhenNoneSelectedProperty (ComboBox* comp, JucerDocument& doc)
: ComponentTextProperty <ComboBox> ("text when none selected", 200, false, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new ComboNonSelTextChangeAction (component, *document.getComponentLayout(), newText),
"Change combo box text when nothing selected");
}
String getText() const override
{
return component->getTextWhenNothingSelected();
}
private:
class ComboNonSelTextChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboNonSelTextChangeAction (ComboBox* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_)
{
oldState = comp->getTextWhenNothingSelected();
}
bool perform()
{
showCorrectTab();
getComponent()->setTextWhenNothingSelected (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setTextWhenNothingSelected (oldState);
changed();
return true;
}
String newState, oldState;
};
};
//==============================================================================
class ComboTextWhenNoItemsProperty : public ComponentTextProperty <ComboBox>
{
public:
ComboTextWhenNoItemsProperty (ComboBox* comp, JucerDocument& doc)
: ComponentTextProperty <ComboBox> ("text when no items", 200, false, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new ComboNoItemTextChangeAction (component, *document.getComponentLayout(), newText),
"Change combo box 'no items' text");
}
String getText() const override
{
return component->getTextWhenNoChoicesAvailable();
}
private:
class ComboNoItemTextChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboNoItemTextChangeAction (ComboBox* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_)
{
oldState = comp->getTextWhenNoChoicesAvailable();
}
bool perform()
{
showCorrectTab();
getComponent()->setTextWhenNoChoicesAvailable (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setTextWhenNoChoicesAvailable (oldState);
changed();
return true;
}
String newState, oldState;
};
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 ComboBoxHandler : public ComponentTypeHandler
{
public:
ComboBoxHandler()
: ComponentTypeHandler ("Combo Box", "juce::ComboBox", typeid (ComboBox), 150, 24)
{}
Component* createNewComponent (JucerDocument*) override
{
return new ComboBox ("new combo box");
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
if (auto* const c = dynamic_cast<ComboBox*> (comp))
{
if (auto* e = ComponentTypeHandler::createXmlFor (comp, layout))
{
e->setAttribute ("editable", c->isTextEditable());
e->setAttribute ("layout", c->getJustificationType().getFlags());
e->setAttribute ("items", c->getProperties() ["items"].toString());
e->setAttribute ("textWhenNonSelected", c->getTextWhenNothingSelected());
e->setAttribute ("textWhenNoItems", c->getTextWhenNoChoicesAvailable());
return e;
}
}
return nullptr;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
ComboBox defaultBox;
if (ComboBox* const c = dynamic_cast<ComboBox*> (comp))
{
c->setEditableText (xml.getBoolAttribute ("editable", defaultBox.isTextEditable()));
c->setJustificationType (Justification (xml.getIntAttribute ("layout", defaultBox.getJustificationType().getFlags())));
c->getProperties().set ("items", xml.getStringAttribute ("items", String()));
c->setTextWhenNothingSelected (xml.getStringAttribute ("textWhenNonSelected", defaultBox.getTextWhenNothingSelected()));
c->setTextWhenNoChoicesAvailable (xml.getStringAttribute ("textWhenNoItems", defaultBox.getTextWhenNoChoicesAvailable()));
updateItems (c);
return true;
}
return false;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* c = dynamic_cast<ComboBox*> (component))
{
props.add (new ComboItemsProperty (c, document));
props.add (new ComboEditableProperty (c, document));
props.add (new ComboJustificationProperty (c, document));
props.add (new ComboTextWhenNoneSelectedProperty (c, document));
props.add (new ComboTextWhenNoItemsProperty (c, document));
}
}
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);
ComboBox* const c = dynamic_cast<ComboBox*> (component);
if (c == nullptr)
{
jassertfalse;
return;
}
String s;
s << memberVariableName << "->setEditableText (" << CodeHelpers::boolLiteral (c->isTextEditable()) << ");\n"
<< memberVariableName << "->setJustificationType (" << CodeHelpers::justificationToCode (c->getJustificationType()) << ");\n"
<< memberVariableName << "->setTextWhenNothingSelected (" << quotedString (c->getTextWhenNothingSelected(), code.shouldUseTransMacro()) << ");\n"
<< memberVariableName << "->setTextWhenNoChoicesAvailable (" << quotedString (c->getTextWhenNoChoicesAvailable(), code.shouldUseTransMacro()) << ");\n";
StringArray lines;
lines.addLines (c->getProperties() ["items"].toString());
int itemId = 1;
for (int i = 0; i < lines.size(); ++i)
{
if (lines[i].trim().isEmpty())
s << memberVariableName << "->addSeparator();\n";
else
s << memberVariableName << "->addItem ("
<< quotedString (lines[i], code.shouldUseTransMacro()) << ", " << itemId++ << ");\n";
}
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::ComboBox::Listener",
"void",
"comboBoxChanged (juce::ComboBox* comboBoxThatHasChanged)",
true);
if (callback.trim().isNotEmpty())
callback << "else ";
const String memberVariableName (code.document->getComponentLayout()->getComponentMemberVariableName (component));
const String userCodeComment ("UserComboBoxCode_" + memberVariableName);
callback
<< "if (comboBoxThatHasChanged == " << memberVariableName << ".get())\n"
<< "{\n //[" << userCodeComment << "] -- add your combo box handling code here..\n //[/" << userCodeComment << "]\n}\n";
}
}
static void updateItems (ComboBox* c)
{
StringArray lines;
lines.addLines (c->getProperties() ["items"].toString());
c->clear();
int itemId = 1;
for (int i = 0; i < lines.size(); ++i)
{
if (lines[i].trim().isEmpty())
c->addSeparator();
else
c->addItem (lines[i], itemId++);
}
}
static bool needsCallback (Component*)
{
return true; // xxx should be configurable
}
private:
class ComboEditableProperty : public ComponentBooleanProperty <ComboBox>
{
public:
ComboEditableProperty (ComboBox* comp, JucerDocument& doc)
: ComponentBooleanProperty <ComboBox> ("editable", "Text is editable", "Text is editable", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new ComboEditableChangeAction (component, *document.getComponentLayout(), newState),
"Change combo box editability");
}
bool getState() const
{
return component->isTextEditable();
}
private:
class ComboEditableChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboEditableChangeAction (ComboBox* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_)
{
oldState = comp->isTextEditable();
}
bool perform()
{
showCorrectTab();
getComponent()->setEditableText (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setEditableText (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class ComboJustificationProperty : public JustificationProperty
{
public:
ComboJustificationProperty (ComboBox* comp, JucerDocument& doc)
: JustificationProperty ("text layout", false),
component (comp),
document (doc)
{
}
void setJustification (Justification newJustification)
{
document.perform (new ComboJustifyChangeAction (component, *document.getComponentLayout(), newJustification),
"Change combo box justification");
}
Justification getJustification() const { return component->getJustificationType(); }
private:
ComboBox* const component;
JucerDocument& document;
class ComboJustifyChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboJustifyChangeAction (ComboBox* const comp, ComponentLayout& l, Justification newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_),
oldState (comp->getJustificationType())
{
}
bool perform()
{
showCorrectTab();
getComponent()->setJustificationType (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setJustificationType (oldState);
changed();
return true;
}
Justification newState, oldState;
};
};
//==============================================================================
class ComboItemsProperty : public ComponentTextProperty <ComboBox>
{
public:
ComboItemsProperty (ComboBox* comp, JucerDocument& doc)
: ComponentTextProperty <ComboBox> ("items", 10000, true, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new ComboItemsChangeAction (component, *document.getComponentLayout(), newText),
"Change combo box items");
}
String getText() const override
{
return component->getProperties() ["items"];
}
private:
class ComboItemsChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboItemsChangeAction (ComboBox* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_)
{
oldState = comp->getProperties() ["items"];
}
bool perform()
{
showCorrectTab();
getComponent()->getProperties().set ("items", newState);
ComboBoxHandler::updateItems (getComponent());
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->getProperties().set ("items", oldState);
ComboBoxHandler::updateItems (getComponent());
changed();
return true;
}
String newState, oldState;
};
};
//==============================================================================
class ComboTextWhenNoneSelectedProperty : public ComponentTextProperty <ComboBox>
{
public:
ComboTextWhenNoneSelectedProperty (ComboBox* comp, JucerDocument& doc)
: ComponentTextProperty <ComboBox> ("text when none selected", 200, false, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new ComboNonSelTextChangeAction (component, *document.getComponentLayout(), newText),
"Change combo box text when nothing selected");
}
String getText() const override
{
return component->getTextWhenNothingSelected();
}
private:
class ComboNonSelTextChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboNonSelTextChangeAction (ComboBox* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_)
{
oldState = comp->getTextWhenNothingSelected();
}
bool perform()
{
showCorrectTab();
getComponent()->setTextWhenNothingSelected (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setTextWhenNothingSelected (oldState);
changed();
return true;
}
String newState, oldState;
};
};
//==============================================================================
class ComboTextWhenNoItemsProperty : public ComponentTextProperty <ComboBox>
{
public:
ComboTextWhenNoItemsProperty (ComboBox* comp, JucerDocument& doc)
: ComponentTextProperty <ComboBox> ("text when no items", 200, false, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new ComboNoItemTextChangeAction (component, *document.getComponentLayout(), newText),
"Change combo box 'no items' text");
}
String getText() const override
{
return component->getTextWhenNoChoicesAvailable();
}
private:
class ComboNoItemTextChangeAction : public ComponentUndoableAction <ComboBox>
{
public:
ComboNoItemTextChangeAction (ComboBox* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <ComboBox> (comp, l),
newState (newState_)
{
oldState = comp->getTextWhenNoChoicesAvailable();
}
bool perform()
{
showCorrectTab();
getComponent()->setTextWhenNoChoicesAvailable (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setTextWhenNoChoicesAvailable (oldState);
changed();
return true;
}
String newState, oldState;
};
};
};

View File

@ -1,178 +1,178 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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
#include "jucer_ComponentTypeHandler.h"
#include "jucer_ComponentUndoableAction.h"
#include "../Properties/jucer_ComponentTextProperty.h"
//==============================================================================
class ComponentNameProperty : public ComponentTextProperty <Component>
{
public:
ComponentNameProperty (Component* comp, JucerDocument& doc)
: ComponentTextProperty <Component> ("name", 40, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new CompNameChangeAction (component, *document.getComponentLayout(), newText),
"Change component name");
}
String getText() const override
{
return component->getName();
}
private:
class CompNameChangeAction : public ComponentUndoableAction <Component>
{
public:
CompNameChangeAction (Component* const comp, ComponentLayout& l, const String& nm)
: ComponentUndoableAction <Component> (comp, l),
newName (nm), oldName (comp->getName())
{
}
bool perform()
{
showCorrectTab();
getComponent()->setName (newName);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setName (oldName);
changed();
return true;
}
String newName, oldName;
};
};
//==============================================================================
class ComponentMemberNameProperty : public ComponentTextProperty <Component>
{
public:
ComponentMemberNameProperty (Component* comp, JucerDocument& doc)
: ComponentTextProperty <Component> ("member name", 40, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new CompMemberNameChangeAction (component, *document.getComponentLayout(), newText),
"Change component member name");
}
String getText() const override
{
return document.getComponentLayout()->getComponentMemberVariableName (component);
}
private:
class CompMemberNameChangeAction : public ComponentUndoableAction <Component>
{
public:
CompMemberNameChangeAction (Component* const comp, ComponentLayout& l, const String& nm)
: ComponentUndoableAction <Component> (comp, l),
newName (nm), oldName (layout.getComponentMemberVariableName (comp))
{
}
bool perform()
{
showCorrectTab();
layout.setComponentMemberVariableName (getComponent(), newName);
return true;
}
bool undo()
{
showCorrectTab();
layout.setComponentMemberVariableName (getComponent(), oldName);
return true;
}
String newName, oldName;
};
};
//==============================================================================
class ComponentVirtualClassProperty : public ComponentTextProperty <Component>
{
public:
ComponentVirtualClassProperty (Component* comp, JucerDocument& doc)
: ComponentTextProperty <Component> ("virtual class", 40, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new CompVirtualClassChangeAction (component, *document.getComponentLayout(), newText),
"Change component virtual class name");
}
String getText() const override
{
return document.getComponentLayout()->getComponentVirtualClassName (component);
}
private:
class CompVirtualClassChangeAction : public ComponentUndoableAction <Component>
{
public:
CompVirtualClassChangeAction (Component* const comp, ComponentLayout& l, const String& nm)
: ComponentUndoableAction <Component> (comp, l),
newName (nm), oldName (layout.getComponentVirtualClassName (comp))
{
}
bool perform()
{
showCorrectTab();
layout.setComponentVirtualClassName (getComponent(), newName);
return true;
}
bool undo()
{
showCorrectTab();
layout.setComponentVirtualClassName (getComponent(), oldName);
return true;
}
String newName, oldName;
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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
#include "jucer_ComponentTypeHandler.h"
#include "jucer_ComponentUndoableAction.h"
#include "../Properties/jucer_ComponentTextProperty.h"
//==============================================================================
class ComponentNameProperty : public ComponentTextProperty <Component>
{
public:
ComponentNameProperty (Component* comp, JucerDocument& doc)
: ComponentTextProperty <Component> ("name", 40, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new CompNameChangeAction (component, *document.getComponentLayout(), newText),
"Change component name");
}
String getText() const override
{
return component->getName();
}
private:
class CompNameChangeAction : public ComponentUndoableAction <Component>
{
public:
CompNameChangeAction (Component* const comp, ComponentLayout& l, const String& nm)
: ComponentUndoableAction <Component> (comp, l),
newName (nm), oldName (comp->getName())
{
}
bool perform()
{
showCorrectTab();
getComponent()->setName (newName);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setName (oldName);
changed();
return true;
}
String newName, oldName;
};
};
//==============================================================================
class ComponentMemberNameProperty : public ComponentTextProperty <Component>
{
public:
ComponentMemberNameProperty (Component* comp, JucerDocument& doc)
: ComponentTextProperty <Component> ("member name", 40, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new CompMemberNameChangeAction (component, *document.getComponentLayout(), newText),
"Change component member name");
}
String getText() const override
{
return document.getComponentLayout()->getComponentMemberVariableName (component);
}
private:
class CompMemberNameChangeAction : public ComponentUndoableAction <Component>
{
public:
CompMemberNameChangeAction (Component* const comp, ComponentLayout& l, const String& nm)
: ComponentUndoableAction <Component> (comp, l),
newName (nm), oldName (layout.getComponentMemberVariableName (comp))
{
}
bool perform()
{
showCorrectTab();
layout.setComponentMemberVariableName (getComponent(), newName);
return true;
}
bool undo()
{
showCorrectTab();
layout.setComponentMemberVariableName (getComponent(), oldName);
return true;
}
String newName, oldName;
};
};
//==============================================================================
class ComponentVirtualClassProperty : public ComponentTextProperty <Component>
{
public:
ComponentVirtualClassProperty (Component* comp, JucerDocument& doc)
: ComponentTextProperty <Component> ("virtual class", 40, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new CompVirtualClassChangeAction (component, *document.getComponentLayout(), newText),
"Change component virtual class name");
}
String getText() const override
{
return document.getComponentLayout()->getComponentVirtualClassName (component);
}
private:
class CompVirtualClassChangeAction : public ComponentUndoableAction <Component>
{
public:
CompVirtualClassChangeAction (Component* const comp, ComponentLayout& l, const String& nm)
: ComponentUndoableAction <Component> (comp, l),
newName (nm), oldName (layout.getComponentVirtualClassName (comp))
{
}
bool perform()
{
showCorrectTab();
layout.setComponentVirtualClassName (getComponent(), newName);
return true;
}
bool undo()
{
showCorrectTab();
layout.setComponentVirtualClassName (getComponent(), oldName);
return true;
}
String newName, oldName;
};
};

View File

@ -1,147 +1,147 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 ComponentOverlayComponent;
class ComponentLayout;
#include "../jucer_GeneratedCode.h"
#include "../UI/jucer_RelativePositionedRectangle.h"
//==============================================================================
/**
Base class for handlers that can understand the properties of all the component classes.
*/
class ComponentTypeHandler
{
public:
//==============================================================================
ComponentTypeHandler (const String& typeDescription_,
const String& className_,
const std::type_info& componentClass,
const int defaultWidth_,
const int defaultHeight_);
virtual ~ComponentTypeHandler() {}
//==============================================================================
virtual bool canHandle (Component& component) const;
static ComponentTypeHandler* getHandlerFor (Component& component);
//==============================================================================
virtual String getXmlTagName() const noexcept
{
if (className.startsWith ("juce::"))
return className.substring (6).toUpperCase();
return className.toUpperCase();
}
static ComponentTypeHandler* getHandlerForXmlTag (const String& tagName);
virtual XmlElement* createXmlFor (Component* component, const ComponentLayout* layout);
virtual bool restoreFromXml (const XmlElement& xml, Component* component, const ComponentLayout* layout);
virtual void getEditableProperties (Component* component,
JucerDocument& document,
Array<PropertyComponent*>& props,
bool multipleSelected);
virtual void addPropertiesToPropertyPanel (Component* component,
JucerDocument& document,
PropertyPanel& panel,
bool multipleSelected);
void registerEditableColour (int colourId,
const String& colourIdCode,
const String& colourName,
const String& xmlTagName);
#define registerColour(colourId, colourName, xmlTagName) \
registerEditableColour (colourId, #colourId, colourName, xmlTagName)
void addColourProperties (Component* component,
JucerDocument& document,
Array<PropertyComponent*>& props);
String getColourIntialisationCode (Component* component,
const String& objectName);
//==============================================================================
virtual Component* createNewComponent (JucerDocument*) = 0;
virtual Component* createCopyOf (JucerDocument*, Component& existing);
virtual ComponentOverlayComponent* createOverlayComponent (Component* child, ComponentLayout& layout);
virtual void showPopupMenu (Component* component,
ComponentLayout& layout);
//==============================================================================
// Code-generation methods:
virtual void fillInGeneratedCode (Component* component, GeneratedCode& code);
virtual void fillInMemberVariableDeclarations (GeneratedCode&, Component*, const String& memberVariableName);
virtual void fillInResizeCode (GeneratedCode&, Component*, const String& memberVariableName);
virtual void fillInCreationCode (GeneratedCode&, Component*, const String& memberVariableName);
virtual String getCreationParameters (GeneratedCode&, Component*);
virtual void fillInDeletionCode (GeneratedCode&, Component*, const String& memberVariableName);
//==============================================================================
const String& getTypeName() const noexcept { return typeName; }
virtual String getClassName (Component*) const { return className; }
int getDefaultWidth() const noexcept { return defaultWidth; }
int getDefaultHeight() const noexcept { return defaultHeight; }
static int64 getComponentId (Component* comp);
static void setComponentId (Component* comp, const int64 newID);
static RelativePositionedRectangle getComponentPosition (Component* comp);
static void setComponentPosition (Component* comp,
const RelativePositionedRectangle& newPos,
const ComponentLayout* layout);
static JucerDocument* findParentDocument (Component* component);
protected:
//==============================================================================
const String typeName, className, virtualClass, componentClassRawName;
int defaultWidth, defaultHeight;
struct ComponentColourInfo
{
int colourId;
String colourIdCode, colourName, xmlTagName;
};
OwnedArray<ComponentColourInfo> colours;
private:
JUCE_DECLARE_NON_COPYABLE (ComponentTypeHandler)
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 ComponentOverlayComponent;
class ComponentLayout;
#include "../jucer_GeneratedCode.h"
#include "../UI/jucer_RelativePositionedRectangle.h"
//==============================================================================
/**
Base class for handlers that can understand the properties of all the component classes.
*/
class ComponentTypeHandler
{
public:
//==============================================================================
ComponentTypeHandler (const String& typeDescription_,
const String& className_,
const std::type_info& componentClass,
const int defaultWidth_,
const int defaultHeight_);
virtual ~ComponentTypeHandler() {}
//==============================================================================
virtual bool canHandle (Component& component) const;
static ComponentTypeHandler* getHandlerFor (Component& component);
//==============================================================================
virtual String getXmlTagName() const noexcept
{
if (className.startsWith ("juce::"))
return className.substring (6).toUpperCase();
return className.toUpperCase();
}
static ComponentTypeHandler* getHandlerForXmlTag (const String& tagName);
virtual XmlElement* createXmlFor (Component* component, const ComponentLayout* layout);
virtual bool restoreFromXml (const XmlElement& xml, Component* component, const ComponentLayout* layout);
virtual void getEditableProperties (Component* component,
JucerDocument& document,
Array<PropertyComponent*>& props,
bool multipleSelected);
virtual void addPropertiesToPropertyPanel (Component* component,
JucerDocument& document,
PropertyPanel& panel,
bool multipleSelected);
void registerEditableColour (int colourId,
const String& colourIdCode,
const String& colourName,
const String& xmlTagName);
#define registerColour(colourId, colourName, xmlTagName) \
registerEditableColour (colourId, #colourId, colourName, xmlTagName)
void addColourProperties (Component* component,
JucerDocument& document,
Array<PropertyComponent*>& props);
String getColourIntialisationCode (Component* component,
const String& objectName);
//==============================================================================
virtual Component* createNewComponent (JucerDocument*) = 0;
virtual Component* createCopyOf (JucerDocument*, Component& existing);
virtual ComponentOverlayComponent* createOverlayComponent (Component* child, ComponentLayout& layout);
virtual void showPopupMenu (Component* component,
ComponentLayout& layout);
//==============================================================================
// Code-generation methods:
virtual void fillInGeneratedCode (Component* component, GeneratedCode& code);
virtual void fillInMemberVariableDeclarations (GeneratedCode&, Component*, const String& memberVariableName);
virtual void fillInResizeCode (GeneratedCode&, Component*, const String& memberVariableName);
virtual void fillInCreationCode (GeneratedCode&, Component*, const String& memberVariableName);
virtual String getCreationParameters (GeneratedCode&, Component*);
virtual void fillInDeletionCode (GeneratedCode&, Component*, const String& memberVariableName);
//==============================================================================
const String& getTypeName() const noexcept { return typeName; }
virtual String getClassName (Component*) const { return className; }
int getDefaultWidth() const noexcept { return defaultWidth; }
int getDefaultHeight() const noexcept { return defaultHeight; }
static int64 getComponentId (Component* comp);
static void setComponentId (Component* comp, const int64 newID);
static RelativePositionedRectangle getComponentPosition (Component* comp);
static void setComponentPosition (Component* comp,
const RelativePositionedRectangle& newPos,
const ComponentLayout* layout);
static JucerDocument* findParentDocument (Component* component);
protected:
//==============================================================================
const String typeName, className, virtualClass, componentClassRawName;
int defaultWidth, defaultHeight;
struct ComponentColourInfo
{
int colourId;
String colourIdCode, colourName, xmlTagName;
};
OwnedArray<ComponentColourInfo> colours;
private:
JUCE_DECLARE_NON_COPYABLE (ComponentTypeHandler)
};

View File

@ -1,75 +1,75 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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
#include "../UI/jucer_JucerDocumentEditor.h"
//==============================================================================
template <class ComponentType>
class ComponentUndoableAction : public UndoableAction
{
public:
ComponentUndoableAction (ComponentType* const comp,
ComponentLayout& layout_)
: layout (layout_),
componentIndex (layout_.indexOfComponent (comp))
{
jassert (comp != nullptr);
jassert (componentIndex >= 0);
}
ComponentType* getComponent() const
{
ComponentType* const c = dynamic_cast<ComponentType*> (layout.getComponent (componentIndex));
jassert (c != nullptr);
return c;
}
int getSizeInUnits() { return 2; }
protected:
ComponentLayout& layout;
const int componentIndex;
void changed() const
{
jassert (layout.getDocument() != nullptr);
layout.getDocument()->changed();
}
void showCorrectTab() const
{
if (JucerDocumentEditor* const ed = JucerDocumentEditor::getActiveDocumentHolder())
ed->showLayout();
if (layout.getSelectedSet().getNumSelected() == 0)
if (ComponentType* const c = dynamic_cast<ComponentType*> (layout.getComponent (componentIndex)))
layout.getSelectedSet().selectOnly (getComponent());
}
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentUndoableAction)
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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
#include "../UI/jucer_JucerDocumentEditor.h"
//==============================================================================
template <class ComponentType>
class ComponentUndoableAction : public UndoableAction
{
public:
ComponentUndoableAction (ComponentType* const comp,
ComponentLayout& layout_)
: layout (layout_),
componentIndex (layout_.indexOfComponent (comp))
{
jassert (comp != nullptr);
jassert (componentIndex >= 0);
}
ComponentType* getComponent() const
{
ComponentType* const c = dynamic_cast<ComponentType*> (layout.getComponent (componentIndex));
jassert (c != nullptr);
return c;
}
int getSizeInUnits() { return 2; }
protected:
ComponentLayout& layout;
const int componentIndex;
void changed() const
{
jassert (layout.getDocument() != nullptr);
layout.getDocument()->changed();
}
void showCorrectTab() const
{
if (JucerDocumentEditor* const ed = JucerDocumentEditor::getActiveDocumentHolder())
ed->showLayout();
if (layout.getSelectedSet().getNumSelected() == 0)
if (ComponentType* const c = dynamic_cast<ComponentType*> (layout.getComponent (componentIndex)))
layout.getSelectedSet().selectOnly (getComponent());
}
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentUndoableAction)
};

View File

@ -1,241 +1,241 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 GenericComponent : public Component
{
public:
GenericComponent()
: Component ("new component"),
actualClassName ("juce::Component")
{
}
void paint (Graphics& g) override
{
g.fillAll (Colours::white.withAlpha (0.25f));
g.setColour (Colours::black.withAlpha (0.5f));
g.drawRect (getLocalBounds());
g.drawLine (0.0f, 0.0f, (float) getWidth(), (float) getHeight());
g.drawLine (0.0f, (float) getHeight(), (float) getWidth(), 0.0f);
g.setFont (14.0f);
g.drawText (actualClassName, 0, 0, getWidth(), getHeight() / 2, Justification::centred, true);
}
void setClassName (const String& newName)
{
if (actualClassName != newName)
{
actualClassName = newName;
repaint();
}
}
void setParams (const String& newParams)
{
if (constructorParams != newParams)
{
constructorParams = newParams;
repaint();
}
}
String actualClassName, constructorParams;
};
//==============================================================================
class GenericComponentHandler : public ComponentTypeHandler
{
public:
GenericComponentHandler()
: ComponentTypeHandler ("Generic Component", "GenericComponent", typeid (GenericComponent), 150, 24)
{}
Component* createNewComponent (JucerDocument*) override
{
return new GenericComponent();
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
e->setAttribute ("class", ((GenericComponent*) comp)->actualClassName);
e->setAttribute ("params", ((GenericComponent*) comp)->constructorParams);
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
((GenericComponent*) comp)->actualClassName = xml.getStringAttribute ("class", "juce::Component");
((GenericComponent*) comp)->constructorParams = xml.getStringAttribute ("params", String());
return true;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
props.add (new GenericCompClassProperty (dynamic_cast<GenericComponent*> (component), document));
props.add (new GenericCompParamsProperty (dynamic_cast<GenericComponent*> (component), document));
}
String getClassName (Component* comp) const override
{
return static_cast<GenericComponent*> (comp)->actualClassName;
}
String getCreationParameters (GeneratedCode&, Component* comp) override
{
return static_cast<GenericComponent*> (comp)->constructorParams;
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
if (component->getName().isNotEmpty())
code.constructorCode
<< memberVariableName << "->setName ("
<< quotedString (component->getName(), false)
<< ");\n\n";
else
code.constructorCode << "\n";
}
private:
class GenericCompClassProperty : public ComponentTextProperty <GenericComponent>
{
public:
GenericCompClassProperty (GenericComponent* comp, JucerDocument& doc)
: ComponentTextProperty <GenericComponent> ("class", 300, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new GenericCompClassChangeAction (component, *document.getComponentLayout(),
build_tools::makeValidIdentifier (newText, false, false, true)),
"Change generic component class");
}
String getText() const override
{
return component->actualClassName;
}
private:
class GenericCompClassChangeAction : public ComponentUndoableAction <GenericComponent>
{
public:
GenericCompClassChangeAction (GenericComponent* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <GenericComponent> (comp, l),
newState (newState_)
{
oldState = comp->actualClassName;
}
bool perform()
{
showCorrectTab();
getComponent()->setClassName (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setClassName (oldState);
changed();
return true;
}
String newState, oldState;
};
};
class GenericCompParamsProperty : public ComponentTextProperty <GenericComponent>
{
public:
GenericCompParamsProperty (GenericComponent* comp, JucerDocument& doc)
: ComponentTextProperty <GenericComponent> ("constructor params", 1024, true, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new GenericCompParamsChangeAction (component, *document.getComponentLayout(), newText),
"Change generic component class");
}
String getText() const override
{
return component->constructorParams;
}
private:
class GenericCompParamsChangeAction : public ComponentUndoableAction <GenericComponent>
{
public:
GenericCompParamsChangeAction (GenericComponent* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <GenericComponent> (comp, l),
newState (newState_)
{
oldState = comp->constructorParams;
}
bool perform()
{
showCorrectTab();
getComponent()->setParams (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setParams (oldState);
changed();
return true;
}
String newState, oldState;
};
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 GenericComponent : public Component
{
public:
GenericComponent()
: Component ("new component"),
actualClassName ("juce::Component")
{
}
void paint (Graphics& g) override
{
g.fillAll (Colours::white.withAlpha (0.25f));
g.setColour (Colours::black.withAlpha (0.5f));
g.drawRect (getLocalBounds());
g.drawLine (0.0f, 0.0f, (float) getWidth(), (float) getHeight());
g.drawLine (0.0f, (float) getHeight(), (float) getWidth(), 0.0f);
g.setFont (14.0f);
g.drawText (actualClassName, 0, 0, getWidth(), getHeight() / 2, Justification::centred, true);
}
void setClassName (const String& newName)
{
if (actualClassName != newName)
{
actualClassName = newName;
repaint();
}
}
void setParams (const String& newParams)
{
if (constructorParams != newParams)
{
constructorParams = newParams;
repaint();
}
}
String actualClassName, constructorParams;
};
//==============================================================================
class GenericComponentHandler : public ComponentTypeHandler
{
public:
GenericComponentHandler()
: ComponentTypeHandler ("Generic Component", "GenericComponent", typeid (GenericComponent), 150, 24)
{}
Component* createNewComponent (JucerDocument*) override
{
return new GenericComponent();
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
e->setAttribute ("class", ((GenericComponent*) comp)->actualClassName);
e->setAttribute ("params", ((GenericComponent*) comp)->constructorParams);
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
((GenericComponent*) comp)->actualClassName = xml.getStringAttribute ("class", "juce::Component");
((GenericComponent*) comp)->constructorParams = xml.getStringAttribute ("params", String());
return true;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
props.add (new GenericCompClassProperty (dynamic_cast<GenericComponent*> (component), document));
props.add (new GenericCompParamsProperty (dynamic_cast<GenericComponent*> (component), document));
}
String getClassName (Component* comp) const override
{
return static_cast<GenericComponent*> (comp)->actualClassName;
}
String getCreationParameters (GeneratedCode&, Component* comp) override
{
return static_cast<GenericComponent*> (comp)->constructorParams;
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
if (component->getName().isNotEmpty())
code.constructorCode
<< memberVariableName << "->setName ("
<< quotedString (component->getName(), false)
<< ");\n\n";
else
code.constructorCode << "\n";
}
private:
class GenericCompClassProperty : public ComponentTextProperty <GenericComponent>
{
public:
GenericCompClassProperty (GenericComponent* comp, JucerDocument& doc)
: ComponentTextProperty <GenericComponent> ("class", 300, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new GenericCompClassChangeAction (component, *document.getComponentLayout(),
build_tools::makeValidIdentifier (newText, false, false, true)),
"Change generic component class");
}
String getText() const override
{
return component->actualClassName;
}
private:
class GenericCompClassChangeAction : public ComponentUndoableAction <GenericComponent>
{
public:
GenericCompClassChangeAction (GenericComponent* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <GenericComponent> (comp, l),
newState (newState_)
{
oldState = comp->actualClassName;
}
bool perform()
{
showCorrectTab();
getComponent()->setClassName (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setClassName (oldState);
changed();
return true;
}
String newState, oldState;
};
};
class GenericCompParamsProperty : public ComponentTextProperty <GenericComponent>
{
public:
GenericCompParamsProperty (GenericComponent* comp, JucerDocument& doc)
: ComponentTextProperty <GenericComponent> ("constructor params", 1024, true, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new GenericCompParamsChangeAction (component, *document.getComponentLayout(), newText),
"Change generic component class");
}
String getText() const override
{
return component->constructorParams;
}
private:
class GenericCompParamsChangeAction : public ComponentUndoableAction <GenericComponent>
{
public:
GenericCompParamsChangeAction (GenericComponent* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <GenericComponent> (comp, l),
newState (newState_)
{
oldState = comp->constructorParams;
}
bool perform()
{
showCorrectTab();
getComponent()->setParams (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setParams (oldState);
changed();
return true;
}
String newState, oldState;
};
};
};

View File

@ -1,237 +1,237 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 GroupComponentHandler : public ComponentTypeHandler
{
public:
GroupComponentHandler()
: ComponentTypeHandler ("Group Box", "juce::GroupComponent", typeid (GroupComponent), 200, 150)
{
registerColour (juce::GroupComponent::outlineColourId, "outline", "outlinecol");
registerColour (juce::GroupComponent::textColourId, "text", "textcol");
}
Component* createNewComponent (JucerDocument*) override
{
return new GroupComponent ("new group", "group");
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
GroupComponent* const g = (GroupComponent*) comp;
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
e->setAttribute ("title", g->getText());
GroupComponent defaultComp;
if (g->getTextLabelPosition().getFlags() != defaultComp.getTextLabelPosition().getFlags())
e->setAttribute ("textpos", g->getTextLabelPosition().getFlags());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
GroupComponent* const g = (GroupComponent*) comp;
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
g->setText (xml.getStringAttribute ("title", g->getText()));
g->setTextLabelPosition (Justification (xml.getIntAttribute ("textpos", g->getTextLabelPosition().getFlags())));
return true;
}
String getCreationParameters (GeneratedCode& code, Component* component) override
{
GroupComponent* g = dynamic_cast<GroupComponent*> (component);
return quotedString (component->getName(), false)
+ ",\n"
+ quotedString (g->getText(), code.shouldUseTransMacro());
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
GroupComponent* const g = dynamic_cast<GroupComponent*> (component);
String s;
GroupComponent defaultComp;
if (g->getTextLabelPosition().getFlags() != defaultComp.getTextLabelPosition().getFlags())
{
s << memberVariableName << "->setTextLabelPosition ("
<< CodeHelpers::justificationToCode (g->getTextLabelPosition())
<< ");\n";
}
s << getColourIntialisationCode (component, memberVariableName)
<< '\n';
code.constructorCode += s;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* gc = dynamic_cast<GroupComponent*> (component))
{
props.add (new GroupTitleProperty (gc, document));
props.add (new GroupJustificationProperty (gc, document));
}
addColourProperties (component, document, props);
}
private:
//==============================================================================
class GroupTitleProperty : public ComponentTextProperty <GroupComponent>
{
public:
GroupTitleProperty (GroupComponent* comp, JucerDocument& doc)
: ComponentTextProperty <GroupComponent> ("text", 200, false, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new GroupTitleChangeAction (component, *document.getComponentLayout(), newText),
"Change group title");
}
String getText() const override
{
return component->getText();
}
private:
class GroupTitleChangeAction : public ComponentUndoableAction <GroupComponent>
{
public:
GroupTitleChangeAction (GroupComponent* const comp, ComponentLayout& l, const String& newName_)
: ComponentUndoableAction <GroupComponent> (comp, l),
newName (newName_)
{
oldName = comp->getText();
}
bool perform()
{
showCorrectTab();
getComponent()->setText (newName);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setText (oldName);
changed();
return true;
}
String newName, oldName;
};
};
//==============================================================================
class GroupJustificationProperty : public JustificationProperty,
private ChangeListener
{
public:
GroupJustificationProperty (GroupComponent* const group_, JucerDocument& doc)
: JustificationProperty ("layout", true),
group (group_),
document (doc)
{
document.addChangeListener (this);
}
~GroupJustificationProperty() override
{
document.removeChangeListener (this);
}
void setJustification (Justification newJustification) override
{
document.perform (new GroupJustifyChangeAction (group, *document.getComponentLayout(), newJustification),
"Change text label position");
}
Justification getJustification() const override
{
return group->getTextLabelPosition();
}
private:
void changeListenerCallback (ChangeBroadcaster*) override { refresh(); }
GroupComponent* const group;
JucerDocument& document;
class GroupJustifyChangeAction : public ComponentUndoableAction <GroupComponent>
{
public:
GroupJustifyChangeAction (GroupComponent* const comp, ComponentLayout& l, Justification newState_)
: ComponentUndoableAction <GroupComponent> (comp, l),
newState (newState_),
oldState (comp->getTextLabelPosition())
{
}
bool perform()
{
showCorrectTab();
getComponent()->setTextLabelPosition (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setTextLabelPosition (oldState);
changed();
return true;
}
Justification newState, oldState;
};
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 GroupComponentHandler : public ComponentTypeHandler
{
public:
GroupComponentHandler()
: ComponentTypeHandler ("Group Box", "juce::GroupComponent", typeid (GroupComponent), 200, 150)
{
registerColour (juce::GroupComponent::outlineColourId, "outline", "outlinecol");
registerColour (juce::GroupComponent::textColourId, "text", "textcol");
}
Component* createNewComponent (JucerDocument*) override
{
return new GroupComponent ("new group", "group");
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
GroupComponent* const g = (GroupComponent*) comp;
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
e->setAttribute ("title", g->getText());
GroupComponent defaultComp;
if (g->getTextLabelPosition().getFlags() != defaultComp.getTextLabelPosition().getFlags())
e->setAttribute ("textpos", g->getTextLabelPosition().getFlags());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
GroupComponent* const g = (GroupComponent*) comp;
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
g->setText (xml.getStringAttribute ("title", g->getText()));
g->setTextLabelPosition (Justification (xml.getIntAttribute ("textpos", g->getTextLabelPosition().getFlags())));
return true;
}
String getCreationParameters (GeneratedCode& code, Component* component) override
{
GroupComponent* g = dynamic_cast<GroupComponent*> (component);
return quotedString (component->getName(), false)
+ ",\n"
+ quotedString (g->getText(), code.shouldUseTransMacro());
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
GroupComponent* const g = dynamic_cast<GroupComponent*> (component);
String s;
GroupComponent defaultComp;
if (g->getTextLabelPosition().getFlags() != defaultComp.getTextLabelPosition().getFlags())
{
s << memberVariableName << "->setTextLabelPosition ("
<< CodeHelpers::justificationToCode (g->getTextLabelPosition())
<< ");\n";
}
s << getColourIntialisationCode (component, memberVariableName)
<< '\n';
code.constructorCode += s;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* gc = dynamic_cast<GroupComponent*> (component))
{
props.add (new GroupTitleProperty (gc, document));
props.add (new GroupJustificationProperty (gc, document));
}
addColourProperties (component, document, props);
}
private:
//==============================================================================
class GroupTitleProperty : public ComponentTextProperty <GroupComponent>
{
public:
GroupTitleProperty (GroupComponent* comp, JucerDocument& doc)
: ComponentTextProperty <GroupComponent> ("text", 200, false, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new GroupTitleChangeAction (component, *document.getComponentLayout(), newText),
"Change group title");
}
String getText() const override
{
return component->getText();
}
private:
class GroupTitleChangeAction : public ComponentUndoableAction <GroupComponent>
{
public:
GroupTitleChangeAction (GroupComponent* const comp, ComponentLayout& l, const String& newName_)
: ComponentUndoableAction <GroupComponent> (comp, l),
newName (newName_)
{
oldName = comp->getText();
}
bool perform()
{
showCorrectTab();
getComponent()->setText (newName);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setText (oldName);
changed();
return true;
}
String newName, oldName;
};
};
//==============================================================================
class GroupJustificationProperty : public JustificationProperty,
private ChangeListener
{
public:
GroupJustificationProperty (GroupComponent* const group_, JucerDocument& doc)
: JustificationProperty ("layout", true),
group (group_),
document (doc)
{
document.addChangeListener (this);
}
~GroupJustificationProperty() override
{
document.removeChangeListener (this);
}
void setJustification (Justification newJustification) override
{
document.perform (new GroupJustifyChangeAction (group, *document.getComponentLayout(), newJustification),
"Change text label position");
}
Justification getJustification() const override
{
return group->getTextLabelPosition();
}
private:
void changeListenerCallback (ChangeBroadcaster*) override { refresh(); }
GroupComponent* const group;
JucerDocument& document;
class GroupJustifyChangeAction : public ComponentUndoableAction <GroupComponent>
{
public:
GroupJustifyChangeAction (GroupComponent* const comp, ComponentLayout& l, Justification newState_)
: ComponentUndoableAction <GroupComponent> (comp, l),
newState (newState_),
oldState (comp->getTextLabelPosition())
{
}
bool perform()
{
showCorrectTab();
getComponent()->setTextLabelPosition (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setTextLabelPosition (oldState);
changed();
return true;
}
Justification newState, oldState;
};
};
};

View File

@ -1,149 +1,149 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 HyperlinkButtonHandler : public ButtonHandler
{
public:
HyperlinkButtonHandler()
: ButtonHandler ("Hyperlink Button", "juce::HyperlinkButton", typeid (HyperlinkButton), 150, 24)
{
registerColour (juce::HyperlinkButton::textColourId, "text", "textCol");
}
Component* createNewComponent (JucerDocument*) override
{
HyperlinkButton* hb = new HyperlinkButton ("new hyperlink", URL ("http://www.juce.com"));
setNeedsButtonListener (hb, false);
return hb;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ButtonHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* hb = dynamic_cast<HyperlinkButton*> (component))
props.add (new HyperlinkURLProperty (hb, document));
addColourProperties (component, document, props);
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
HyperlinkButton* const hb = (HyperlinkButton*) comp;
XmlElement* const e = ButtonHandler::createXmlFor (comp, layout);
e->setAttribute ("url", hb->getURL().toString (false));
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
HyperlinkButton* const hb = (HyperlinkButton*) comp;
if (! ButtonHandler::restoreFromXml (xml, comp, layout))
return false;
hb->setURL (URL (xml.getStringAttribute ("url", hb->getURL().toString (false))));
return true;
}
String getCreationParameters (GeneratedCode& code, Component* comp) override
{
HyperlinkButton* const hb = dynamic_cast<HyperlinkButton*> (comp);
return quotedString (hb->getButtonText(), code.shouldUseTransMacro())
+ ",\nURL ("
+ quotedString (hb->getURL().toString (false), false)
+ ")";
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ButtonHandler::fillInCreationCode (code, component, memberVariableName);
code.constructorCode << getColourIntialisationCode (component, memberVariableName)
<< '\n';
}
private:
//==============================================================================
class HyperlinkURLProperty : public ComponentTextProperty <HyperlinkButton>
{
public:
HyperlinkURLProperty (HyperlinkButton* comp, JucerDocument& doc)
: ComponentTextProperty <HyperlinkButton> ("URL", 512, false, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new HyperlinkURLChangeAction (component, *document.getComponentLayout(), URL::createWithoutParsing (newText)),
"Change hyperlink URL");
}
String getText() const override
{
return component->getURL().toString (false);
}
private:
class HyperlinkURLChangeAction : public ComponentUndoableAction <HyperlinkButton>
{
public:
HyperlinkURLChangeAction (HyperlinkButton* const comp, ComponentLayout& l, const URL& newState_)
: ComponentUndoableAction <HyperlinkButton> (comp, l),
newState (newState_)
{
oldState = comp->getURL();
}
bool perform()
{
showCorrectTab();
getComponent()->setURL (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setURL (oldState);
changed();
return true;
}
URL newState, oldState;
};
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 HyperlinkButtonHandler : public ButtonHandler
{
public:
HyperlinkButtonHandler()
: ButtonHandler ("Hyperlink Button", "juce::HyperlinkButton", typeid (HyperlinkButton), 150, 24)
{
registerColour (juce::HyperlinkButton::textColourId, "text", "textCol");
}
Component* createNewComponent (JucerDocument*) override
{
HyperlinkButton* hb = new HyperlinkButton ("new hyperlink", URL ("http://www.juce.com"));
setNeedsButtonListener (hb, false);
return hb;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ButtonHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* hb = dynamic_cast<HyperlinkButton*> (component))
props.add (new HyperlinkURLProperty (hb, document));
addColourProperties (component, document, props);
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
HyperlinkButton* const hb = (HyperlinkButton*) comp;
XmlElement* const e = ButtonHandler::createXmlFor (comp, layout);
e->setAttribute ("url", hb->getURL().toString (false));
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
HyperlinkButton* const hb = (HyperlinkButton*) comp;
if (! ButtonHandler::restoreFromXml (xml, comp, layout))
return false;
hb->setURL (URL (xml.getStringAttribute ("url", hb->getURL().toString (false))));
return true;
}
String getCreationParameters (GeneratedCode& code, Component* comp) override
{
HyperlinkButton* const hb = dynamic_cast<HyperlinkButton*> (comp);
return quotedString (hb->getButtonText(), code.shouldUseTransMacro())
+ ",\njuce::URL ("
+ quotedString (hb->getURL().toString (false), false)
+ ")";
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ButtonHandler::fillInCreationCode (code, component, memberVariableName);
code.constructorCode << getColourIntialisationCode (component, memberVariableName)
<< '\n';
}
private:
//==============================================================================
class HyperlinkURLProperty : public ComponentTextProperty <HyperlinkButton>
{
public:
HyperlinkURLProperty (HyperlinkButton* comp, JucerDocument& doc)
: ComponentTextProperty <HyperlinkButton> ("URL", 512, false, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new HyperlinkURLChangeAction (component, *document.getComponentLayout(), URL::createWithoutParsing (newText)),
"Change hyperlink URL");
}
String getText() const override
{
return component->getURL().toString (false);
}
private:
class HyperlinkURLChangeAction : public ComponentUndoableAction <HyperlinkButton>
{
public:
HyperlinkURLChangeAction (HyperlinkButton* const comp, ComponentLayout& l, const URL& newState_)
: ComponentUndoableAction <HyperlinkButton> (comp, l),
newState (newState_)
{
oldState = comp->getURL();
}
bool perform()
{
showCorrectTab();
getComponent()->setURL (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setURL (oldState);
changed();
return true;
}
URL newState, oldState;
};
};
};

View File

@ -1,273 +1,273 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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
#include "../UI/jucer_TestComponent.h"
#include "../Properties/jucer_FilePropertyComponent.h"
#include "../Properties/jucer_ComponentTextProperty.h"
#include "jucer_ComponentUndoableAction.h"
#include "../../Project/UI/jucer_ProjectContentComponent.h"
//==============================================================================
class JucerComponentHandler : public ComponentTypeHandler
{
public:
JucerComponentHandler()
: ComponentTypeHandler ("Projucer Component", "xxx",
typeid (TestComponent), 300, 200)
{}
Component* createNewComponent (JucerDocument* doc) override
{
return new TestComponent (doc, nullptr, false);
}
String getXmlTagName() const noexcept override { return "JUCERCOMP"; }
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
TestComponent* const tc = dynamic_cast<TestComponent*> (comp);
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
e->setAttribute ("sourceFile", tc->getFilename());
e->setAttribute ("constructorParams", tc->getConstructorParams());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
auto tc = dynamic_cast<TestComponent*> (comp);
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
tc->setFilename (xml.getStringAttribute ("sourceFile", tc->getFilename()));
tc->setConstructorParams (xml.getStringAttribute ("constructorParams"));
return true;
}
String getClassName (Component* comp) const override
{
auto tc = dynamic_cast<TestComponent*> (comp);
String jucerCompClassName;
if (tc->getDocument() != nullptr)
jucerCompClassName = tc->getDocument()->getClassName();
if (jucerCompClassName.isEmpty())
jucerCompClassName = "juce::Component";
return jucerCompClassName;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto tc = dynamic_cast<TestComponent*> (component))
{
props.add (new JucerCompFileProperty (tc, document));
props.add (new ConstructorParamsProperty (tc, document));
props.add (new JucerCompOpenDocProperty (tc));
}
}
String getCreationParameters (GeneratedCode&, Component* component) override
{
return dynamic_cast<TestComponent*> (component)->getConstructorParams().trim();
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
if (auto tc = dynamic_cast<TestComponent*> (component))
code.includeFilesH.add (tc->findFile().withFileExtension (".h"));
else
jassertfalse;
}
//==============================================================================
class JucerCompFileChangeAction : public ComponentUndoableAction <TestComponent>
{
public:
JucerCompFileChangeAction (TestComponent* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <TestComponent> (comp, l),
newState (newState_)
{
oldState = comp->getFilename();
}
bool perform()
{
showCorrectTab();
getComponent()->setFilename (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setFilename (oldState);
changed();
return true;
}
String newState, oldState;
};
static void setJucerComponentFile (JucerDocument& document, TestComponent* comp, const String& newFilename)
{
jassert (comp != nullptr);
if (comp != nullptr)
document.perform (new JucerCompFileChangeAction (comp, *document.getComponentLayout(), newFilename),
"Change Projucer component file");
}
private:
//==============================================================================
class JucerCompFileProperty : public FilePropertyComponent,
private ChangeListener
{
public:
JucerCompFileProperty (TestComponent* const comp, JucerDocument& doc)
: FilePropertyComponent ("Jucer file", false, true),
component (comp),
document (doc)
{
document.addChangeListener (this);
}
~JucerCompFileProperty() override
{
document.removeChangeListener (this);
}
void setFile (const File& newFile) override
{
setJucerComponentFile (document, component,
newFile.getRelativePathFrom (document.getCppFile().getParentDirectory())
.replaceCharacter ('\\', '/'));
}
File getFile() const override
{
return component->findFile();
}
private:
void changeListenerCallback (ChangeBroadcaster*) override
{
refresh();
}
TestComponent* const component;
JucerDocument& document;
};
//==============================================================================
struct JucerCompOpenDocProperty : public ButtonPropertyComponent
{
JucerCompOpenDocProperty (TestComponent* const c)
: ButtonPropertyComponent ("edit", false),
component (c)
{
}
void buttonClicked()
{
if (ProjectContentComponent* const pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->showEditorForFile (component->findFile(), true);
}
String getButtonText() const
{
return "Open file for editing";
}
TestComponent* const component;
};
//==============================================================================
struct ConstructorParamsProperty : public ComponentTextProperty <TestComponent>
{
ConstructorParamsProperty (TestComponent* comp, JucerDocument& doc)
: ComponentTextProperty <TestComponent> ("constructor params", 512, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new ConstructorParamChangeAction (component, *document.getComponentLayout(), newText),
"Change Viewport content constructor params");
}
String getText() const override
{
return component->getConstructorParams();
}
private:
struct ConstructorParamChangeAction : public ComponentUndoableAction <TestComponent>
{
ConstructorParamChangeAction (TestComponent* const comp, ComponentLayout& l, const String& newValue_)
: ComponentUndoableAction <TestComponent> (comp, l),
newValue (newValue_)
{
oldValue = comp->getConstructorParams();
}
bool perform()
{
showCorrectTab();
getComponent()->setConstructorParams (newValue);
changed();
layout.getDocument()->refreshAllPropertyComps();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setConstructorParams (oldValue);
changed();
layout.getDocument()->refreshAllPropertyComps();
return true;
}
String newValue, oldValue;
};
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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
#include "../UI/jucer_TestComponent.h"
#include "../Properties/jucer_FilePropertyComponent.h"
#include "../Properties/jucer_ComponentTextProperty.h"
#include "jucer_ComponentUndoableAction.h"
#include "../../Project/UI/jucer_ProjectContentComponent.h"
//==============================================================================
class JucerComponentHandler : public ComponentTypeHandler
{
public:
JucerComponentHandler()
: ComponentTypeHandler ("Projucer Component", "xxx",
typeid (TestComponent), 300, 200)
{}
Component* createNewComponent (JucerDocument* doc) override
{
return new TestComponent (doc, nullptr, false);
}
String getXmlTagName() const noexcept override { return "JUCERCOMP"; }
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
TestComponent* const tc = dynamic_cast<TestComponent*> (comp);
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
e->setAttribute ("sourceFile", tc->getFilename());
e->setAttribute ("constructorParams", tc->getConstructorParams());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
auto tc = dynamic_cast<TestComponent*> (comp);
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
tc->setFilename (xml.getStringAttribute ("sourceFile", tc->getFilename()));
tc->setConstructorParams (xml.getStringAttribute ("constructorParams"));
return true;
}
String getClassName (Component* comp) const override
{
auto tc = dynamic_cast<TestComponent*> (comp);
String jucerCompClassName;
if (tc->getDocument() != nullptr)
jucerCompClassName = tc->getDocument()->getClassName();
if (jucerCompClassName.isEmpty())
jucerCompClassName = "juce::Component";
return jucerCompClassName;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto tc = dynamic_cast<TestComponent*> (component))
{
props.add (new JucerCompFileProperty (tc, document));
props.add (new ConstructorParamsProperty (tc, document));
props.add (new JucerCompOpenDocProperty (tc));
}
}
String getCreationParameters (GeneratedCode&, Component* component) override
{
return dynamic_cast<TestComponent*> (component)->getConstructorParams().trim();
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
if (auto tc = dynamic_cast<TestComponent*> (component))
code.includeFilesH.add (tc->findFile().withFileExtension (".h"));
else
jassertfalse;
}
//==============================================================================
class JucerCompFileChangeAction : public ComponentUndoableAction <TestComponent>
{
public:
JucerCompFileChangeAction (TestComponent* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <TestComponent> (comp, l),
newState (newState_)
{
oldState = comp->getFilename();
}
bool perform()
{
showCorrectTab();
getComponent()->setFilename (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setFilename (oldState);
changed();
return true;
}
String newState, oldState;
};
static void setJucerComponentFile (JucerDocument& document, TestComponent* comp, const String& newFilename)
{
jassert (comp != nullptr);
if (comp != nullptr)
document.perform (new JucerCompFileChangeAction (comp, *document.getComponentLayout(), newFilename),
"Change Projucer component file");
}
private:
//==============================================================================
class JucerCompFileProperty : public FilePropertyComponent,
private ChangeListener
{
public:
JucerCompFileProperty (TestComponent* const comp, JucerDocument& doc)
: FilePropertyComponent ("Jucer file", false, true),
component (comp),
document (doc)
{
document.addChangeListener (this);
}
~JucerCompFileProperty() override
{
document.removeChangeListener (this);
}
void setFile (const File& newFile) override
{
setJucerComponentFile (document, component,
newFile.getRelativePathFrom (document.getCppFile().getParentDirectory())
.replaceCharacter ('\\', '/'));
}
File getFile() const override
{
return component->findFile();
}
private:
void changeListenerCallback (ChangeBroadcaster*) override
{
refresh();
}
TestComponent* const component;
JucerDocument& document;
};
//==============================================================================
struct JucerCompOpenDocProperty : public ButtonPropertyComponent
{
JucerCompOpenDocProperty (TestComponent* const c)
: ButtonPropertyComponent ("edit", false),
component (c)
{
}
void buttonClicked()
{
if (ProjectContentComponent* const pcc = findParentComponentOfClass<ProjectContentComponent>())
pcc->showEditorForFile (component->findFile(), true);
}
String getButtonText() const
{
return "Open file for editing";
}
TestComponent* const component;
};
//==============================================================================
struct ConstructorParamsProperty : public ComponentTextProperty <TestComponent>
{
ConstructorParamsProperty (TestComponent* comp, JucerDocument& doc)
: ComponentTextProperty <TestComponent> ("constructor params", 512, false, comp, doc)
{
}
void setText (const String& newText) override
{
document.perform (new ConstructorParamChangeAction (component, *document.getComponentLayout(), newText),
"Change Viewport content constructor params");
}
String getText() const override
{
return component->getConstructorParams();
}
private:
struct ConstructorParamChangeAction : public ComponentUndoableAction <TestComponent>
{
ConstructorParamChangeAction (TestComponent* const comp, ComponentLayout& l, const String& newValue_)
: ComponentUndoableAction <TestComponent> (comp, l),
newValue (newValue_)
{
oldValue = comp->getConstructorParams();
}
bool perform()
{
showCorrectTab();
getComponent()->setConstructorParams (newValue);
changed();
layout.getDocument()->refreshAllPropertyComps();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setConstructorParams (oldValue);
changed();
layout.getDocument()->refreshAllPropertyComps();
return true;
}
String newValue, oldValue;
};
};
};

View File

@ -1,79 +1,79 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 TextButtonHandler : public ButtonHandler
{
public:
TextButtonHandler()
: ButtonHandler ("Text Button", "juce::TextButton", typeid (TextButton), 150, 24)
{
registerColour (juce::TextButton::buttonColourId, "background (normal)", "bgColOff");
registerColour (juce::TextButton::buttonOnColourId, "background (on)", "bgColOn");
registerColour (juce::TextButton::textColourOffId, "text colour (normal)", "textCol");
registerColour (juce::TextButton::textColourOnId, "text colour (on)", "textColOn");
}
Component* createNewComponent (JucerDocument*) override
{
return new TextButton ("new button", String());
}
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);
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
return ButtonHandler::createXmlFor (comp, layout);
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
return ButtonHandler::restoreFromXml (xml, comp, layout);
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ButtonHandler::fillInCreationCode (code, component, memberVariableName);
String s;
s << getColourIntialisationCode (component, memberVariableName)
<< '\n';
code.constructorCode += s;
}
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 TextButtonHandler : public ButtonHandler
{
public:
TextButtonHandler()
: ButtonHandler ("Text Button", "juce::TextButton", typeid (TextButton), 150, 24)
{
registerColour (juce::TextButton::buttonColourId, "background (normal)", "bgColOff");
registerColour (juce::TextButton::buttonOnColourId, "background (on)", "bgColOn");
registerColour (juce::TextButton::textColourOffId, "text colour (normal)", "textCol");
registerColour (juce::TextButton::textColourOnId, "text colour (on)", "textColOn");
}
Component* createNewComponent (JucerDocument*) override
{
return new TextButton ("new button", String());
}
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);
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
return ButtonHandler::createXmlFor (comp, layout);
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
return ButtonHandler::restoreFromXml (xml, comp, layout);
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ButtonHandler::fillInCreationCode (code, component, memberVariableName);
String s;
s << getColourIntialisationCode (component, memberVariableName)
<< '\n';
code.constructorCode += s;
}
};

View File

@ -1,433 +1,433 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 TextEditorHandler : public ComponentTypeHandler
{
public:
TextEditorHandler()
: ComponentTypeHandler ("Text Editor", "juce::TextEditor", typeid (TextEditor), 150, 24)
{
registerColour (juce::TextEditor::textColourId, "text", "textcol");
registerColour (juce::TextEditor::backgroundColourId, "background", "bkgcol");
registerColour (juce::TextEditor::highlightColourId, "highlight", "hilitecol");
registerColour (juce::TextEditor::outlineColourId, "outline", "outlinecol");
registerColour (juce::TextEditor::shadowColourId, "shadow", "shadowcol");
registerColour (juce::CaretComponent::caretColourId, "caret", "caretcol");
}
Component* createNewComponent (JucerDocument*) override
{
return new TextEditor ("new text editor");
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
TextEditor* te = (TextEditor*) comp;
e->setAttribute ("initialText", comp->getProperties() ["initialText"].toString());
e->setAttribute ("multiline", te->isMultiLine());
e->setAttribute ("retKeyStartsLine", te->getReturnKeyStartsNewLine());
e->setAttribute ("readonly", te->isReadOnly());
e->setAttribute ("scrollbars", te->areScrollbarsShown());
e->setAttribute ("caret", te->isCaretVisible());
e->setAttribute ("popupmenu", te->isPopupMenuEnabled());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
TextEditor* te = (TextEditor*) comp;
TextEditor defaultEditor;
te->setMultiLine (xml.getBoolAttribute ("multiline", defaultEditor.isMultiLine()));
te->setReturnKeyStartsNewLine (xml.getBoolAttribute ("retKeyStartsLine", defaultEditor.getReturnKeyStartsNewLine()));
te->setReadOnly (xml.getBoolAttribute ("readonly", defaultEditor.isReadOnly()));
te->setScrollbarsShown (xml.getBoolAttribute ("scrollbars", defaultEditor.areScrollbarsShown()));
te->setCaretVisible (xml.getBoolAttribute ("caret", defaultEditor.isCaretVisible()));
te->setPopupMenuEnabled (xml.getBoolAttribute ("popupmenu", defaultEditor.isPopupMenuEnabled()));
const String initialText (xml.getStringAttribute ("initialText"));
te->setText (initialText, false);
te->getProperties().set ("initialText", initialText);
return true;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* t = dynamic_cast<TextEditor*> (component))
{
props.add (new TextEditorInitialTextProperty (t, document));
props.add (new TextEditorMultiLineProperty (t, document));
props.add (new TextEditorReadOnlyProperty (t, document));
props.add (new TextEditorScrollbarsProperty (t, document));
props.add (new TextEditorCaretProperty (t, document));
props.add (new TextEditorPopupMenuProperty (t, document));
addColourProperties (t, document, props);
}
}
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);
if (auto* te = dynamic_cast<TextEditor*> (component))
{
String s;
s << memberVariableName << "->setMultiLine (" << CodeHelpers::boolLiteral (te->isMultiLine()) << ");\n"
<< memberVariableName << "->setReturnKeyStartsNewLine (" << CodeHelpers::boolLiteral (te->getReturnKeyStartsNewLine()) << ");\n"
<< memberVariableName << "->setReadOnly (" << CodeHelpers::boolLiteral (te->isReadOnly()) << ");\n"
<< memberVariableName << "->setScrollbarsShown (" << CodeHelpers::boolLiteral (te->areScrollbarsShown()) << ");\n"
<< memberVariableName << "->setCaretVisible (" << CodeHelpers::boolLiteral (te->isCaretVisible()) << ");\n"
<< memberVariableName << "->setPopupMenuEnabled (" << CodeHelpers::boolLiteral (te->isPopupMenuEnabled()) << ");\n"
<< getColourIntialisationCode (component, memberVariableName)
<< memberVariableName << "->setText (" << quotedString (te->getProperties() ["initialText"].toString(), code.shouldUseTransMacro()) << ");\n\n";
code.constructorCode += s;
}
}
private:
//==============================================================================
class TextEditorMultiLineProperty : public ComponentChoiceProperty <TextEditor>
{
public:
TextEditorMultiLineProperty (TextEditor* comp, JucerDocument& doc)
: ComponentChoiceProperty <TextEditor> ("mode", comp, doc)
{
choices.add ("single line");
choices.add ("multi-line, return key starts new line");
choices.add ("multi-line, return key disabled");
}
void setIndex (int newIndex)
{
document.perform (new TextEditorMultilineChangeAction (component, *document.getComponentLayout(), newIndex),
"Change TextEditor multiline mode");
}
int getIndex() const
{
return component->isMultiLine() ? (component->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
}
private:
class TextEditorMultilineChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorMultilineChangeAction (TextEditor* const comp, ComponentLayout& l, const int newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->isMultiLine() ? (comp->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
}
bool perform()
{
showCorrectTab();
getComponent()->setMultiLine (newState > 0);
getComponent()->setReturnKeyStartsNewLine (newState == 1);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setMultiLine (oldState > 0);
getComponent()->setReturnKeyStartsNewLine (oldState == 1);
changed();
return true;
}
int newState, oldState;
};
};
//==============================================================================
class TextEditorReadOnlyProperty : public ComponentBooleanProperty <TextEditor>
{
public:
TextEditorReadOnlyProperty (TextEditor* comp, JucerDocument& doc)
: ComponentBooleanProperty <TextEditor> ("editable", "Editable", "Editable", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TextEditorReadonlyChangeAction (component, *document.getComponentLayout(), ! newState),
"Change TextEditor read-only mode");
}
bool getState() const { return ! component->isReadOnly(); }
private:
class TextEditorReadonlyChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorReadonlyChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->isReadOnly();
}
bool perform()
{
showCorrectTab();
getComponent()->setReadOnly (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setReadOnly (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TextEditorScrollbarsProperty : public ComponentBooleanProperty <TextEditor>
{
public:
TextEditorScrollbarsProperty (TextEditor* comp, JucerDocument& doc)
: ComponentBooleanProperty <TextEditor> ("scrollbars", "Scrollbars enabled", "Scrollbars enabled", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TextEditorScrollbarChangeAction (component, *document.getComponentLayout(), newState),
"Change TextEditor scrollbars");
}
bool getState() const { return component->areScrollbarsShown(); }
private:
class TextEditorScrollbarChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorScrollbarChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->areScrollbarsShown();
}
bool perform()
{
showCorrectTab();
getComponent()->setScrollbarsShown (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setScrollbarsShown (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TextEditorCaretProperty : public ComponentBooleanProperty <TextEditor>
{
public:
TextEditorCaretProperty (TextEditor* comp, JucerDocument& doc)
: ComponentBooleanProperty <TextEditor> ("caret", "Caret visible", "Caret visible", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TextEditorCaretChangeAction (component, *document.getComponentLayout(), newState),
"Change TextEditor caret");
}
bool getState() const { return component->isCaretVisible(); }
private:
class TextEditorCaretChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorCaretChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->isCaretVisible();
}
bool perform()
{
showCorrectTab();
getComponent()->setCaretVisible (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setCaretVisible (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TextEditorPopupMenuProperty : public ComponentBooleanProperty <TextEditor>
{
public:
TextEditorPopupMenuProperty (TextEditor* comp, JucerDocument& doc)
: ComponentBooleanProperty <TextEditor> ("popup menu", "Popup menu enabled", "Popup menu enabled", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TextEditorPopupMenuChangeAction (component, *document.getComponentLayout(), newState),
"Change TextEditor popup menu");
}
bool getState() const { return component->isPopupMenuEnabled(); }
private:
class TextEditorPopupMenuChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorPopupMenuChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->isPopupMenuEnabled();
}
bool perform()
{
showCorrectTab();
getComponent()->setPopupMenuEnabled (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setPopupMenuEnabled (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TextEditorInitialTextProperty : public ComponentTextProperty <TextEditor>
{
public:
TextEditorInitialTextProperty (TextEditor* comp, JucerDocument& doc)
: ComponentTextProperty <TextEditor> ("initial text", 10000, true, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new TextEditorInitialTextChangeAction (component, *document.getComponentLayout(), newText),
"Change TextEditor initial text");
}
String getText() const override
{
return component->getProperties() ["initialText"];
}
private:
class TextEditorInitialTextChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorInitialTextChangeAction (TextEditor* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->getProperties() ["initialText"];
}
bool perform()
{
showCorrectTab();
getComponent()->setText (newState, false);
getComponent()->getProperties().set ("initialText", newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setText (oldState, false);
getComponent()->getProperties().set ("initialText", oldState);
changed();
return true;
}
String newState, oldState;
};
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 TextEditorHandler : public ComponentTypeHandler
{
public:
TextEditorHandler()
: ComponentTypeHandler ("Text Editor", "juce::TextEditor", typeid (TextEditor), 150, 24)
{
registerColour (juce::TextEditor::textColourId, "text", "textcol");
registerColour (juce::TextEditor::backgroundColourId, "background", "bkgcol");
registerColour (juce::TextEditor::highlightColourId, "highlight", "hilitecol");
registerColour (juce::TextEditor::outlineColourId, "outline", "outlinecol");
registerColour (juce::TextEditor::shadowColourId, "shadow", "shadowcol");
registerColour (juce::CaretComponent::caretColourId, "caret", "caretcol");
}
Component* createNewComponent (JucerDocument*) override
{
return new TextEditor ("new text editor");
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
TextEditor* te = (TextEditor*) comp;
e->setAttribute ("initialText", comp->getProperties() ["initialText"].toString());
e->setAttribute ("multiline", te->isMultiLine());
e->setAttribute ("retKeyStartsLine", te->getReturnKeyStartsNewLine());
e->setAttribute ("readonly", te->isReadOnly());
e->setAttribute ("scrollbars", te->areScrollbarsShown());
e->setAttribute ("caret", te->isCaretVisible());
e->setAttribute ("popupmenu", te->isPopupMenuEnabled());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
TextEditor* te = (TextEditor*) comp;
TextEditor defaultEditor;
te->setMultiLine (xml.getBoolAttribute ("multiline", defaultEditor.isMultiLine()));
te->setReturnKeyStartsNewLine (xml.getBoolAttribute ("retKeyStartsLine", defaultEditor.getReturnKeyStartsNewLine()));
te->setReadOnly (xml.getBoolAttribute ("readonly", defaultEditor.isReadOnly()));
te->setScrollbarsShown (xml.getBoolAttribute ("scrollbars", defaultEditor.areScrollbarsShown()));
te->setCaretVisible (xml.getBoolAttribute ("caret", defaultEditor.isCaretVisible()));
te->setPopupMenuEnabled (xml.getBoolAttribute ("popupmenu", defaultEditor.isPopupMenuEnabled()));
const String initialText (xml.getStringAttribute ("initialText"));
te->setText (initialText, false);
te->getProperties().set ("initialText", initialText);
return true;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* t = dynamic_cast<TextEditor*> (component))
{
props.add (new TextEditorInitialTextProperty (t, document));
props.add (new TextEditorMultiLineProperty (t, document));
props.add (new TextEditorReadOnlyProperty (t, document));
props.add (new TextEditorScrollbarsProperty (t, document));
props.add (new TextEditorCaretProperty (t, document));
props.add (new TextEditorPopupMenuProperty (t, document));
addColourProperties (t, document, props);
}
}
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);
if (auto* te = dynamic_cast<TextEditor*> (component))
{
String s;
s << memberVariableName << "->setMultiLine (" << CodeHelpers::boolLiteral (te->isMultiLine()) << ");\n"
<< memberVariableName << "->setReturnKeyStartsNewLine (" << CodeHelpers::boolLiteral (te->getReturnKeyStartsNewLine()) << ");\n"
<< memberVariableName << "->setReadOnly (" << CodeHelpers::boolLiteral (te->isReadOnly()) << ");\n"
<< memberVariableName << "->setScrollbarsShown (" << CodeHelpers::boolLiteral (te->areScrollbarsShown()) << ");\n"
<< memberVariableName << "->setCaretVisible (" << CodeHelpers::boolLiteral (te->isCaretVisible()) << ");\n"
<< memberVariableName << "->setPopupMenuEnabled (" << CodeHelpers::boolLiteral (te->isPopupMenuEnabled()) << ");\n"
<< getColourIntialisationCode (component, memberVariableName)
<< memberVariableName << "->setText (" << quotedString (te->getProperties() ["initialText"].toString(), code.shouldUseTransMacro()) << ");\n\n";
code.constructorCode += s;
}
}
private:
//==============================================================================
class TextEditorMultiLineProperty : public ComponentChoiceProperty <TextEditor>
{
public:
TextEditorMultiLineProperty (TextEditor* comp, JucerDocument& doc)
: ComponentChoiceProperty <TextEditor> ("mode", comp, doc)
{
choices.add ("single line");
choices.add ("multi-line, return key starts new line");
choices.add ("multi-line, return key disabled");
}
void setIndex (int newIndex)
{
document.perform (new TextEditorMultilineChangeAction (component, *document.getComponentLayout(), newIndex),
"Change TextEditor multiline mode");
}
int getIndex() const
{
return component->isMultiLine() ? (component->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
}
private:
class TextEditorMultilineChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorMultilineChangeAction (TextEditor* const comp, ComponentLayout& l, const int newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->isMultiLine() ? (comp->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
}
bool perform()
{
showCorrectTab();
getComponent()->setMultiLine (newState > 0);
getComponent()->setReturnKeyStartsNewLine (newState == 1);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setMultiLine (oldState > 0);
getComponent()->setReturnKeyStartsNewLine (oldState == 1);
changed();
return true;
}
int newState, oldState;
};
};
//==============================================================================
class TextEditorReadOnlyProperty : public ComponentBooleanProperty <TextEditor>
{
public:
TextEditorReadOnlyProperty (TextEditor* comp, JucerDocument& doc)
: ComponentBooleanProperty <TextEditor> ("editable", "Editable", "Editable", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TextEditorReadonlyChangeAction (component, *document.getComponentLayout(), ! newState),
"Change TextEditor read-only mode");
}
bool getState() const { return ! component->isReadOnly(); }
private:
class TextEditorReadonlyChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorReadonlyChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->isReadOnly();
}
bool perform()
{
showCorrectTab();
getComponent()->setReadOnly (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setReadOnly (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TextEditorScrollbarsProperty : public ComponentBooleanProperty <TextEditor>
{
public:
TextEditorScrollbarsProperty (TextEditor* comp, JucerDocument& doc)
: ComponentBooleanProperty <TextEditor> ("scrollbars", "Scrollbars enabled", "Scrollbars enabled", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TextEditorScrollbarChangeAction (component, *document.getComponentLayout(), newState),
"Change TextEditor scrollbars");
}
bool getState() const { return component->areScrollbarsShown(); }
private:
class TextEditorScrollbarChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorScrollbarChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->areScrollbarsShown();
}
bool perform()
{
showCorrectTab();
getComponent()->setScrollbarsShown (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setScrollbarsShown (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TextEditorCaretProperty : public ComponentBooleanProperty <TextEditor>
{
public:
TextEditorCaretProperty (TextEditor* comp, JucerDocument& doc)
: ComponentBooleanProperty <TextEditor> ("caret", "Caret visible", "Caret visible", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TextEditorCaretChangeAction (component, *document.getComponentLayout(), newState),
"Change TextEditor caret");
}
bool getState() const { return component->isCaretVisible(); }
private:
class TextEditorCaretChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorCaretChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->isCaretVisible();
}
bool perform()
{
showCorrectTab();
getComponent()->setCaretVisible (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setCaretVisible (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TextEditorPopupMenuProperty : public ComponentBooleanProperty <TextEditor>
{
public:
TextEditorPopupMenuProperty (TextEditor* comp, JucerDocument& doc)
: ComponentBooleanProperty <TextEditor> ("popup menu", "Popup menu enabled", "Popup menu enabled", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TextEditorPopupMenuChangeAction (component, *document.getComponentLayout(), newState),
"Change TextEditor popup menu");
}
bool getState() const { return component->isPopupMenuEnabled(); }
private:
class TextEditorPopupMenuChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorPopupMenuChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->isPopupMenuEnabled();
}
bool perform()
{
showCorrectTab();
getComponent()->setPopupMenuEnabled (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setPopupMenuEnabled (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TextEditorInitialTextProperty : public ComponentTextProperty <TextEditor>
{
public:
TextEditorInitialTextProperty (TextEditor* comp, JucerDocument& doc)
: ComponentTextProperty <TextEditor> ("initial text", 10000, true, comp, doc)
{}
void setText (const String& newText) override
{
document.perform (new TextEditorInitialTextChangeAction (component, *document.getComponentLayout(), newText),
"Change TextEditor initial text");
}
String getText() const override
{
return component->getProperties() ["initialText"];
}
private:
class TextEditorInitialTextChangeAction : public ComponentUndoableAction <TextEditor>
{
public:
TextEditorInitialTextChangeAction (TextEditor* const comp, ComponentLayout& l, const String& newState_)
: ComponentUndoableAction <TextEditor> (comp, l),
newState (newState_)
{
oldState = comp->getProperties() ["initialText"];
}
bool perform()
{
showCorrectTab();
getComponent()->setText (newState, false);
getComponent()->getProperties().set ("initialText", newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setText (oldState, false);
getComponent()->getProperties().set ("initialText", oldState);
changed();
return true;
}
String newState, oldState;
};
};
};

View File

@ -1,146 +1,146 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 ToggleButtonHandler : public ButtonHandler
{
public:
ToggleButtonHandler()
: ButtonHandler ("Toggle Button", "juce::ToggleButton", typeid (ToggleButton), 150, 24)
{
registerColour (juce::ToggleButton::textColourId, "text colour", "txtcol");
}
Component* createNewComponent (JucerDocument*) override
{
return new ToggleButton ("new toggle button");
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ButtonHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* tb = dynamic_cast<ToggleButton*> (component))
props.add (new ToggleButtonStateProperty (tb, document));
addColourProperties (component, document, props);
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
ToggleButton* tb = (ToggleButton*) comp;
XmlElement* e = ButtonHandler::createXmlFor (comp, layout);
e->setAttribute ("state", tb->getToggleState());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
ToggleButton* const tb = (ToggleButton*) comp;
if (! ButtonHandler::restoreFromXml (xml, comp, layout))
return false;
tb->setToggleState (xml.getBoolAttribute ("state", false), dontSendNotification);
return true;
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ButtonHandler::fillInCreationCode (code, component, memberVariableName);
ToggleButton* const tb = dynamic_cast<ToggleButton*> (component);
String s;
if (tb->getToggleState())
s << memberVariableName << "->setToggleState (true, juce::dontSendNotification);\n";
s << getColourIntialisationCode (component, memberVariableName)
<< '\n';
code.constructorCode += s;
}
private:
class ToggleButtonStateProperty : public ComponentBooleanProperty <ToggleButton>
{
public:
ToggleButtonStateProperty (ToggleButton* button_, JucerDocument& doc)
: ComponentBooleanProperty <ToggleButton> ("initial state", "on", "off", button_, doc)
{
}
void setState (bool newState)
{
document.perform (new ToggleStateChangeAction (component, *document.getComponentLayout(), newState),
"Change ToggleButton state");
}
bool getState() const
{
return component->getToggleState();
}
private:
class ToggleStateChangeAction : public ComponentUndoableAction <ToggleButton>
{
public:
ToggleStateChangeAction (ToggleButton* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <ToggleButton> (comp, l),
newState (newState_)
{
oldState = comp->getToggleState();
}
bool perform()
{
showCorrectTab();
getComponent()->setToggleState (newState, dontSendNotification);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setToggleState (oldState, dontSendNotification);
changed();
return true;
}
bool newState, oldState;
};
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 ToggleButtonHandler : public ButtonHandler
{
public:
ToggleButtonHandler()
: ButtonHandler ("Toggle Button", "juce::ToggleButton", typeid (ToggleButton), 150, 24)
{
registerColour (juce::ToggleButton::textColourId, "text colour", "txtcol");
}
Component* createNewComponent (JucerDocument*) override
{
return new ToggleButton ("new toggle button");
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ButtonHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
if (auto* tb = dynamic_cast<ToggleButton*> (component))
props.add (new ToggleButtonStateProperty (tb, document));
addColourProperties (component, document, props);
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
ToggleButton* tb = (ToggleButton*) comp;
XmlElement* e = ButtonHandler::createXmlFor (comp, layout);
e->setAttribute ("state", tb->getToggleState());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
ToggleButton* const tb = (ToggleButton*) comp;
if (! ButtonHandler::restoreFromXml (xml, comp, layout))
return false;
tb->setToggleState (xml.getBoolAttribute ("state", false), dontSendNotification);
return true;
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
ButtonHandler::fillInCreationCode (code, component, memberVariableName);
ToggleButton* const tb = dynamic_cast<ToggleButton*> (component);
String s;
if (tb->getToggleState())
s << memberVariableName << "->setToggleState (true, juce::dontSendNotification);\n";
s << getColourIntialisationCode (component, memberVariableName)
<< '\n';
code.constructorCode += s;
}
private:
class ToggleButtonStateProperty : public ComponentBooleanProperty <ToggleButton>
{
public:
ToggleButtonStateProperty (ToggleButton* button_, JucerDocument& doc)
: ComponentBooleanProperty <ToggleButton> ("initial state", "on", "off", button_, doc)
{
}
void setState (bool newState)
{
document.perform (new ToggleStateChangeAction (component, *document.getComponentLayout(), newState),
"Change ToggleButton state");
}
bool getState() const
{
return component->getToggleState();
}
private:
class ToggleStateChangeAction : public ComponentUndoableAction <ToggleButton>
{
public:
ToggleStateChangeAction (ToggleButton* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <ToggleButton> (comp, l),
newState (newState_)
{
oldState = comp->getToggleState();
}
bool perform()
{
showCorrectTab();
getComponent()->setToggleState (newState, dontSendNotification);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setToggleState (oldState, dontSendNotification);
changed();
return true;
}
bool newState, oldState;
};
};
};

View File

@ -1,265 +1,265 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 TreeViewHandler : public ComponentTypeHandler
{
public:
TreeViewHandler()
: ComponentTypeHandler ("TreeView", "juce::TreeView", typeid (DemoTreeView), 150, 150)
{
registerColour (juce::TreeView::backgroundColourId, "background", "backgroundColour");
registerColour (juce::TreeView::linesColourId, "lines", "linecol");
}
Component* createNewComponent (JucerDocument*) override
{
return new DemoTreeView();
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
TreeView* const t = dynamic_cast<TreeView*> (comp);
XmlElement* const e = ComponentTypeHandler::createXmlFor (comp, layout);
e->setAttribute ("rootVisible", t->isRootItemVisible());
e->setAttribute ("openByDefault", t->areItemsOpenByDefault());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
TreeView defaultTreeView;
TreeView* const t = dynamic_cast<TreeView*> (comp);
t->setRootItemVisible (xml.getBoolAttribute ("rootVisible", defaultTreeView.isRootItemVisible()));
t->setDefaultOpenness (xml.getBoolAttribute ("openByDefault", defaultTreeView.areItemsOpenByDefault()));
return true;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
auto* t = dynamic_cast<TreeView*> (component);
props.add (new TreeViewRootItemProperty (t, document));
props.add (new TreeViewRootOpennessProperty (t, document));
addColourProperties (t, document, props);
}
String getCreationParameters (GeneratedCode&, Component* comp) override
{
return quotedString (comp->getName(), false);
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
TreeView defaultTreeView;
TreeView* const t = dynamic_cast<TreeView*> (component);
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
if (defaultTreeView.isRootItemVisible() != t->isRootItemVisible())
{
code.constructorCode
<< memberVariableName << "->setRootItemVisible ("
<< CodeHelpers::boolLiteral (t->isRootItemVisible()) << ");\n";
}
if (defaultTreeView.areItemsOpenByDefault() != t->areItemsOpenByDefault())
{
code.constructorCode
<< memberVariableName << "->setDefaultOpenness ("
<< CodeHelpers::boolLiteral (t->areItemsOpenByDefault()) << ");\n";
}
code.constructorCode << getColourIntialisationCode (component, memberVariableName);
code.constructorCode << "\n";
}
private:
//==============================================================================
class DemoTreeView : public TreeView
{
public:
DemoTreeView()
: TreeView ("new treeview")
{
setRootItem (new DemoTreeViewItem ("Demo root node", 4));
}
~DemoTreeView()
{
deleteRootItem();
}
private:
class DemoTreeViewItem : public TreeViewItem
{
public:
DemoTreeViewItem (const String& name_, const int numItems)
: name (name_)
{
for (int i = 0; i < numItems; ++i)
addSubItem (new DemoTreeViewItem ("Demo sub-node " + String (i), numItems - 1));
}
void paintItem (Graphics& g, int width, int height) override
{
if (isSelected())
g.fillAll (Colours::lightblue);
g.setColour (Colours::black);
g.setFont ((float) height * 0.7f);
g.drawText (name, 4, 0, width - 4, height, Justification::centredLeft, true);
}
bool mightContainSubItems() override
{
return true;
}
const String name;
};
};
//==============================================================================
class TreeViewRootItemProperty : public ComponentBooleanProperty <TreeView>
{
public:
TreeViewRootItemProperty (TreeView* comp, JucerDocument& doc)
: ComponentBooleanProperty <TreeView> ("show root item", "Root item visible", "Root item visible", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TreeviewRootChangeAction (component, *document.getComponentLayout(), newState),
"Change TreeView root item");
}
bool getState() const
{
return component->isRootItemVisible();
}
private:
class TreeviewRootChangeAction : public ComponentUndoableAction <TreeView>
{
public:
TreeviewRootChangeAction (TreeView* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TreeView> (comp, l),
newState (newState_)
{
oldState = comp->isRootItemVisible();
}
bool perform()
{
showCorrectTab();
getComponent()->setRootItemVisible (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setRootItemVisible (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TreeViewRootOpennessProperty : public ComponentChoiceProperty <TreeView>
{
public:
TreeViewRootOpennessProperty (TreeView* comp, JucerDocument& doc)
: ComponentChoiceProperty <TreeView> ("default openness", comp, doc)
{
choices.add ("Items open by default");
choices.add ("Items closed by default");
}
void setIndex (int newIndex)
{
document.perform (new TreeviewOpennessChangeAction (component, *document.getComponentLayout(), newIndex == 0),
"Change TreeView openness");
}
int getIndex() const
{
return component->areItemsOpenByDefault() ? 0 : 1;
}
private:
class TreeviewOpennessChangeAction : public ComponentUndoableAction <TreeView>
{
public:
TreeviewOpennessChangeAction (TreeView* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TreeView> (comp, l),
newState (newState_)
{
oldState = comp->areItemsOpenByDefault();
}
bool perform()
{
showCorrectTab();
getComponent()->setDefaultOpenness (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setDefaultOpenness (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
};
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
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 TreeViewHandler : public ComponentTypeHandler
{
public:
TreeViewHandler()
: ComponentTypeHandler ("TreeView", "juce::TreeView", typeid (DemoTreeView), 150, 150)
{
registerColour (juce::TreeView::backgroundColourId, "background", "backgroundColour");
registerColour (juce::TreeView::linesColourId, "lines", "linecol");
}
Component* createNewComponent (JucerDocument*) override
{
return new DemoTreeView();
}
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
{
TreeView* const t = dynamic_cast<TreeView*> (comp);
XmlElement* const e = ComponentTypeHandler::createXmlFor (comp, layout);
e->setAttribute ("rootVisible", t->isRootItemVisible());
e->setAttribute ("openByDefault", t->areItemsOpenByDefault());
return e;
}
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
{
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
return false;
TreeView defaultTreeView;
TreeView* const t = dynamic_cast<TreeView*> (comp);
t->setRootItemVisible (xml.getBoolAttribute ("rootVisible", defaultTreeView.isRootItemVisible()));
t->setDefaultOpenness (xml.getBoolAttribute ("openByDefault", defaultTreeView.areItemsOpenByDefault()));
return true;
}
void getEditableProperties (Component* component, JucerDocument& document,
Array<PropertyComponent*>& props, bool multipleSelected) override
{
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
if (multipleSelected)
return;
auto* t = dynamic_cast<TreeView*> (component);
props.add (new TreeViewRootItemProperty (t, document));
props.add (new TreeViewRootOpennessProperty (t, document));
addColourProperties (t, document, props);
}
String getCreationParameters (GeneratedCode&, Component* comp) override
{
return quotedString (comp->getName(), false);
}
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
{
TreeView defaultTreeView;
TreeView* const t = dynamic_cast<TreeView*> (component);
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
if (defaultTreeView.isRootItemVisible() != t->isRootItemVisible())
{
code.constructorCode
<< memberVariableName << "->setRootItemVisible ("
<< CodeHelpers::boolLiteral (t->isRootItemVisible()) << ");\n";
}
if (defaultTreeView.areItemsOpenByDefault() != t->areItemsOpenByDefault())
{
code.constructorCode
<< memberVariableName << "->setDefaultOpenness ("
<< CodeHelpers::boolLiteral (t->areItemsOpenByDefault()) << ");\n";
}
code.constructorCode << getColourIntialisationCode (component, memberVariableName);
code.constructorCode << "\n";
}
private:
//==============================================================================
class DemoTreeView : public TreeView
{
public:
DemoTreeView()
: TreeView ("new treeview")
{
setRootItem (new DemoTreeViewItem ("Demo root node", 4));
}
~DemoTreeView()
{
deleteRootItem();
}
private:
class DemoTreeViewItem : public TreeViewItem
{
public:
DemoTreeViewItem (const String& name_, const int numItems)
: name (name_)
{
for (int i = 0; i < numItems; ++i)
addSubItem (new DemoTreeViewItem ("Demo sub-node " + String (i), numItems - 1));
}
void paintItem (Graphics& g, int width, int height) override
{
if (isSelected())
g.fillAll (Colours::lightblue);
g.setColour (Colours::black);
g.setFont ((float) height * 0.7f);
g.drawText (name, 4, 0, width - 4, height, Justification::centredLeft, true);
}
bool mightContainSubItems() override
{
return true;
}
const String name;
};
};
//==============================================================================
class TreeViewRootItemProperty : public ComponentBooleanProperty <TreeView>
{
public:
TreeViewRootItemProperty (TreeView* comp, JucerDocument& doc)
: ComponentBooleanProperty <TreeView> ("show root item", "Root item visible", "Root item visible", comp, doc)
{
}
void setState (bool newState)
{
document.perform (new TreeviewRootChangeAction (component, *document.getComponentLayout(), newState),
"Change TreeView root item");
}
bool getState() const
{
return component->isRootItemVisible();
}
private:
class TreeviewRootChangeAction : public ComponentUndoableAction <TreeView>
{
public:
TreeviewRootChangeAction (TreeView* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TreeView> (comp, l),
newState (newState_)
{
oldState = comp->isRootItemVisible();
}
bool perform()
{
showCorrectTab();
getComponent()->setRootItemVisible (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setRootItemVisible (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
//==============================================================================
class TreeViewRootOpennessProperty : public ComponentChoiceProperty <TreeView>
{
public:
TreeViewRootOpennessProperty (TreeView* comp, JucerDocument& doc)
: ComponentChoiceProperty <TreeView> ("default openness", comp, doc)
{
choices.add ("Items open by default");
choices.add ("Items closed by default");
}
void setIndex (int newIndex)
{
document.perform (new TreeviewOpennessChangeAction (component, *document.getComponentLayout(), newIndex == 0),
"Change TreeView openness");
}
int getIndex() const
{
return component->areItemsOpenByDefault() ? 0 : 1;
}
private:
class TreeviewOpennessChangeAction : public ComponentUndoableAction <TreeView>
{
public:
TreeviewOpennessChangeAction (TreeView* const comp, ComponentLayout& l, const bool newState_)
: ComponentUndoableAction <TreeView> (comp, l),
newState (newState_)
{
oldState = comp->areItemsOpenByDefault();
}
bool perform()
{
showCorrectTab();
getComponent()->setDefaultOpenness (newState);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setDefaultOpenness (oldState);
changed();
return true;
}
bool newState, oldState;
};
};
};