git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
389
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ButtonHandler.h
vendored
Normal file
389
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ButtonHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
||||
};
|
446
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComboBoxHandler.h
vendored
Normal file
446
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComboBoxHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
||||
};
|
178
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentNameProperty.h
vendored
Normal file
178
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentNameProperty.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
638
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentTypeHandler.cpp
vendored
Normal file
638
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentTypeHandler.cpp
vendored
Normal file
@ -0,0 +1,638 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../Application/jucer_Headers.h"
|
||||
#include "../../Application/jucer_Application.h"
|
||||
#include "../jucer_ObjectTypes.h"
|
||||
#include "../jucer_UtilityFunctions.h"
|
||||
#include "../UI/jucer_JucerCommandIDs.h"
|
||||
#include "../UI/jucer_ComponentOverlayComponent.h"
|
||||
#include "jucer_ComponentNameProperty.h"
|
||||
#include "../Properties/jucer_PositionPropertyBase.h"
|
||||
#include "../Properties/jucer_ComponentColourProperty.h"
|
||||
#include "../UI/jucer_TestComponent.h"
|
||||
|
||||
static String getTypeInfoName (const std::type_info& info)
|
||||
{
|
||||
#if JUCE_MSVC
|
||||
return info.raw_name();
|
||||
#else
|
||||
return info.name();
|
||||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ComponentTypeHandler::ComponentTypeHandler (const String& typeName_,
|
||||
const String& className_,
|
||||
const std::type_info& componentClass_,
|
||||
const int defaultWidth_,
|
||||
const int defaultHeight_)
|
||||
: typeName (typeName_),
|
||||
className (className_),
|
||||
componentClassRawName (getTypeInfoName (componentClass_)),
|
||||
defaultWidth (defaultWidth_),
|
||||
defaultHeight (defaultHeight_)
|
||||
{
|
||||
}
|
||||
|
||||
Component* ComponentTypeHandler::createCopyOf (JucerDocument* document, Component& existing)
|
||||
{
|
||||
jassert (getHandlerFor (existing) == this);
|
||||
|
||||
Component* const newOne = createNewComponent (document);
|
||||
std::unique_ptr<XmlElement> xml (createXmlFor (&existing, document->getComponentLayout()));
|
||||
|
||||
if (xml != nullptr)
|
||||
restoreFromXml (*xml, newOne, document->getComponentLayout());
|
||||
|
||||
return newOne;
|
||||
}
|
||||
|
||||
ComponentOverlayComponent* ComponentTypeHandler::createOverlayComponent (Component* child, ComponentLayout& layout)
|
||||
{
|
||||
return new ComponentOverlayComponent (child, layout);
|
||||
}
|
||||
|
||||
static void dummyMenuCallback (int, int) {}
|
||||
|
||||
void ComponentTypeHandler::showPopupMenu (Component*, ComponentLayout& layout)
|
||||
{
|
||||
PopupMenu m;
|
||||
|
||||
ApplicationCommandManager* commandManager = &ProjucerApplication::getCommandManager();
|
||||
|
||||
m.addCommandItem (commandManager, JucerCommandIDs::toFront);
|
||||
m.addCommandItem (commandManager, JucerCommandIDs::toBack);
|
||||
m.addSeparator();
|
||||
|
||||
if (layout.getSelectedSet().getNumSelected() > 1)
|
||||
{
|
||||
m.addCommandItem (commandManager, JucerCommandIDs::alignTop);
|
||||
m.addCommandItem (commandManager, JucerCommandIDs::alignRight);
|
||||
m.addCommandItem (commandManager, JucerCommandIDs::alignBottom);
|
||||
m.addCommandItem (commandManager, JucerCommandIDs::alignLeft);
|
||||
m.addSeparator();
|
||||
}
|
||||
|
||||
m.addCommandItem (commandManager, StandardApplicationCommandIDs::cut);
|
||||
m.addCommandItem (commandManager, StandardApplicationCommandIDs::copy);
|
||||
m.addCommandItem (commandManager, StandardApplicationCommandIDs::paste);
|
||||
m.addCommandItem (commandManager, StandardApplicationCommandIDs::del);
|
||||
|
||||
m.showMenuAsync (PopupMenu::Options(),
|
||||
ModalCallbackFunction::create (dummyMenuCallback, 0));
|
||||
}
|
||||
|
||||
JucerDocument* ComponentTypeHandler::findParentDocument (Component* component)
|
||||
{
|
||||
Component* p = component->getParentComponent();
|
||||
|
||||
while (p != nullptr)
|
||||
{
|
||||
if (JucerDocumentEditor* const ed = dynamic_cast<JucerDocumentEditor*> (p))
|
||||
return ed->getDocument();
|
||||
|
||||
if (TestComponent* const t = dynamic_cast<TestComponent*> (p))
|
||||
return t->getDocument();
|
||||
|
||||
p = p->getParentComponent();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool ComponentTypeHandler::canHandle (Component& component) const
|
||||
{
|
||||
return componentClassRawName == getTypeInfoName (typeid (component));
|
||||
}
|
||||
|
||||
ComponentTypeHandler* ComponentTypeHandler::getHandlerFor (Component& component)
|
||||
{
|
||||
for (int i = 0; i < ObjectTypes::numComponentTypes; ++i)
|
||||
if (ObjectTypes::componentTypeHandlers[i]->canHandle (component))
|
||||
return ObjectTypes::componentTypeHandlers[i];
|
||||
|
||||
jassertfalse;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ComponentTypeHandler* ComponentTypeHandler::getHandlerForXmlTag (const String& tagName)
|
||||
{
|
||||
for (int i = 0; i < ObjectTypes::numComponentTypes; ++i)
|
||||
if (ObjectTypes::componentTypeHandlers[i]->getXmlTagName().equalsIgnoreCase (tagName))
|
||||
return ObjectTypes::componentTypeHandlers[i];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
XmlElement* ComponentTypeHandler::createXmlFor (Component* comp, const ComponentLayout* layout)
|
||||
{
|
||||
XmlElement* e = new XmlElement (getXmlTagName());
|
||||
|
||||
e->setAttribute ("name", comp->getName());
|
||||
e->setAttribute ("id", String::toHexString (getComponentId (comp)));
|
||||
e->setAttribute ("memberName", comp->getProperties() ["memberName"].toString());
|
||||
e->setAttribute ("virtualName", comp->getProperties() ["virtualName"].toString());
|
||||
e->setAttribute ("explicitFocusOrder", comp->getExplicitFocusOrder());
|
||||
|
||||
RelativePositionedRectangle pos (getComponentPosition (comp));
|
||||
pos.updateFromComponent (*comp, layout);
|
||||
pos.applyToXml (*e);
|
||||
|
||||
if (SettableTooltipClient* const ttc = dynamic_cast<SettableTooltipClient*> (comp))
|
||||
if (ttc->getTooltip().isNotEmpty())
|
||||
e->setAttribute ("tooltip", ttc->getTooltip());
|
||||
|
||||
for (int i = 0; i < colours.size(); ++i)
|
||||
{
|
||||
if (comp->isColourSpecified (colours[i]->colourId))
|
||||
{
|
||||
e->setAttribute (colours[i]->xmlTagName,
|
||||
comp->findColour (colours[i]->colourId).toString());
|
||||
}
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool ComponentTypeHandler::restoreFromXml (const XmlElement& xml,
|
||||
Component* comp,
|
||||
const ComponentLayout* layout)
|
||||
{
|
||||
jassert (xml.hasTagName (getXmlTagName()));
|
||||
|
||||
if (! xml.hasTagName (getXmlTagName()))
|
||||
return false;
|
||||
|
||||
comp->setName (xml.getStringAttribute ("name", comp->getName()));
|
||||
setComponentId (comp, xml.getStringAttribute ("id").getHexValue64());
|
||||
comp->getProperties().set ("memberName", xml.getStringAttribute ("memberName"));
|
||||
comp->getProperties().set ("virtualName", xml.getStringAttribute ("virtualName"));
|
||||
comp->setExplicitFocusOrder (xml.getIntAttribute ("explicitFocusOrder"));
|
||||
|
||||
RelativePositionedRectangle currentPos (getComponentPosition (comp));
|
||||
currentPos.updateFromComponent (*comp, layout);
|
||||
|
||||
RelativePositionedRectangle rpr;
|
||||
rpr.restoreFromXml (xml, currentPos);
|
||||
|
||||
jassert (layout != nullptr);
|
||||
setComponentPosition (comp, rpr, layout);
|
||||
|
||||
if (SettableTooltipClient* const ttc = dynamic_cast<SettableTooltipClient*> (comp))
|
||||
ttc->setTooltip (xml.getStringAttribute ("tooltip"));
|
||||
|
||||
for (int i = 0; i < colours.size(); ++i)
|
||||
{
|
||||
const String col (xml.getStringAttribute (colours[i]->xmlTagName, String()));
|
||||
|
||||
if (col.isNotEmpty())
|
||||
comp->setColour (colours[i]->colourId, Colour::fromString (col));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int64 ComponentTypeHandler::getComponentId (Component* comp)
|
||||
{
|
||||
if (comp == nullptr)
|
||||
return 0;
|
||||
|
||||
int64 compId = comp->getProperties() ["jucerCompId"].toString().getHexValue64();
|
||||
|
||||
if (compId == 0)
|
||||
{
|
||||
compId = Random::getSystemRandom().nextInt64();
|
||||
setComponentId (comp, compId);
|
||||
}
|
||||
|
||||
return compId;
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::setComponentId (Component* comp, const int64 newID)
|
||||
{
|
||||
jassert (comp != nullptr);
|
||||
if (newID != 0)
|
||||
comp->getProperties().set ("jucerCompId", String::toHexString (newID));
|
||||
}
|
||||
|
||||
RelativePositionedRectangle ComponentTypeHandler::getComponentPosition (Component* comp)
|
||||
{
|
||||
RelativePositionedRectangle rp;
|
||||
rp.rect = PositionedRectangle (comp->getProperties() ["pos"]);
|
||||
rp.relativeToX = comp->getProperties() ["relativeToX"].toString().getHexValue64();
|
||||
rp.relativeToY = comp->getProperties() ["relativeToY"].toString().getHexValue64();
|
||||
rp.relativeToW = comp->getProperties() ["relativeToW"].toString().getHexValue64();
|
||||
rp.relativeToH = comp->getProperties() ["relativeToH"].toString().getHexValue64();
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::setComponentPosition (Component* comp,
|
||||
const RelativePositionedRectangle& newPos,
|
||||
const ComponentLayout* layout)
|
||||
{
|
||||
comp->getProperties().set ("pos", newPos.rect.toString());
|
||||
comp->getProperties().set ("relativeToX", String::toHexString (newPos.relativeToX));
|
||||
comp->getProperties().set ("relativeToY", String::toHexString (newPos.relativeToY));
|
||||
comp->getProperties().set ("relativeToW", String::toHexString (newPos.relativeToW));
|
||||
comp->getProperties().set ("relativeToH", String::toHexString (newPos.relativeToH));
|
||||
|
||||
comp->setBounds (newPos.getRectangle (Rectangle<int> (0, 0, comp->getParentWidth(), comp->getParentHeight()),
|
||||
layout));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class TooltipProperty : public ComponentTextProperty <Component>
|
||||
{
|
||||
public:
|
||||
TooltipProperty (Component* comp, JucerDocument& doc)
|
||||
: ComponentTextProperty<Component> ("tooltip", 1024, true, comp, doc)
|
||||
{
|
||||
}
|
||||
|
||||
String getText() const override
|
||||
{
|
||||
SettableTooltipClient* ttc = dynamic_cast<SettableTooltipClient*> (component);
|
||||
return ttc->getTooltip();
|
||||
}
|
||||
|
||||
void setText (const String& newText) override
|
||||
{
|
||||
document.perform (new SetTooltipAction (component, *document.getComponentLayout(), newText),
|
||||
"Change tooltip");
|
||||
}
|
||||
|
||||
private:
|
||||
class SetTooltipAction : public ComponentUndoableAction <Component>
|
||||
{
|
||||
public:
|
||||
SetTooltipAction (Component* const comp, ComponentLayout& l, const String& newValue_)
|
||||
: ComponentUndoableAction<Component> (comp, l),
|
||||
newValue (newValue_)
|
||||
{
|
||||
SettableTooltipClient* ttc = dynamic_cast<SettableTooltipClient*> (comp);
|
||||
jassert (ttc != nullptr);
|
||||
oldValue = ttc->getTooltip();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
|
||||
if (SettableTooltipClient* ttc = dynamic_cast<SettableTooltipClient*> (getComponent()))
|
||||
{
|
||||
ttc->setTooltip (newValue);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
|
||||
if (SettableTooltipClient* ttc = dynamic_cast<SettableTooltipClient*> (getComponent()))
|
||||
{
|
||||
ttc->setTooltip (oldValue);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String newValue, oldValue;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ComponentPositionProperty : public PositionPropertyBase
|
||||
{
|
||||
public:
|
||||
ComponentPositionProperty (Component* comp,
|
||||
JucerDocument& doc,
|
||||
const String& name,
|
||||
ComponentPositionDimension dimension_)
|
||||
: PositionPropertyBase (comp, name, dimension_,
|
||||
true, true,
|
||||
doc.getComponentLayout()),
|
||||
document (doc)
|
||||
{
|
||||
document.addChangeListener (this);
|
||||
}
|
||||
|
||||
~ComponentPositionProperty()
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setPosition (const RelativePositionedRectangle& newPos)
|
||||
{
|
||||
auto* l = document.getComponentLayout();
|
||||
|
||||
if (l->getSelectedSet().getNumSelected() > 1)
|
||||
positionOtherSelectedComponents (ComponentTypeHandler::getComponentPosition (component), newPos);
|
||||
|
||||
l->setComponentPosition (component, newPos, true);
|
||||
}
|
||||
|
||||
RelativePositionedRectangle getPosition() const
|
||||
{
|
||||
return ComponentTypeHandler::getComponentPosition (component);
|
||||
}
|
||||
|
||||
private:
|
||||
JucerDocument& document;
|
||||
|
||||
void positionOtherSelectedComponents (const RelativePositionedRectangle& oldPos, const RelativePositionedRectangle& newPos)
|
||||
{
|
||||
for (auto* s : document.getComponentLayout()->getSelectedSet())
|
||||
{
|
||||
if (s != component)
|
||||
{
|
||||
auto currentPos = ComponentTypeHandler::getComponentPosition (s);
|
||||
auto diff = 0.0;
|
||||
|
||||
if (dimension == ComponentPositionDimension::componentX)
|
||||
{
|
||||
diff = newPos.rect.getX() - oldPos.rect.getX();
|
||||
currentPos.rect.setX (currentPos.rect.getX() + diff);
|
||||
}
|
||||
else if (dimension == ComponentPositionDimension::componentY)
|
||||
{
|
||||
diff = newPos.rect.getY() - oldPos.rect.getY();
|
||||
currentPos.rect.setY (currentPos.rect.getY() + diff);
|
||||
}
|
||||
else if (dimension == ComponentPositionDimension::componentWidth)
|
||||
{
|
||||
diff = newPos.rect.getWidth() - oldPos.rect.getWidth();
|
||||
currentPos.rect.setWidth (currentPos.rect.getWidth() + diff);
|
||||
}
|
||||
else if (dimension == ComponentPositionDimension::componentHeight)
|
||||
{
|
||||
diff = newPos.rect.getHeight() - oldPos.rect.getHeight();
|
||||
currentPos.rect.setHeight (currentPos.rect.getHeight() + diff);
|
||||
}
|
||||
|
||||
document.getComponentLayout()->setComponentPosition (s, currentPos, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class FocusOrderProperty : public ComponentTextProperty <Component>
|
||||
{
|
||||
public:
|
||||
FocusOrderProperty (Component* comp, JucerDocument& doc)
|
||||
: ComponentTextProperty <Component> ("focus order", 8, false, comp, doc)
|
||||
{
|
||||
}
|
||||
|
||||
String getText() const override
|
||||
{
|
||||
return String (component->getExplicitFocusOrder());
|
||||
}
|
||||
|
||||
void setText (const String& newText) override
|
||||
{
|
||||
document.perform (new SetFocusOrderAction (component, *document.getComponentLayout(), jmax (0, newText.getIntValue())),
|
||||
"Change focus order");
|
||||
}
|
||||
|
||||
private:
|
||||
class SetFocusOrderAction : public ComponentUndoableAction <Component>
|
||||
{
|
||||
public:
|
||||
SetFocusOrderAction (Component* const comp, ComponentLayout& l, const int newOrder_)
|
||||
: ComponentUndoableAction <Component> (comp, l),
|
||||
newValue (newOrder_)
|
||||
{
|
||||
oldValue = comp->getExplicitFocusOrder();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setExplicitFocusOrder (newValue);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setExplicitFocusOrder (oldValue);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
int newValue, oldValue;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void ComponentTypeHandler::getEditableProperties (Component* component,
|
||||
JucerDocument& document,
|
||||
Array<PropertyComponent*>& props,
|
||||
bool multipleSelected)
|
||||
{
|
||||
if (! multipleSelected)
|
||||
{
|
||||
props.add (new ComponentMemberNameProperty (component, document));
|
||||
props.add (new ComponentNameProperty (component, document));
|
||||
props.add (new ComponentVirtualClassProperty (component, document));
|
||||
|
||||
if (dynamic_cast<SettableTooltipClient*> (component) != nullptr)
|
||||
props.add (new TooltipProperty (component, document));
|
||||
|
||||
props.add (new FocusOrderProperty (component, document));
|
||||
}
|
||||
|
||||
props.add (new ComponentPositionProperty (component, document, "x", ComponentPositionProperty::componentX));
|
||||
props.add (new ComponentPositionProperty (component, document, "y", ComponentPositionProperty::componentY));
|
||||
props.add (new ComponentPositionProperty (component, document, "width", ComponentPositionProperty::componentWidth));
|
||||
props.add (new ComponentPositionProperty (component, document, "height", ComponentPositionProperty::componentHeight));
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::addPropertiesToPropertyPanel (Component* comp, JucerDocument& document,
|
||||
PropertyPanel& panel, bool multipleSelected)
|
||||
{
|
||||
Array <PropertyComponent*> props;
|
||||
getEditableProperties (comp, document, props, multipleSelected);
|
||||
|
||||
panel.addSection (getClassName (comp), props);
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::registerEditableColour (int colourId,
|
||||
const String& colourIdCode,
|
||||
const String& colourName, const String& xmlTagName)
|
||||
{
|
||||
ComponentColourInfo* const c = new ComponentColourInfo();
|
||||
|
||||
c->colourId = colourId;
|
||||
c->colourIdCode = colourIdCode;
|
||||
c->colourName = colourName;
|
||||
c->xmlTagName = xmlTagName;
|
||||
|
||||
colours.add (c);
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::addColourProperties (Component* component,
|
||||
JucerDocument& document,
|
||||
Array<PropertyComponent*>& props)
|
||||
{
|
||||
for (int i = 0; i < colours.size(); ++i)
|
||||
props.add (new ComponentColourIdProperty (component, document,
|
||||
colours[i]->colourId,
|
||||
colours[i]->colourName,
|
||||
true));
|
||||
}
|
||||
|
||||
String ComponentTypeHandler::getColourIntialisationCode (Component* component,
|
||||
const String& objectName)
|
||||
{
|
||||
String s;
|
||||
|
||||
for (int i = 0; i < colours.size(); ++i)
|
||||
{
|
||||
if (component->isColourSpecified (colours[i]->colourId))
|
||||
{
|
||||
s << objectName << "->setColour ("
|
||||
<< colours[i]->colourIdCode
|
||||
<< ", "
|
||||
<< CodeHelpers::colourToCode (component->findColour (colours[i]->colourId))
|
||||
<< ");\n";
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ComponentTypeHandler::fillInGeneratedCode (Component* component, GeneratedCode& code)
|
||||
{
|
||||
const String memberVariableName (code.document->getComponentLayout()->getComponentMemberVariableName (component));
|
||||
|
||||
fillInMemberVariableDeclarations (code, component, memberVariableName);
|
||||
fillInCreationCode (code, component, memberVariableName);
|
||||
fillInDeletionCode (code, component, memberVariableName);
|
||||
fillInResizeCode (code, component, memberVariableName);
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::fillInMemberVariableDeclarations (GeneratedCode& code, Component* component, const String& memberVariableName)
|
||||
{
|
||||
String clsName (component->getProperties() ["virtualName"].toString());
|
||||
|
||||
if (clsName.isNotEmpty())
|
||||
clsName = build_tools::makeValidIdentifier (clsName, false, false, true);
|
||||
else
|
||||
clsName = getClassName (component);
|
||||
|
||||
code.privateMemberDeclarations
|
||||
<< "std::unique_ptr<" << clsName << "> " << memberVariableName << ";\n";
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::fillInResizeCode (GeneratedCode& code, Component* component, const String& memberVariableName)
|
||||
{
|
||||
const RelativePositionedRectangle pos (getComponentPosition (component));
|
||||
|
||||
String x, y, w, h, r;
|
||||
positionToCode (pos, code.document->getComponentLayout(), x, y, w, h);
|
||||
|
||||
r << memberVariableName << "->setBounds ("
|
||||
<< x << ", " << y << ", " << w << ", " << h << ");\n";
|
||||
|
||||
if (pos.rect.isPositionAbsolute() && ! code.document->getComponentLayout()->isComponentPositionRelative (component))
|
||||
code.constructorCode += r + "\n";
|
||||
else
|
||||
code.getCallbackCode (String(), "void", "resized()", false) += r;
|
||||
}
|
||||
|
||||
String ComponentTypeHandler::getCreationParameters (GeneratedCode&, Component*)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName)
|
||||
{
|
||||
String params (getCreationParameters (code, component));
|
||||
const String virtualName (component->getProperties() ["virtualName"].toString());
|
||||
|
||||
String s;
|
||||
s << memberVariableName << ".reset (new ";
|
||||
|
||||
if (virtualName.isNotEmpty())
|
||||
s << build_tools::makeValidIdentifier (virtualName, false, false, true);
|
||||
else
|
||||
s << getClassName (component);
|
||||
|
||||
if (params.isEmpty())
|
||||
{
|
||||
s << "());\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
StringArray lines;
|
||||
lines.addLines (params);
|
||||
|
||||
params = lines.joinIntoString ("\n" + String::repeatedString (" ", s.length() + 2));
|
||||
|
||||
s << " (" << params << "));\n";
|
||||
}
|
||||
|
||||
s << "addAndMakeVisible (" << memberVariableName << ".get());\n";
|
||||
|
||||
|
||||
if (auto* ttc = dynamic_cast<SettableTooltipClient*> (component))
|
||||
{
|
||||
if (ttc->getTooltip().isNotEmpty())
|
||||
{
|
||||
s << memberVariableName << "->setTooltip ("
|
||||
<< quotedString (ttc->getTooltip(), code.shouldUseTransMacro())
|
||||
<< ");\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (component != nullptr && component->getExplicitFocusOrder() > 0)
|
||||
s << memberVariableName << "->setExplicitFocusOrder ("
|
||||
<< component->getExplicitFocusOrder()
|
||||
<< ");\n";
|
||||
|
||||
code.constructorCode += s;
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::fillInDeletionCode (GeneratedCode& code, Component*,
|
||||
const String& memberVariableName)
|
||||
{
|
||||
code.destructorCode
|
||||
<< memberVariableName << " = nullptr;\n";
|
||||
}
|
147
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentTypeHandler.h
vendored
Normal file
147
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentTypeHandler.h
vendored
Normal file
@ -0,0 +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)
|
||||
};
|
75
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentUndoableAction.h
vendored
Normal file
75
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentUndoableAction.h
vendored
Normal file
@ -0,0 +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)
|
||||
};
|
241
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_GenericComponentHandler.h
vendored
Normal file
241
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_GenericComponentHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
||||
};
|
237
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_GroupComponentHandler.h
vendored
Normal file
237
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_GroupComponentHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
||||
};
|
149
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_HyperlinkButtonHandler.h
vendored
Normal file
149
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_HyperlinkButtonHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
||||
};
|
526
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ImageButtonHandler.h
vendored
Normal file
526
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ImageButtonHandler.h
vendored
Normal file
@ -0,0 +1,526 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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 ImageButtonHandler : public ButtonHandler
|
||||
{
|
||||
public:
|
||||
enum ImageRole
|
||||
{
|
||||
normalImage = 0,
|
||||
overImage = 1,
|
||||
downImage = 2
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
ImageButtonHandler()
|
||||
: ButtonHandler ("Image Button", "juce::ImageButton", typeid (ImageButton), 150, 24)
|
||||
{
|
||||
}
|
||||
|
||||
Component* createNewComponent (JucerDocument*) override
|
||||
{
|
||||
return new ImageButton ("new button");
|
||||
}
|
||||
|
||||
void getEditableProperties (Component* component, JucerDocument& document,
|
||||
Array<PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
ButtonHandler::getEditableProperties (component, document, props, multipleSelected);
|
||||
|
||||
if (multipleSelected)
|
||||
return;
|
||||
|
||||
addColourProperties (component, document, props);
|
||||
|
||||
if (auto* ib = dynamic_cast<ImageButton*> (component))
|
||||
{
|
||||
auto& layout = *document.getComponentLayout();
|
||||
|
||||
props.add (new ImageButtonProportionProperty (layout, ib));
|
||||
|
||||
props.add (new ImageButtonResourceProperty (layout, ib, normalImage, "normal image"));
|
||||
props.add (new ImageButtonOpacityProperty (layout, ib, "opacity", normalImage));
|
||||
props.add (new ImageButtonColourProperty (layout, ib, "overlay col.", normalImage));
|
||||
|
||||
props.add (new ImageButtonResourceProperty (layout, ib, overImage, "over image"));
|
||||
props.add (new ImageButtonOpacityProperty (layout, ib, "opacity", overImage));
|
||||
props.add (new ImageButtonColourProperty (layout, ib, "overlay col.", overImage));
|
||||
|
||||
props.add (new ImageButtonResourceProperty (layout, ib, downImage, "down image"));
|
||||
props.add (new ImageButtonOpacityProperty (layout, ib, "opacity", downImage));
|
||||
props.add (new ImageButtonColourProperty (layout, ib, "overlay col.", downImage));
|
||||
}
|
||||
}
|
||||
|
||||
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
|
||||
{
|
||||
XmlElement* e = ButtonHandler::createXmlFor (comp, layout);
|
||||
|
||||
ImageButton* const ib = (ImageButton*) comp;
|
||||
|
||||
e->setAttribute ("keepProportions", doesImageKeepProportions (ib));
|
||||
|
||||
e->setAttribute ("resourceNormal", getImageResource (ib, normalImage));
|
||||
e->setAttribute ("opacityNormal", getImageOpacity (ib, normalImage));
|
||||
e->setAttribute ("colourNormal", getImageColour (ib, normalImage).toString());
|
||||
|
||||
e->setAttribute ("resourceOver", getImageResource (ib, overImage));
|
||||
e->setAttribute ("opacityOver", getImageOpacity (ib, overImage));
|
||||
e->setAttribute ("colourOver", getImageColour (ib, overImage).toString());
|
||||
|
||||
e->setAttribute ("resourceDown", getImageResource (ib, downImage));
|
||||
e->setAttribute ("opacityDown", getImageOpacity (ib, downImage));
|
||||
e->setAttribute ("colourDown", getImageColour (ib, downImage).toString());
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
|
||||
{
|
||||
if (! ButtonHandler::restoreFromXml (xml, comp, layout))
|
||||
return false;
|
||||
|
||||
ImageButton* const ib = (ImageButton*) comp;
|
||||
ComponentLayout& l = const_cast<ComponentLayout&> (*layout);
|
||||
|
||||
setImageKeepProportions (l, ib, xml.getBoolAttribute ("keepProportions", true), false);
|
||||
|
||||
setImageResource (l, ib, normalImage, xml.getStringAttribute ("resourceNormal", String()), false);
|
||||
setImageOpacity (l, ib, normalImage, (float) xml.getDoubleAttribute ("opacityNormal", 1.0f), false);
|
||||
setImageColour (l, ib, normalImage, Colour::fromString (xml.getStringAttribute ("colourNormal", "0")), false);
|
||||
|
||||
setImageResource (l, ib, overImage, xml.getStringAttribute ("resourceOver", String()), false);
|
||||
setImageOpacity (l, ib, overImage, (float) xml.getDoubleAttribute ("opacityOver", 1.0f), false);
|
||||
setImageColour (l, ib, overImage, Colour::fromString (xml.getStringAttribute ("colourOver", "0")), false);
|
||||
|
||||
setImageResource (l, ib, downImage, xml.getStringAttribute ("resourceDown", String()), false);
|
||||
setImageOpacity (l, ib, downImage, (float) xml.getDoubleAttribute ("opacityDown", 1.0f), false);
|
||||
setImageColour (l, ib, downImage, Colour::fromString (xml.getStringAttribute ("colourDown", "0")), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
|
||||
{
|
||||
ButtonHandler::fillInCreationCode (code, component, memberVariableName);
|
||||
|
||||
ImageButton* const ib = dynamic_cast<ImageButton*> (component);
|
||||
|
||||
String s;
|
||||
|
||||
s << getColourIntialisationCode (component, memberVariableName)
|
||||
<< '\n';
|
||||
|
||||
const String indent (String::repeatedString (" ", memberVariableName.length() + 13));
|
||||
|
||||
s << memberVariableName << "->setImages (false, true, "
|
||||
<< CodeHelpers::boolLiteral (doesImageKeepProportions (ib)) << ",\n"
|
||||
<< indent
|
||||
<< getImageCreationCode (ib, normalImage) << ", "
|
||||
<< CodeHelpers::floatLiteral (getImageOpacity (ib, normalImage), 3) << ", "
|
||||
<< CodeHelpers::colourToCode (getImageColour (ib, normalImage)) << ",\n"
|
||||
<< indent
|
||||
<< getImageCreationCode (ib, overImage) << ", "
|
||||
<< CodeHelpers::floatLiteral (getImageOpacity (ib, overImage), 3) << ", "
|
||||
<< CodeHelpers::colourToCode (getImageColour (ib, overImage)) << ",\n"
|
||||
<< indent
|
||||
<< getImageCreationCode (ib, downImage) << ", "
|
||||
<< CodeHelpers::floatLiteral (getImageOpacity (ib, downImage), 3) << ", "
|
||||
<< CodeHelpers::colourToCode (getImageColour (ib, downImage))
|
||||
<< ");\n";
|
||||
|
||||
code.constructorCode += s;
|
||||
}
|
||||
|
||||
static String getImageCreationCode (ImageButton* ib, const ImageRole role)
|
||||
{
|
||||
const String resName (getImageResource (ib, role));
|
||||
|
||||
if (resName.isEmpty())
|
||||
return "juce::Image()";
|
||||
|
||||
return "juce::ImageCache::getFromMemory (" + resName + ", " + resName + "Size)";
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class ImageButtonResourceProperty : public ImageResourceProperty<ImageButton>
|
||||
{
|
||||
public:
|
||||
ImageButtonResourceProperty (ComponentLayout& layout_, ImageButton* const owner_, const ImageRole role_, const String& name)
|
||||
: ImageResourceProperty<ImageButton> (*layout_.getDocument(), owner_, name, true),
|
||||
role (role_),
|
||||
layout (layout_)
|
||||
{
|
||||
}
|
||||
|
||||
void setResource (const String& newName)
|
||||
{
|
||||
setImageResource (layout, element, role, newName, true);
|
||||
}
|
||||
|
||||
String getResource() const
|
||||
{
|
||||
return getImageResource (element, role);
|
||||
}
|
||||
|
||||
private:
|
||||
const ImageRole role;
|
||||
ComponentLayout& layout;
|
||||
};
|
||||
|
||||
class SetImageResourceAction : public ComponentUndoableAction<ImageButton>
|
||||
{
|
||||
public:
|
||||
SetImageResourceAction (ImageButton* const button,
|
||||
ComponentLayout& layout_,
|
||||
const ImageRole role_,
|
||||
const String& newResource_)
|
||||
: ComponentUndoableAction<ImageButton> (button, layout_),
|
||||
newResource (newResource_),
|
||||
role (role_)
|
||||
{
|
||||
oldResource = ImageButtonHandler::getImageResource (button, role_);
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
ImageButtonHandler::setImageResource (layout, getComponent(), role, newResource, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
ImageButtonHandler::setImageResource (layout, getComponent(), role, oldResource, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
String newResource, oldResource;
|
||||
const ImageRole role;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static void setImageResource (ComponentLayout& layout, ImageButton* button, const ImageRole role, const String& newName, const bool undoable)
|
||||
{
|
||||
jassert (role < 3);
|
||||
|
||||
if (role < 3 && getImageResource (button, role) != newName)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
layout.getDocument()->perform (new SetImageResourceAction (button, layout, role, newName),
|
||||
"Change image resource");
|
||||
}
|
||||
else
|
||||
{
|
||||
button->getProperties().set ("resource" + String ((int) role), newName);
|
||||
updateButtonImages (*layout.getDocument(), button);
|
||||
layout.changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String getImageResource (ImageButton* button, const ImageRole role)
|
||||
{
|
||||
jassert (role < 3);
|
||||
return button->getProperties() ["resource" + String ((int) role)].toString();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class SetImageKeepsPropAction : public ComponentUndoableAction<ImageButton>
|
||||
{
|
||||
public:
|
||||
SetImageKeepsPropAction (ImageButton* const button,
|
||||
ComponentLayout& layout_,
|
||||
const bool newState_)
|
||||
: ComponentUndoableAction<ImageButton> (button, layout_),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = ImageButtonHandler::doesImageKeepProportions (button);
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
ImageButtonHandler::setImageKeepProportions (layout, getComponent(), newState, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
ImageButtonHandler::setImageKeepProportions (layout, getComponent(), oldState, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool newState, oldState;
|
||||
};
|
||||
|
||||
static bool doesImageKeepProportions (ImageButton* button)
|
||||
{
|
||||
return button->getProperties().getWithDefault ("keepImageProp", true);
|
||||
}
|
||||
|
||||
static void setImageKeepProportions (ComponentLayout& layout, ImageButton* button, const bool newState, const bool undoable)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
layout.perform (new SetImageKeepsPropAction (button, layout, newState), "change imagebutton proportion mode");
|
||||
}
|
||||
else
|
||||
{
|
||||
button->getProperties().set ("keepImageProp", newState);
|
||||
updateButtonImages (*layout.getDocument(), button);
|
||||
layout.changed();
|
||||
}
|
||||
}
|
||||
|
||||
class ImageButtonProportionProperty : public ComponentBooleanProperty<ImageButton>
|
||||
{
|
||||
public:
|
||||
ImageButtonProportionProperty (ComponentLayout& layout_, ImageButton* const owner_)
|
||||
: ComponentBooleanProperty<ImageButton> ("proportional", "maintain image proportions", "scale to fit",
|
||||
owner_, *layout_.getDocument()),
|
||||
layout (layout_)
|
||||
{
|
||||
}
|
||||
|
||||
void setState (bool newState)
|
||||
{
|
||||
setImageKeepProportions (layout, component, newState, true);
|
||||
}
|
||||
|
||||
bool getState() const
|
||||
{
|
||||
return doesImageKeepProportions (component);
|
||||
}
|
||||
|
||||
private:
|
||||
ComponentLayout& layout;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class SetImageOpacityAction : public ComponentUndoableAction<ImageButton>
|
||||
{
|
||||
public:
|
||||
SetImageOpacityAction (ImageButton* const button,
|
||||
ComponentLayout& layout_,
|
||||
const ImageRole role_,
|
||||
const float newState_)
|
||||
: ComponentUndoableAction<ImageButton> (button, layout_),
|
||||
role (role_),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = ImageButtonHandler::getImageOpacity (button, role_);
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
ImageButtonHandler::setImageOpacity (layout, getComponent(), role, newState, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
ImageButtonHandler::setImageOpacity (layout, getComponent(), role, oldState, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const ImageRole role;
|
||||
float newState, oldState;
|
||||
};
|
||||
|
||||
static float getImageOpacity (ImageButton* button, const ImageRole role)
|
||||
{
|
||||
return (float) button->getProperties().getWithDefault ("imageOpacity" + String ((int) role), 1.0f);
|
||||
}
|
||||
|
||||
static void setImageOpacity (ComponentLayout& layout, ImageButton* button, const ImageRole role, const float opacity, const bool undoable)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
layout.perform (new SetImageOpacityAction (button, layout, role, opacity), "change imagebutton opacity");
|
||||
}
|
||||
else
|
||||
{
|
||||
button->getProperties().set ("imageOpacity" + String ((int) role), opacity);
|
||||
updateButtonImages (*layout.getDocument(), button);
|
||||
layout.changed();
|
||||
}
|
||||
}
|
||||
|
||||
class ImageButtonOpacityProperty : public SliderPropertyComponent
|
||||
{
|
||||
public:
|
||||
ImageButtonOpacityProperty (ComponentLayout& layout_, ImageButton* const owner_,
|
||||
const String& name, const ImageRole role_)
|
||||
: SliderPropertyComponent (name, 0.0, 1.0, 0.0),
|
||||
owner (owner_),
|
||||
layout (layout_),
|
||||
role (role_)
|
||||
{
|
||||
}
|
||||
|
||||
void setValue (double newValue) override
|
||||
{
|
||||
setImageOpacity (layout, owner, role, (float) newValue, true);
|
||||
}
|
||||
|
||||
double getValue() const override
|
||||
{
|
||||
return getImageOpacity (owner, role);
|
||||
}
|
||||
|
||||
private:
|
||||
ImageButton* const owner;
|
||||
ComponentLayout& layout;
|
||||
const ImageRole role;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class SetImageColourAction : public ComponentUndoableAction<ImageButton>
|
||||
{
|
||||
public:
|
||||
SetImageColourAction (ImageButton* const button,
|
||||
ComponentLayout& layout_,
|
||||
const ImageRole role_,
|
||||
Colour newState_)
|
||||
: ComponentUndoableAction<ImageButton> (button, layout_),
|
||||
role (role_),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = ImageButtonHandler::getImageColour (button, role_);
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
ImageButtonHandler::setImageColour (layout, getComponent(), role, newState, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
ImageButtonHandler::setImageColour (layout, getComponent(), role, oldState, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const ImageRole role;
|
||||
Colour newState, oldState;
|
||||
};
|
||||
|
||||
static Colour getImageColour (ImageButton* button, const ImageRole role)
|
||||
{
|
||||
return Colour::fromString (button->getProperties().getWithDefault ("imageColour" + String ((int) role), "0").toString());
|
||||
}
|
||||
|
||||
static void setImageColour (ComponentLayout& layout, ImageButton* button,
|
||||
const ImageRole role, Colour colour, const bool undoable)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
layout.perform (new SetImageColourAction (button, layout, role, colour), "change imagebutton colour");
|
||||
}
|
||||
else
|
||||
{
|
||||
button->getProperties().set ("imageColour" + String ((int) role), colour.toString());
|
||||
updateButtonImages (*layout.getDocument(), button);
|
||||
layout.changed();
|
||||
}
|
||||
}
|
||||
|
||||
class ImageButtonColourProperty : public JucerColourPropertyComponent,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
ImageButtonColourProperty (ComponentLayout& layout_, ImageButton* const owner_,
|
||||
const String& name, const ImageRole role_)
|
||||
: JucerColourPropertyComponent (name, false),
|
||||
owner (owner_),
|
||||
layout (layout_),
|
||||
role (role_)
|
||||
{
|
||||
layout_.getDocument()->addChangeListener (this);
|
||||
}
|
||||
|
||||
~ImageButtonColourProperty() override
|
||||
{
|
||||
layout.getDocument()->removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setColour (Colour newColour) override
|
||||
{
|
||||
setImageColour (layout, owner, role, newColour, true);
|
||||
}
|
||||
|
||||
Colour getColour() const override
|
||||
{
|
||||
return getImageColour (owner, role);
|
||||
}
|
||||
|
||||
void resetToDefault() override {}
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
ImageButton* const owner;
|
||||
ComponentLayout& layout;
|
||||
const ImageRole role;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static void updateButtonImages (JucerDocument& document, ImageButton* const ib)
|
||||
{
|
||||
Image norm = document.getResources().getImageFromCache (getImageResource (ib, normalImage));
|
||||
Image over = document.getResources().getImageFromCache (getImageResource (ib, overImage));
|
||||
Image down = document.getResources().getImageFromCache (getImageResource (ib, downImage));
|
||||
|
||||
ib->setImages (false, true, doesImageKeepProportions (ib),
|
||||
norm,
|
||||
getImageOpacity (ib, normalImage),
|
||||
getImageColour (ib, normalImage),
|
||||
over,
|
||||
getImageOpacity (ib, overImage),
|
||||
getImageColour (ib, overImage),
|
||||
down,
|
||||
getImageOpacity (ib, downImage),
|
||||
getImageColour (ib, downImage));
|
||||
}
|
||||
};
|
273
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_JucerComponentHandler.h
vendored
Normal file
273
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_JucerComponentHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
||||
};
|
774
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_LabelHandler.h
vendored
Normal file
774
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_LabelHandler.h
vendored
Normal file
@ -0,0 +1,774 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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 LabelHandler : public ComponentTypeHandler
|
||||
{
|
||||
public:
|
||||
LabelHandler()
|
||||
: ComponentTypeHandler ("Label", "juce::Label", typeid (Label), 150, 24)
|
||||
{
|
||||
registerColour (juce::Label::backgroundColourId, "background", "bkgCol");
|
||||
registerColour (juce::Label::textColourId, "text", "textCol");
|
||||
registerColour (juce::Label::outlineColourId, "outline", "outlineCol");
|
||||
registerColour (juce::TextEditor::textColourId, "editor text", "edTextCol");
|
||||
registerColour (juce::TextEditor::backgroundColourId, "editor bkg", "edBkgCol");
|
||||
registerColour (juce::TextEditor::highlightColourId, "highlight", "hiliteCol");
|
||||
}
|
||||
|
||||
Component* createNewComponent (JucerDocument*) override
|
||||
{
|
||||
return new Label ("new label", "label text");
|
||||
}
|
||||
|
||||
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
|
||||
{
|
||||
Label* const l = dynamic_cast<Label*> (comp);
|
||||
|
||||
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
|
||||
e->setAttribute ("labelText", l->getText());
|
||||
|
||||
e->setAttribute ("editableSingleClick", l->isEditableOnSingleClick());
|
||||
e->setAttribute ("editableDoubleClick", l->isEditableOnDoubleClick());
|
||||
e->setAttribute ("focusDiscardsChanges", l->doesLossOfFocusDiscardChanges());
|
||||
|
||||
e->setAttribute ("fontname", l->getProperties().getWithDefault ("typefaceName", FontPropertyComponent::getDefaultFont()).toString());
|
||||
e->setAttribute ("fontsize", roundToInt (l->getFont().getHeight() * 100.0) / 100.0);
|
||||
e->setAttribute ("kerning", roundToInt (l->getFont().getExtraKerningFactor() * 1000.0) / 1000.0);
|
||||
e->setAttribute ("bold", l->getFont().isBold());
|
||||
e->setAttribute ("italic", l->getFont().isItalic());
|
||||
e->setAttribute ("justification", l->getJustificationType().getFlags());
|
||||
if (l->getFont().getTypefaceStyle() != "Regular")
|
||||
{
|
||||
e->setAttribute ("typefaceStyle", l->getFont().getTypefaceStyle());
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
|
||||
{
|
||||
Label* const l = dynamic_cast<Label*> (comp);
|
||||
|
||||
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
|
||||
return false;
|
||||
|
||||
Label defaultLabel;
|
||||
|
||||
Font font;
|
||||
font.setHeight ((float) xml.getDoubleAttribute ("fontsize", 15.0));
|
||||
font.setBold (xml.getBoolAttribute ("bold", false));
|
||||
font.setItalic (xml.getBoolAttribute ("italic", false));
|
||||
font.setExtraKerningFactor ((float) xml.getDoubleAttribute ("kerning", 0.0));
|
||||
auto fontStyle = xml.getStringAttribute ("typefaceStyle");
|
||||
if (! fontStyle.isEmpty())
|
||||
font.setTypefaceStyle (fontStyle);
|
||||
|
||||
l->setFont (font);
|
||||
|
||||
l->getProperties().set ("typefaceName", xml.getStringAttribute ("fontname", FontPropertyComponent::getDefaultFont()));
|
||||
updateLabelFont (l);
|
||||
|
||||
l->setJustificationType (Justification (xml.getIntAttribute ("justification", Justification::centred)));
|
||||
|
||||
l->setText (xml.getStringAttribute ("labelText", "Label Text"), dontSendNotification);
|
||||
|
||||
l->setEditable (xml.getBoolAttribute ("editableSingleClick", defaultLabel.isEditableOnSingleClick()),
|
||||
xml.getBoolAttribute ("editableDoubleClick", defaultLabel.isEditableOnDoubleClick()),
|
||||
xml.getBoolAttribute ("focusDiscardsChanges", defaultLabel.doesLossOfFocusDiscardChanges()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void updateLabelFont (Label* label)
|
||||
{
|
||||
Font f (label->getFont());
|
||||
f = FontPropertyComponent::applyNameToFont (label->getProperties().getWithDefault ("typefaceName", FontPropertyComponent::getDefaultFont()), f);
|
||||
label->setFont (f);
|
||||
}
|
||||
|
||||
String getCreationParameters (GeneratedCode& code, Component* component) override
|
||||
{
|
||||
Label* const l = dynamic_cast<Label*> (component);
|
||||
|
||||
return quotedString (component->getName(), false)
|
||||
+ ",\n"
|
||||
+ quotedString (l->getText(), code.shouldUseTransMacro());
|
||||
}
|
||||
|
||||
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
|
||||
{
|
||||
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
|
||||
|
||||
Label* const l = dynamic_cast<Label*> (component);
|
||||
|
||||
String s;
|
||||
|
||||
s << memberVariableName << "->setFont ("
|
||||
<< FontPropertyComponent::getCompleteFontCode (l->getFont(), l->getProperties().getWithDefault ("typefaceName", FontPropertyComponent::getDefaultFont()))
|
||||
<< ");\n"
|
||||
<< memberVariableName << "->setJustificationType ("
|
||||
<< CodeHelpers::justificationToCode (l->getJustificationType())
|
||||
<< ");\n"
|
||||
<< memberVariableName << "->setEditable ("
|
||||
<< CodeHelpers::boolLiteral (l->isEditableOnSingleClick()) << ", "
|
||||
<< CodeHelpers::boolLiteral (l->isEditableOnDoubleClick()) << ", "
|
||||
<< CodeHelpers::boolLiteral (l->doesLossOfFocusDiscardChanges()) << ");\n"
|
||||
<< getColourIntialisationCode (component, memberVariableName);
|
||||
|
||||
if (needsCallback (component))
|
||||
s << memberVariableName << "->addListener (this);\n";
|
||||
|
||||
s << '\n';
|
||||
|
||||
code.constructorCode += s;
|
||||
}
|
||||
|
||||
void fillInGeneratedCode (Component* component, GeneratedCode& code) override
|
||||
{
|
||||
ComponentTypeHandler::fillInGeneratedCode (component, code);
|
||||
|
||||
if (needsCallback (component))
|
||||
{
|
||||
String& callback = code.getCallbackCode ("public juce::Label::Listener",
|
||||
"void",
|
||||
"labelTextChanged (juce::Label* labelThatHasChanged)",
|
||||
true);
|
||||
|
||||
if (callback.trim().isNotEmpty())
|
||||
callback << "else ";
|
||||
|
||||
const String memberVariableName (code.document->getComponentLayout()->getComponentMemberVariableName (component));
|
||||
const String userCodeComment ("UserLabelCode_" + memberVariableName);
|
||||
|
||||
callback
|
||||
<< "if (labelThatHasChanged == " << memberVariableName << ".get())\n"
|
||||
<< "{\n //[" << userCodeComment << "] -- add your label text handling code here..\n //[/" << userCodeComment << "]\n}\n";
|
||||
}
|
||||
}
|
||||
|
||||
void getEditableProperties (Component* component, JucerDocument& document,
|
||||
Array<PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
|
||||
|
||||
if (multipleSelected)
|
||||
return;
|
||||
|
||||
if (auto* const l = dynamic_cast<Label*> (component))
|
||||
{
|
||||
props.add (new LabelTextProperty (l, document));
|
||||
props.add (new LabelJustificationProperty (l, document));
|
||||
props.add (new FontNameProperty (l, document));
|
||||
props.add (new FontStyleProperty (l, document));
|
||||
props.add (new FontSizeProperty (l, document));
|
||||
props.add (new FontKerningProperty (l, document));
|
||||
|
||||
props.add (new LabelEditableProperty (l, document));
|
||||
|
||||
if (l->isEditableOnDoubleClick() || l->isEditableOnSingleClick())
|
||||
props.add (new LabelLossOfFocusProperty (l, document));
|
||||
}
|
||||
|
||||
addColourProperties (component, document, props);
|
||||
}
|
||||
|
||||
static bool needsCallback (Component* label)
|
||||
{
|
||||
return ((Label*) label)->isEditableOnSingleClick()
|
||||
|| ((Label*) label)->isEditableOnDoubleClick(); // xxx should be configurable
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//==============================================================================
|
||||
class LabelTextProperty : public ComponentTextProperty <Label>
|
||||
{
|
||||
public:
|
||||
LabelTextProperty (Label* comp, JucerDocument& doc)
|
||||
: ComponentTextProperty <Label> ("text", 10000, true, comp, doc)
|
||||
{}
|
||||
|
||||
void setText (const String& newText) override
|
||||
{
|
||||
document.perform (new LabelTextChangeAction (component, *document.getComponentLayout(), newText),
|
||||
"Change Label text");
|
||||
}
|
||||
|
||||
String getText() const override
|
||||
{
|
||||
return component->getText();
|
||||
}
|
||||
|
||||
private:
|
||||
class LabelTextChangeAction : public ComponentUndoableAction <Label>
|
||||
{
|
||||
public:
|
||||
LabelTextChangeAction (Label* const comp, ComponentLayout& l, const String& newState_)
|
||||
: ComponentUndoableAction <Label> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->getText();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setText (newState, dontSendNotification);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setText (oldState, dontSendNotification);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
String newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class LabelEditableProperty : public ComponentChoiceProperty <Label>
|
||||
{
|
||||
public:
|
||||
LabelEditableProperty (Label* comp, JucerDocument& doc)
|
||||
: ComponentChoiceProperty <Label> ("editing", comp, doc)
|
||||
{
|
||||
choices.add ("read-only");
|
||||
choices.add ("edit on single-click");
|
||||
choices.add ("edit on double-click");
|
||||
}
|
||||
|
||||
void setIndex (int newIndex)
|
||||
{
|
||||
document.perform (new LabelEditableChangeAction (component, *document.getComponentLayout(), newIndex),
|
||||
"Change Label editability");
|
||||
}
|
||||
|
||||
int getIndex() const
|
||||
{
|
||||
return component->isEditableOnSingleClick()
|
||||
? 1
|
||||
: (component->isEditableOnDoubleClick() ? 2 : 0);
|
||||
}
|
||||
|
||||
private:
|
||||
class LabelEditableChangeAction : public ComponentUndoableAction <Label>
|
||||
{
|
||||
public:
|
||||
LabelEditableChangeAction (Label* const comp, ComponentLayout& l, const int newState_)
|
||||
: ComponentUndoableAction <Label> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->isEditableOnSingleClick()
|
||||
? 1
|
||||
: (comp->isEditableOnDoubleClick() ? 2 : 0);
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setEditable (newState == 1, newState >= 1, getComponent()->doesLossOfFocusDiscardChanges());
|
||||
changed();
|
||||
layout.getSelectedSet().changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setEditable (oldState == 1, oldState >= 1, getComponent()->doesLossOfFocusDiscardChanges());
|
||||
changed();
|
||||
layout.getSelectedSet().changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
int newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class LabelLossOfFocusProperty : public ComponentChoiceProperty <Label>
|
||||
{
|
||||
public:
|
||||
LabelLossOfFocusProperty (Label* comp, JucerDocument& doc)
|
||||
: ComponentChoiceProperty <Label> ("focus", comp, doc)
|
||||
{
|
||||
choices.add ("loss of focus discards changes");
|
||||
choices.add ("loss of focus commits changes");
|
||||
}
|
||||
|
||||
void setIndex (int newIndex)
|
||||
{
|
||||
document.perform (new LabelFocusLossChangeAction (component, *document.getComponentLayout(), newIndex == 0),
|
||||
"Change Label focus behaviour");
|
||||
}
|
||||
|
||||
int getIndex() const
|
||||
{
|
||||
return component->doesLossOfFocusDiscardChanges() ? 0 : 1;
|
||||
}
|
||||
|
||||
private:
|
||||
class LabelFocusLossChangeAction : public ComponentUndoableAction <Label>
|
||||
{
|
||||
public:
|
||||
LabelFocusLossChangeAction (Label* const comp, ComponentLayout& l, const bool newState_)
|
||||
: ComponentUndoableAction <Label> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->doesLossOfFocusDiscardChanges();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setEditable (getComponent()->isEditableOnSingleClick(),
|
||||
getComponent()->isEditableOnDoubleClick(),
|
||||
newState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setEditable (getComponent()->isEditableOnSingleClick(),
|
||||
getComponent()->isEditableOnDoubleClick(),
|
||||
oldState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class LabelJustificationProperty : public JustificationProperty,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
LabelJustificationProperty (Label* const label_, JucerDocument& doc)
|
||||
: JustificationProperty ("layout", false),
|
||||
label (label_),
|
||||
document (doc)
|
||||
{
|
||||
document.addChangeListener (this);
|
||||
}
|
||||
|
||||
~LabelJustificationProperty() override
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setJustification (Justification newJustification) override
|
||||
{
|
||||
document.perform (new LabelJustifyChangeAction (label, *document.getComponentLayout(), newJustification),
|
||||
"Change Label justification");
|
||||
}
|
||||
|
||||
Justification getJustification() const override
|
||||
{
|
||||
return label->getJustificationType();
|
||||
}
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override { refresh(); }
|
||||
|
||||
Label* const label;
|
||||
JucerDocument& document;
|
||||
|
||||
class LabelJustifyChangeAction : public ComponentUndoableAction <Label>
|
||||
{
|
||||
public:
|
||||
LabelJustifyChangeAction (Label* const comp, ComponentLayout& l, Justification newState_)
|
||||
: ComponentUndoableAction <Label> (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 FontNameProperty : public FontPropertyComponent,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
FontNameProperty (Label* const label_, JucerDocument& doc)
|
||||
: FontPropertyComponent ("font"),
|
||||
label (label_),
|
||||
document (doc)
|
||||
{
|
||||
document.addChangeListener (this);
|
||||
}
|
||||
|
||||
~FontNameProperty() override
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setTypefaceName (const String& newFontName) override
|
||||
{
|
||||
document.perform (new FontNameChangeAction (label, *document.getComponentLayout(), newFontName),
|
||||
"Change Label typeface");
|
||||
}
|
||||
|
||||
String getTypefaceName() const override
|
||||
{
|
||||
return label->getProperties().getWithDefault ("typefaceName", FontPropertyComponent::getDefaultFont());
|
||||
}
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override { refresh(); }
|
||||
|
||||
Label* const label;
|
||||
JucerDocument& document;
|
||||
|
||||
class FontNameChangeAction : public ComponentUndoableAction <Label>
|
||||
{
|
||||
public:
|
||||
FontNameChangeAction (Label* const comp, ComponentLayout& l, const String& newState_)
|
||||
: ComponentUndoableAction <Label> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->getProperties().getWithDefault ("typefaceName", FontPropertyComponent::getDefaultFont());
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->getProperties().set ("typefaceName", newState);
|
||||
LabelHandler::updateLabelFont (getComponent());
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->getProperties().set ("typefaceName", oldState);
|
||||
LabelHandler::updateLabelFont (getComponent());
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
String newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class FontSizeProperty : public SliderPropertyComponent,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
FontSizeProperty (Label* const label_, JucerDocument& doc)
|
||||
: SliderPropertyComponent ("size", 1.0, 250.0, 0.1, 0.3),
|
||||
label (label_),
|
||||
document (doc)
|
||||
{
|
||||
document.addChangeListener (this);
|
||||
}
|
||||
|
||||
~FontSizeProperty() override
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setValue (double newValue) override
|
||||
{
|
||||
document.getUndoManager().undoCurrentTransactionOnly();
|
||||
|
||||
document.perform (new FontSizeChangeAction (label, *document.getComponentLayout(), (float) newValue),
|
||||
"Change Label font size");
|
||||
}
|
||||
|
||||
double getValue() const override
|
||||
{
|
||||
return label->getFont().getHeight();
|
||||
}
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override { refresh(); }
|
||||
|
||||
Label* const label;
|
||||
JucerDocument& document;
|
||||
|
||||
class FontSizeChangeAction : public ComponentUndoableAction <Label>
|
||||
{
|
||||
public:
|
||||
FontSizeChangeAction (Label* const comp, ComponentLayout& l, const float newState_)
|
||||
: ComponentUndoableAction <Label> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->getFont().getHeight();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
Font f (getComponent()->getFont());
|
||||
f.setHeight ((float) newState);
|
||||
getComponent()->setFont (f);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
Font f (getComponent()->getFont());
|
||||
f.setHeight ((float) oldState);
|
||||
getComponent()->setFont (f);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
float newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class FontStyleProperty : public ChoicePropertyComponent,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
FontStyleProperty (Label* const label_, JucerDocument& doc)
|
||||
: ChoicePropertyComponent ("style"),
|
||||
label (label_),
|
||||
document (doc)
|
||||
{
|
||||
document.addChangeListener (this);
|
||||
|
||||
updateStylesList (label->getFont());
|
||||
}
|
||||
|
||||
~FontStyleProperty() override
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void updateStylesList (const Font& newFont)
|
||||
{
|
||||
if (getNumChildComponents() > 0)
|
||||
{
|
||||
if (auto cb = dynamic_cast<ComboBox*> (getChildComponent (0)))
|
||||
cb->clear();
|
||||
|
||||
getChildComponent (0)->setVisible (false);
|
||||
removeAllChildren();
|
||||
}
|
||||
|
||||
choices.clear();
|
||||
|
||||
choices.add ("Regular");
|
||||
choices.add ("Bold");
|
||||
choices.add ("Italic");
|
||||
choices.add ("Bold Italic");
|
||||
|
||||
choices.mergeArray (newFont.getAvailableStyles());
|
||||
refresh();
|
||||
}
|
||||
|
||||
void setIndex (int newIndex) override
|
||||
{
|
||||
Font f (label->getFont());
|
||||
|
||||
if (f.getAvailableStyles().contains (choices[newIndex]))
|
||||
{
|
||||
f.setBold (false);
|
||||
f.setItalic (false);
|
||||
f.setTypefaceStyle (choices[newIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
f.setTypefaceStyle ("Regular");
|
||||
f.setBold (newIndex == 1 || newIndex == 3);
|
||||
f.setItalic (newIndex == 2 || newIndex == 3);
|
||||
}
|
||||
|
||||
document.perform (new FontStyleChangeAction (label, *document.getComponentLayout(), f),
|
||||
"Change Label font style");
|
||||
}
|
||||
|
||||
int getIndex() const override
|
||||
{
|
||||
auto f = label->getFont();
|
||||
|
||||
const auto typefaceIndex = choices.indexOf (f.getTypefaceStyle());
|
||||
if (typefaceIndex == -1)
|
||||
{
|
||||
if (f.isBold() && f.isItalic())
|
||||
return 3;
|
||||
else if (f.isBold())
|
||||
return 1;
|
||||
else if (f.isItalic())
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return typefaceIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
updateStylesList (label->getFont());
|
||||
}
|
||||
|
||||
Label* const label;
|
||||
JucerDocument& document;
|
||||
|
||||
class FontStyleChangeAction : public ComponentUndoableAction <Label>
|
||||
{
|
||||
public:
|
||||
FontStyleChangeAction (Label* const comp, ComponentLayout& l, const Font& newState_)
|
||||
: ComponentUndoableAction <Label> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->getFont();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setFont (newState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setFont (oldState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
Font newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class FontKerningProperty : public SliderPropertyComponent,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
FontKerningProperty (Label* const label_, JucerDocument& doc)
|
||||
: SliderPropertyComponent ("kerning", -0.5, 0.5, 0.001),
|
||||
label (label_),
|
||||
document (doc)
|
||||
{
|
||||
document.addChangeListener (this);
|
||||
}
|
||||
|
||||
~FontKerningProperty() override
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setValue (double newValue) override
|
||||
{
|
||||
document.getUndoManager().undoCurrentTransactionOnly();
|
||||
|
||||
document.perform (new FontKerningChangeAction (label, *document.getComponentLayout(), (float) newValue),
|
||||
"Change Label font kerning");
|
||||
}
|
||||
|
||||
double getValue() const override
|
||||
{
|
||||
return label->getFont().getExtraKerningFactor();
|
||||
}
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
Label* const label;
|
||||
JucerDocument& document;
|
||||
|
||||
class FontKerningChangeAction : public ComponentUndoableAction <Label>
|
||||
{
|
||||
public:
|
||||
FontKerningChangeAction (Label* const comp, ComponentLayout& l, const float newState_)
|
||||
: ComponentUndoableAction <Label> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->getFont().getExtraKerningFactor();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
Font f (getComponent()->getFont());
|
||||
f.setExtraKerningFactor ((float) newState);
|
||||
getComponent()->setFont (f);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
Font f (getComponent()->getFont());
|
||||
f.setExtraKerningFactor ((float) oldState);
|
||||
getComponent()->setFont (f);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
float newState, oldState;
|
||||
};
|
||||
};
|
||||
};
|
709
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_SliderHandler.h
vendored
Normal file
709
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_SliderHandler.h
vendored
Normal file
@ -0,0 +1,709 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
|
||||
|
||||
//==============================================================================
|
||||
static const Slider::SliderStyle sliderStyleTypes[] =
|
||||
{
|
||||
Slider::LinearHorizontal,
|
||||
Slider::LinearVertical,
|
||||
Slider::LinearBar,
|
||||
Slider::LinearBarVertical,
|
||||
Slider::Rotary,
|
||||
Slider::RotaryHorizontalDrag,
|
||||
Slider::RotaryVerticalDrag,
|
||||
Slider::RotaryHorizontalVerticalDrag,
|
||||
Slider::IncDecButtons,
|
||||
Slider::TwoValueHorizontal,
|
||||
Slider::TwoValueVertical,
|
||||
Slider::ThreeValueHorizontal,
|
||||
Slider::ThreeValueVertical
|
||||
};
|
||||
|
||||
static const Slider::TextEntryBoxPosition sliderTextBoxPositions[] =
|
||||
{
|
||||
Slider::NoTextBox,
|
||||
Slider::TextBoxLeft,
|
||||
Slider::TextBoxRight,
|
||||
Slider::TextBoxAbove,
|
||||
Slider::TextBoxBelow
|
||||
};
|
||||
|
||||
|
||||
struct SliderHandler : public ComponentTypeHandler
|
||||
{
|
||||
SliderHandler()
|
||||
: ComponentTypeHandler ("Slider", "juce::Slider", typeid (Slider), 150, 24)
|
||||
{
|
||||
registerColour (juce::Slider::backgroundColourId, "background", "bkgcol");
|
||||
registerColour (juce::Slider::thumbColourId, "thumb", "thumbcol");
|
||||
registerColour (juce::Slider::trackColourId, "track", "trackcol");
|
||||
registerColour (juce::Slider::rotarySliderFillColourId, "rotary fill", "rotarysliderfill");
|
||||
registerColour (juce::Slider::rotarySliderOutlineColourId, "rotary outln", "rotaryslideroutline");
|
||||
registerColour (juce::Slider::textBoxTextColourId, "textbox text", "textboxtext");
|
||||
registerColour (juce::Slider::textBoxBackgroundColourId, "textbox bkgd", "textboxbkgd");
|
||||
registerColour (juce::Slider::textBoxHighlightColourId, "textbox highlt", "textboxhighlight");
|
||||
registerColour (juce::Slider::textBoxOutlineColourId, "textbox outln", "textboxoutline");
|
||||
}
|
||||
|
||||
Component* createNewComponent (JucerDocument*) override
|
||||
{
|
||||
return new Slider ("new slider");
|
||||
}
|
||||
|
||||
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
|
||||
{
|
||||
XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
|
||||
|
||||
Slider* s = dynamic_cast<Slider*> (comp);
|
||||
e->setAttribute ("min", s->getMinimum());
|
||||
e->setAttribute ("max", s->getMaximum());
|
||||
e->setAttribute ("int", s->getInterval());
|
||||
e->setAttribute ("style", sliderStyleToString (s->getSliderStyle()));
|
||||
e->setAttribute ("textBoxPos", textBoxPosToString (s->getTextBoxPosition()));
|
||||
e->setAttribute ("textBoxEditable", s->isTextBoxEditable());
|
||||
e->setAttribute ("textBoxWidth", s->getTextBoxWidth());
|
||||
e->setAttribute ("textBoxHeight", s->getTextBoxHeight());
|
||||
e->setAttribute ("skewFactor", s->getSkewFactor());
|
||||
e->setAttribute ("needsCallback", needsSliderListener (s));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
|
||||
{
|
||||
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
|
||||
return false;
|
||||
|
||||
Slider* const s = dynamic_cast<Slider*> (comp);
|
||||
|
||||
s->setRange (xml.getDoubleAttribute ("min", 0.0),
|
||||
xml.getDoubleAttribute ("max", 10.0),
|
||||
xml.getDoubleAttribute ("int", 0.0));
|
||||
|
||||
s->setSliderStyle (sliderStringToStyle (xml.getStringAttribute ("style", "LinearHorizontal")));
|
||||
|
||||
s->setTextBoxStyle (stringToTextBoxPos (xml.getStringAttribute ("textBoxPos", "TextBoxLeft")),
|
||||
! xml.getBoolAttribute ("textBoxEditable", true),
|
||||
xml.getIntAttribute ("textBoxWidth", 80),
|
||||
xml.getIntAttribute ("textBoxHeight", 20));
|
||||
|
||||
s->setSkewFactor (xml.getDoubleAttribute ("skewFactor", 1.0));
|
||||
|
||||
setNeedsSliderListener (s, xml.getBoolAttribute ("needsCallback", true));
|
||||
|
||||
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);
|
||||
|
||||
Slider* const s = dynamic_cast<Slider*> (component);
|
||||
|
||||
String r;
|
||||
r << memberVariableName << "->setRange ("
|
||||
<< s->getMinimum() << ", " << s->getMaximum() << ", " << s->getInterval()
|
||||
<< ");\n"
|
||||
<< memberVariableName << "->setSliderStyle (juce::Slider::"
|
||||
<< sliderStyleToString (s->getSliderStyle()) << ");\n"
|
||||
<< memberVariableName << "->setTextBoxStyle (juce::Slider::"
|
||||
<< textBoxPosToString (s->getTextBoxPosition())
|
||||
<< ", " << CodeHelpers::boolLiteral (! s->isTextBoxEditable())
|
||||
<< ", " << s->getTextBoxWidth() << ", " << s->getTextBoxHeight() << ");\n"
|
||||
<< getColourIntialisationCode (component, memberVariableName);
|
||||
|
||||
if (needsSliderListener (component))
|
||||
r << memberVariableName << "->addListener (this);\n";
|
||||
|
||||
if (s->getSkewFactor() != 1.0)
|
||||
r << memberVariableName << "->setSkewFactor (" << s->getSkewFactor() << ");\n";
|
||||
|
||||
r << '\n';
|
||||
code.constructorCode += r;
|
||||
}
|
||||
|
||||
void fillInGeneratedCode (Component* component, GeneratedCode& code) override
|
||||
{
|
||||
ComponentTypeHandler::fillInGeneratedCode (component, code);
|
||||
|
||||
if (needsSliderListener (component))
|
||||
{
|
||||
String& callback = code.getCallbackCode ("public juce::Slider::Listener",
|
||||
"void",
|
||||
"sliderValueChanged (juce::Slider* sliderThatWasMoved)",
|
||||
true);
|
||||
|
||||
if (callback.isNotEmpty())
|
||||
callback << "else ";
|
||||
|
||||
const String memberVariableName (code.document->getComponentLayout()->getComponentMemberVariableName (component));
|
||||
const String userCodeComment ("UserSliderCode_" + memberVariableName);
|
||||
|
||||
callback
|
||||
<< "if (sliderThatWasMoved == " << memberVariableName << ".get())\n"
|
||||
<< "{\n //[" << userCodeComment << "] -- add your slider handling code here..\n //[/" << userCodeComment << "]\n}\n";
|
||||
}
|
||||
}
|
||||
|
||||
void getEditableProperties (Component* component, JucerDocument& document,
|
||||
Array<PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
|
||||
|
||||
if (multipleSelected)
|
||||
return;
|
||||
|
||||
if (auto* s = dynamic_cast<Slider*> (component))
|
||||
{
|
||||
props.add (new SliderRangeProperty (s, document, "minimum", 0));
|
||||
props.add (new SliderRangeProperty (s, document, "maximum", 1));
|
||||
props.add (new SliderRangeProperty (s, document, "interval", 2));
|
||||
props.add (new SliderTypeProperty (s, document));
|
||||
props.add (new SliderTextboxProperty (s, document));
|
||||
props.add (new SliderTextboxEditableProperty (s, document));
|
||||
props.add (new SliderTextboxSizeProperty (s, document, true));
|
||||
props.add (new SliderTextboxSizeProperty (s, document, false));
|
||||
props.add (new SliderSkewProperty (s, document));
|
||||
props.add (new SliderCallbackProperty (s, document));
|
||||
}
|
||||
|
||||
addColourProperties (component, document, props);
|
||||
}
|
||||
|
||||
static bool needsSliderListener (Component* slider)
|
||||
{
|
||||
return slider->getProperties().getWithDefault ("generateListenerCallback", true);
|
||||
}
|
||||
|
||||
static void setNeedsSliderListener (Component* slider, bool shouldDoCallback)
|
||||
{
|
||||
slider->getProperties().set ("generateListenerCallback", shouldDoCallback);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
struct SliderTypeProperty : public ComponentChoiceProperty<Slider>
|
||||
{
|
||||
SliderTypeProperty (Slider* slider, JucerDocument& doc)
|
||||
: ComponentChoiceProperty<Slider> ("type", slider, doc)
|
||||
{
|
||||
choices.add ("Linear Horizontal");
|
||||
choices.add ("Linear Vertical");
|
||||
choices.add ("Linear Bar Horizontal");
|
||||
choices.add ("Linear Bar Vertical");
|
||||
choices.add ("Rotary");
|
||||
choices.add ("Rotary HorizontalDrag");
|
||||
choices.add ("Rotary VerticalDrag");
|
||||
choices.add ("Rotary HorizontalVerticalDrag");
|
||||
choices.add ("Inc/Dec Buttons");
|
||||
choices.add ("Two Value Horizontal");
|
||||
choices.add ("Two Value Vertical");
|
||||
choices.add ("Three Value Horizontal");
|
||||
choices.add ("Three Value Vertical");
|
||||
}
|
||||
|
||||
void setIndex (int newIndex) override
|
||||
{
|
||||
if (newIndex >= 0 && newIndex < numElementsInArray (sliderStyleTypes))
|
||||
document.perform (new SliderTypeChangeAction (component, *document.getComponentLayout(),
|
||||
sliderStyleTypes[newIndex]),
|
||||
"Change Slider style");
|
||||
}
|
||||
|
||||
int getIndex() const override
|
||||
{
|
||||
for (int i = 0; i < numElementsInArray (sliderStyleTypes); ++i)
|
||||
if (sliderStyleTypes[i] == dynamic_cast<Slider*> (component)->getSliderStyle())
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private:
|
||||
struct SliderTypeChangeAction : public ComponentUndoableAction<Slider>
|
||||
{
|
||||
SliderTypeChangeAction (Slider* comp, ComponentLayout& l, Slider::SliderStyle newState_)
|
||||
: ComponentUndoableAction<Slider> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->getSliderStyle();
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setSliderStyle (newState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setSliderStyle (oldState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
Slider::SliderStyle newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct SliderTextboxProperty : public ComponentChoiceProperty<Slider>
|
||||
{
|
||||
SliderTextboxProperty (Slider* slider, JucerDocument& doc)
|
||||
: ComponentChoiceProperty<Slider> ("text position", slider, doc)
|
||||
{
|
||||
choices.add ("No text box");
|
||||
choices.add ("Text box on left");
|
||||
choices.add ("Text box on right");
|
||||
choices.add ("Text box above");
|
||||
choices.add ("Text box below");
|
||||
}
|
||||
|
||||
void setIndex (int newIndex) override
|
||||
{
|
||||
if (newIndex >= 0 && newIndex < numElementsInArray (sliderTextBoxPositions))
|
||||
document.perform (new SliderTextBoxChangeAction (component, *document.getComponentLayout(),
|
||||
sliderTextBoxPositions[newIndex]),
|
||||
"Change Slider textbox");
|
||||
}
|
||||
|
||||
int getIndex() const override
|
||||
{
|
||||
for (int i = 0; i < numElementsInArray (sliderTextBoxPositions); ++i)
|
||||
if (sliderTextBoxPositions[i] == component->getTextBoxPosition())
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private:
|
||||
struct SliderTextBoxChangeAction : public ComponentUndoableAction<Slider>
|
||||
{
|
||||
SliderTextBoxChangeAction (Slider* comp, ComponentLayout& l, Slider::TextEntryBoxPosition newState_)
|
||||
: ComponentUndoableAction<Slider> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->getTextBoxPosition();
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setTextBoxStyle (newState,
|
||||
! getComponent()->isTextBoxEditable(),
|
||||
getComponent()->getTextBoxWidth(),
|
||||
getComponent()->getTextBoxHeight());
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setTextBoxStyle (oldState,
|
||||
! getComponent()->isTextBoxEditable(),
|
||||
getComponent()->getTextBoxWidth(),
|
||||
getComponent()->getTextBoxHeight());
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
Slider::TextEntryBoxPosition newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct SliderTextboxEditableProperty : public ComponentBooleanProperty<Slider>
|
||||
{
|
||||
SliderTextboxEditableProperty (Slider* slider, JucerDocument& doc)
|
||||
: ComponentBooleanProperty<Slider> ("text box mode", "Editable", "Editable", slider, doc)
|
||||
{
|
||||
}
|
||||
|
||||
void setState (bool newState) override
|
||||
{
|
||||
document.perform (new SliderEditableChangeAction (component, *document.getComponentLayout(), newState),
|
||||
"Change Slider editability");
|
||||
}
|
||||
|
||||
bool getState() const override
|
||||
{
|
||||
return component->isTextBoxEditable();
|
||||
}
|
||||
|
||||
private:
|
||||
struct SliderEditableChangeAction : public ComponentUndoableAction<Slider>
|
||||
{
|
||||
SliderEditableChangeAction (Slider* const comp, ComponentLayout& l, bool newState_)
|
||||
: ComponentUndoableAction<Slider> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->isTextBoxEditable();
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setTextBoxIsEditable (newState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setTextBoxIsEditable (oldState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct SliderCallbackProperty : public ComponentBooleanProperty<Slider>
|
||||
{
|
||||
SliderCallbackProperty (Slider* s, JucerDocument& doc)
|
||||
: ComponentBooleanProperty<Slider> ("callback", "Generate SliderListener",
|
||||
"Generate SliderListener", s, doc)
|
||||
{
|
||||
}
|
||||
|
||||
void setState (bool newState) override
|
||||
{
|
||||
document.perform (new SliderCallbackChangeAction (component, *document.getComponentLayout(), newState),
|
||||
"Change button callback");
|
||||
}
|
||||
|
||||
bool getState() const override { return needsSliderListener (component); }
|
||||
|
||||
struct SliderCallbackChangeAction : public ComponentUndoableAction<Slider>
|
||||
{
|
||||
SliderCallbackChangeAction (Slider* comp, ComponentLayout& l, bool newState_)
|
||||
: ComponentUndoableAction<Slider> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = needsSliderListener (comp);
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
setNeedsSliderListener (getComponent(), newState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
setNeedsSliderListener (getComponent(), oldState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct SliderTextboxSizeProperty : public ComponentTextProperty<Slider>
|
||||
{
|
||||
SliderTextboxSizeProperty (Slider* slider, JucerDocument& doc, bool isWidth_)
|
||||
: ComponentTextProperty<Slider> (isWidth_ ? "text box width" : "text box height",
|
||||
12, false, slider, doc),
|
||||
isWidth (isWidth_)
|
||||
{
|
||||
}
|
||||
|
||||
void setText (const String& newText) override
|
||||
{
|
||||
document.perform (new SliderBoxSizeChangeAction (component, *document.getComponentLayout(), isWidth, newText.getIntValue()),
|
||||
"Change Slider textbox size");
|
||||
}
|
||||
|
||||
String getText() const override
|
||||
{
|
||||
return String (isWidth ? component->getTextBoxWidth()
|
||||
: component->getTextBoxHeight());
|
||||
}
|
||||
|
||||
private:
|
||||
const bool isWidth;
|
||||
|
||||
struct SliderBoxSizeChangeAction : public ComponentUndoableAction<Slider>
|
||||
{
|
||||
SliderBoxSizeChangeAction (Slider* const comp, ComponentLayout& l, bool isWidth_, int newSize_)
|
||||
: ComponentUndoableAction<Slider> (comp, l),
|
||||
isWidth (isWidth_),
|
||||
newSize (newSize_)
|
||||
{
|
||||
oldSize = isWidth ? comp->getTextBoxWidth()
|
||||
: comp->getTextBoxHeight();
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
Slider& c = *getComponent();
|
||||
|
||||
if (isWidth)
|
||||
c.setTextBoxStyle (c.getTextBoxPosition(),
|
||||
! c.isTextBoxEditable(),
|
||||
newSize,
|
||||
c.getTextBoxHeight());
|
||||
else
|
||||
c.setTextBoxStyle (c.getTextBoxPosition(),
|
||||
! c.isTextBoxEditable(),
|
||||
c.getTextBoxWidth(),
|
||||
newSize);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
Slider& c = *getComponent();
|
||||
|
||||
if (isWidth)
|
||||
c.setTextBoxStyle (c.getTextBoxPosition(),
|
||||
! c.isTextBoxEditable(),
|
||||
oldSize,
|
||||
c.getTextBoxHeight());
|
||||
else
|
||||
c.setTextBoxStyle (c.getTextBoxPosition(),
|
||||
! c.isTextBoxEditable(),
|
||||
c.getTextBoxWidth(),
|
||||
oldSize);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isWidth;
|
||||
int newSize, oldSize;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct SliderRangeProperty : public ComponentTextProperty<Slider>
|
||||
{
|
||||
SliderRangeProperty (Slider* slider, JucerDocument& doc,
|
||||
const String& name, int rangeParam_)
|
||||
: ComponentTextProperty<Slider> (name, 15, false, slider, doc),
|
||||
rangeParam (rangeParam_)
|
||||
{
|
||||
}
|
||||
|
||||
void setText (const String& newText) override
|
||||
{
|
||||
double state [3];
|
||||
state [0] = component->getMinimum();
|
||||
state [1] = component->getMaximum();
|
||||
state [2] = component->getInterval();
|
||||
|
||||
state [rangeParam] = newText.getDoubleValue();
|
||||
|
||||
document.perform (new SliderRangeChangeAction (component, *document.getComponentLayout(), state),
|
||||
"Change Slider range");
|
||||
}
|
||||
|
||||
String getText() const override
|
||||
{
|
||||
if (auto* s = dynamic_cast<Slider*> (component))
|
||||
{
|
||||
switch (rangeParam)
|
||||
{
|
||||
case 0: return String (s->getMinimum());
|
||||
case 1: return String (s->getMaximum());
|
||||
case 2: return String (s->getInterval());
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
const int rangeParam;
|
||||
|
||||
struct SliderRangeChangeAction : public ComponentUndoableAction<Slider>
|
||||
{
|
||||
SliderRangeChangeAction (Slider* comp, ComponentLayout& l, const double newState_[3])
|
||||
: ComponentUndoableAction<Slider> (comp, l)
|
||||
{
|
||||
newState[0] = newState_ [0];
|
||||
newState[1] = newState_ [1];
|
||||
newState[2] = newState_ [2];
|
||||
|
||||
oldState[0] = comp->getMinimum();
|
||||
oldState[1] = comp->getMaximum();
|
||||
oldState[2] = comp->getInterval();
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setRange (newState[0], newState[1], newState[2]);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setRange (oldState[0], oldState[1], oldState[2]);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
double newState[3], oldState[3];
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct SliderSkewProperty : public ComponentTextProperty<Slider>
|
||||
{
|
||||
SliderSkewProperty (Slider* slider, JucerDocument& doc)
|
||||
: ComponentTextProperty<Slider> ("skew factor", 12, false, slider, doc)
|
||||
{
|
||||
}
|
||||
|
||||
void setText (const String& newText) override
|
||||
{
|
||||
const double skew = jlimit (0.001, 1000.0, newText.getDoubleValue());
|
||||
|
||||
document.perform (new SliderSkewChangeAction (component, *document.getComponentLayout(), skew),
|
||||
"Change Slider skew");
|
||||
}
|
||||
|
||||
String getText() const override
|
||||
{
|
||||
if (auto* s = dynamic_cast<Slider*> (component))
|
||||
return String (s->getSkewFactor());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
struct SliderSkewChangeAction : public ComponentUndoableAction<Slider>
|
||||
{
|
||||
SliderSkewChangeAction (Slider* comp, ComponentLayout& l, double newValue_)
|
||||
: ComponentUndoableAction<Slider> (comp, l)
|
||||
{
|
||||
newValue = newValue_;
|
||||
oldValue = comp->getSkewFactor();
|
||||
}
|
||||
|
||||
bool perform() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setSkewFactor (newValue);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo() override
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setSkewFactor (oldValue);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
double newValue, oldValue;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static String sliderStyleToString (Slider::SliderStyle style)
|
||||
{
|
||||
switch (style)
|
||||
{
|
||||
case Slider::LinearHorizontal: return "LinearHorizontal";
|
||||
case Slider::LinearVertical: return "LinearVertical";
|
||||
case Slider::LinearBar: return "LinearBar";
|
||||
case Slider::LinearBarVertical: return "LinearBarVertical";
|
||||
case Slider::Rotary: return "Rotary";
|
||||
case Slider::RotaryHorizontalDrag: return "RotaryHorizontalDrag";
|
||||
case Slider::RotaryVerticalDrag: return "RotaryVerticalDrag";
|
||||
case Slider::RotaryHorizontalVerticalDrag: return "RotaryHorizontalVerticalDrag";
|
||||
case Slider::IncDecButtons: return "IncDecButtons";
|
||||
case Slider::TwoValueHorizontal: return "TwoValueHorizontal";
|
||||
case Slider::TwoValueVertical: return "TwoValueVertical";
|
||||
case Slider::ThreeValueHorizontal: return "ThreeValueHorizontal";
|
||||
case Slider::ThreeValueVertical: return "ThreeValueVertical";
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static Slider::SliderStyle sliderStringToStyle (const String& s)
|
||||
{
|
||||
for (int i = 0; i < numElementsInArray (sliderStyleTypes); ++i)
|
||||
if (s == sliderStyleToString (sliderStyleTypes[i]))
|
||||
return sliderStyleTypes[i];
|
||||
|
||||
jassertfalse;
|
||||
return Slider::LinearHorizontal;
|
||||
}
|
||||
|
||||
static String textBoxPosToString (const Slider::TextEntryBoxPosition pos)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
case Slider::NoTextBox: return "NoTextBox";
|
||||
case Slider::TextBoxLeft: return "TextBoxLeft";
|
||||
case Slider::TextBoxRight: return "TextBoxRight";
|
||||
case Slider::TextBoxAbove: return "TextBoxAbove";
|
||||
case Slider::TextBoxBelow: return "TextBoxBelow";
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static Slider::TextEntryBoxPosition stringToTextBoxPos (const String& s)
|
||||
{
|
||||
for (int i = 0; i < numElementsInArray (sliderTextBoxPositions); ++i)
|
||||
if (s == textBoxPosToString (sliderTextBoxPositions[i]))
|
||||
return sliderTextBoxPositions[i];
|
||||
|
||||
jassertfalse;
|
||||
return Slider::TextBoxLeft;
|
||||
}
|
||||
};
|
1195
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_TabbedComponentHandler.h
vendored
Normal file
1195
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_TabbedComponentHandler.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
79
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_TextButtonHandler.h
vendored
Normal file
79
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_TextButtonHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
}
|
||||
};
|
433
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_TextEditorHandler.h
vendored
Normal file
433
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_TextEditorHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
||||
};
|
146
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ToggleButtonHandler.h
vendored
Normal file
146
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ToggleButtonHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
||||
};
|
265
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_TreeViewHandler.h
vendored
Normal file
265
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_TreeViewHandler.h
vendored
Normal file
@ -0,0 +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;
|
||||
};
|
||||
};
|
||||
};
|
666
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ViewportHandler.h
vendored
Normal file
666
deps/juce/extras/Projucer/Source/ComponentEditor/Components/jucer_ViewportHandler.h
vendored
Normal file
@ -0,0 +1,666 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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 ViewportHandler : public ComponentTypeHandler
|
||||
{
|
||||
public:
|
||||
ViewportHandler()
|
||||
: ComponentTypeHandler ("Viewport", "juce::Viewport", typeid (UpdatingViewport), 150, 150)
|
||||
{}
|
||||
|
||||
Component* createNewComponent (JucerDocument*) override
|
||||
{
|
||||
Viewport* const v = new UpdatingViewport ("new viewport");
|
||||
v->setViewedComponent (new ViewportDemoContentComp());
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
|
||||
{
|
||||
Viewport* const v = dynamic_cast<Viewport*> (comp);
|
||||
XmlElement* const e = ComponentTypeHandler::createXmlFor (comp, layout);
|
||||
|
||||
e->setAttribute ("vscroll", v->isVerticalScrollBarShown());
|
||||
e->setAttribute ("hscroll", v->isHorizontalScrollBarShown());
|
||||
e->setAttribute ("scrollbarThickness", v->getScrollBarThickness());
|
||||
|
||||
e->setAttribute ("contentType", getViewportContentType (v));
|
||||
e->setAttribute ("jucerFile", getViewportJucerComponentFile (v));
|
||||
e->setAttribute ("contentClass", getViewportGenericComponentClass (v));
|
||||
e->setAttribute ("constructorParams", getViewportConstructorParams (v));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
|
||||
{
|
||||
if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
|
||||
return false;
|
||||
|
||||
Viewport defaultViewport;
|
||||
Viewport* const v = dynamic_cast<Viewport*> (comp);
|
||||
v->setScrollBarsShown (xml.getBoolAttribute ("vscroll", defaultViewport.isVerticalScrollBarShown()),
|
||||
xml.getBoolAttribute ("hscroll", defaultViewport.isHorizontalScrollBarShown()));
|
||||
|
||||
v->setScrollBarThickness (xml.getIntAttribute ("scrollbarThickness", defaultViewport.getScrollBarThickness()));
|
||||
|
||||
setViewportJucerComponentFile (v, xml.getStringAttribute ("jucerFile", String()));
|
||||
setViewportGenericComponentClass (v, xml.getStringAttribute ("contentClass"));
|
||||
setViewportContentType (v, xml.getIntAttribute ("contentType", 0));
|
||||
setViewportConstructorParams (v, xml.getStringAttribute ("constructorParams"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void getEditableProperties (Component* component, JucerDocument& document,
|
||||
Array<PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
|
||||
|
||||
if (multipleSelected)
|
||||
return;
|
||||
|
||||
auto* v = dynamic_cast<Viewport*> (component);
|
||||
|
||||
props.add (new ViewportScrollbarShownProperty (v, document, true));
|
||||
props.add (new ViewportScrollbarShownProperty (v, document, false));
|
||||
props.add (new ViewportScrollbarSizeProperty (v, document));
|
||||
props.add (new ViewportContentTypeProperty (v, document));
|
||||
|
||||
if (getViewportContentType (v) == 1)
|
||||
{
|
||||
props.add (new ViewportJucerFileProperty (v, document));
|
||||
props.add (new ConstructorParamsProperty (v, document));
|
||||
}
|
||||
else if (getViewportContentType (v) == 2)
|
||||
{
|
||||
props.add (new ViewportContentClassProperty (v, document));
|
||||
props.add (new ConstructorParamsProperty (v, document));
|
||||
}
|
||||
}
|
||||
|
||||
String getCreationParameters (GeneratedCode&, Component* comp) override
|
||||
{
|
||||
return quotedString (comp->getName(), false);
|
||||
}
|
||||
|
||||
void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
|
||||
{
|
||||
Viewport defaultViewport;
|
||||
Viewport* const v = dynamic_cast<Viewport*> (component);
|
||||
|
||||
ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
|
||||
|
||||
if (defaultViewport.isVerticalScrollBarShown() != v->isVerticalScrollBarShown()
|
||||
|| defaultViewport.isHorizontalScrollBarShown() != v->isHorizontalScrollBarShown())
|
||||
{
|
||||
code.constructorCode
|
||||
<< memberVariableName << "->setScrollBarsShown ("
|
||||
<< CodeHelpers::boolLiteral (v->isVerticalScrollBarShown()) << ", "
|
||||
<< CodeHelpers::boolLiteral (v->isHorizontalScrollBarShown()) << ");\n";
|
||||
}
|
||||
|
||||
if (defaultViewport.getScrollBarThickness() != v->getScrollBarThickness())
|
||||
{
|
||||
code.constructorCode
|
||||
<< memberVariableName << "->setScrollBarThickness ("
|
||||
<< v->getScrollBarThickness() << ");\n";
|
||||
}
|
||||
|
||||
if (getViewportContentType (v) != 0)
|
||||
{
|
||||
String classNm (getViewportGenericComponentClass (v));
|
||||
|
||||
if (getViewportContentType (v) == 1)
|
||||
{
|
||||
File file;
|
||||
|
||||
const String filename (getViewportJucerComponentFile (v));
|
||||
|
||||
if (filename.isNotEmpty())
|
||||
file = code.document->getCppFile().getSiblingFile (filename);
|
||||
|
||||
std::unique_ptr<JucerDocument> doc (JucerDocument::createForCppFile (nullptr, file));
|
||||
|
||||
if (doc != nullptr)
|
||||
{
|
||||
code.includeFilesCPP.add (File::createFileWithoutCheckingPath (doc->getHeaderFile()
|
||||
.getRelativePathFrom (code.document->getCppFile().getParentDirectory())
|
||||
.replaceCharacter ('\\', '/')));
|
||||
classNm = doc->getClassName();
|
||||
}
|
||||
else
|
||||
{
|
||||
classNm = String();
|
||||
}
|
||||
}
|
||||
|
||||
if (classNm.isNotEmpty())
|
||||
{
|
||||
code.constructorCode
|
||||
<< memberVariableName << "->setViewedComponent (new "
|
||||
<< classNm;
|
||||
|
||||
if (getViewportConstructorParams (v).trim().isNotEmpty())
|
||||
{
|
||||
code.constructorCode << " (" << getViewportConstructorParams (v).trim() << "));\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
code.constructorCode << "());\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code.constructorCode << "\n";
|
||||
}
|
||||
|
||||
static void updateViewportContentComp (Viewport* vp)
|
||||
{
|
||||
if (getViewportContentType (vp) == 1)
|
||||
{
|
||||
JucerDocument* doc = findParentDocument (vp);
|
||||
auto tc = new TestComponent (doc, nullptr, false);
|
||||
|
||||
tc->setFilename (getViewportJucerComponentFile (vp));
|
||||
tc->setToInitialSize();
|
||||
|
||||
vp->setViewedComponent (tc);
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->setViewedComponent (new ViewportDemoContentComp());
|
||||
}
|
||||
}
|
||||
|
||||
static int getViewportContentType (Viewport* vp)
|
||||
{
|
||||
return vp->getProperties() ["contentType"];
|
||||
}
|
||||
|
||||
static void setViewportContentType (Viewport* vp, int newValue)
|
||||
{
|
||||
if (newValue != getViewportContentType (vp))
|
||||
{
|
||||
vp->getProperties().set ("contentType", newValue);
|
||||
updateViewportContentComp (vp);
|
||||
}
|
||||
}
|
||||
|
||||
static String getViewportJucerComponentFile (Viewport* vp)
|
||||
{
|
||||
return vp->getProperties() ["jucerFile"].toString();
|
||||
}
|
||||
|
||||
static void setViewportJucerComponentFile (Viewport* vp, const String& file)
|
||||
{
|
||||
if (file != getViewportJucerComponentFile (vp))
|
||||
{
|
||||
vp->getProperties().set ("jucerFile", file);
|
||||
updateViewportContentComp (vp);
|
||||
}
|
||||
}
|
||||
|
||||
static String getViewportGenericComponentClass (Viewport* vp)
|
||||
{
|
||||
return vp->getProperties() ["contentClass"].toString();
|
||||
}
|
||||
|
||||
static void setViewportGenericComponentClass (Viewport* vp, const String& name)
|
||||
{
|
||||
if (name != getViewportGenericComponentClass (vp))
|
||||
{
|
||||
vp->getProperties().set ("contentClass", name);
|
||||
updateViewportContentComp (vp);
|
||||
}
|
||||
}
|
||||
|
||||
static String getViewportConstructorParams (Viewport* vp)
|
||||
{
|
||||
return vp->getProperties() ["constructorParams"].toString();
|
||||
}
|
||||
|
||||
static void setViewportConstructorParams (Viewport* vp, const String& newParams)
|
||||
{
|
||||
if (newParams != getViewportConstructorParams (vp))
|
||||
{
|
||||
vp->getProperties().set ("constructorParams", newParams);
|
||||
updateViewportContentComp (vp);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class UpdatingViewport : public Viewport
|
||||
{
|
||||
public:
|
||||
UpdatingViewport (const String& name)
|
||||
: Viewport (name)
|
||||
{
|
||||
}
|
||||
|
||||
void parentHierarchyChanged()
|
||||
{
|
||||
Viewport::parentHierarchyChanged();
|
||||
updateViewportContentComp (this);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct ViewportDemoContentComp : public Component
|
||||
{
|
||||
ViewportDemoContentComp()
|
||||
{
|
||||
setSize (2048, 2048);
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillCheckerBoard (getLocalBounds().toFloat(), 50.0f, 50.0f,
|
||||
Colours::lightgrey.withAlpha (0.5f),
|
||||
Colours::darkgrey.withAlpha (0.5f));
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ViewportScrollbarShownProperty : public ComponentBooleanProperty <Viewport>
|
||||
{
|
||||
public:
|
||||
ViewportScrollbarShownProperty (Viewport* comp, JucerDocument& doc, const bool vertical_)
|
||||
: ComponentBooleanProperty <Viewport> (vertical_ ? "V scrollbar" : "H scrollbar",
|
||||
"enabled", "enabled",
|
||||
comp, doc),
|
||||
vertical (vertical_)
|
||||
{
|
||||
}
|
||||
|
||||
void setState (bool newState)
|
||||
{
|
||||
document.perform (new ViewportScrollbarChangeAction (component, *document.getComponentLayout(), vertical, newState),
|
||||
"Change Viewport scrollbar");
|
||||
}
|
||||
|
||||
bool getState() const
|
||||
{
|
||||
return vertical ? component->isVerticalScrollBarShown()
|
||||
: component->isHorizontalScrollBarShown();
|
||||
}
|
||||
|
||||
const bool vertical;
|
||||
|
||||
private:
|
||||
class ViewportScrollbarChangeAction : public ComponentUndoableAction <Viewport>
|
||||
{
|
||||
public:
|
||||
ViewportScrollbarChangeAction (Viewport* const comp, ComponentLayout& l, const bool vertical_, const bool newState_)
|
||||
: ComponentUndoableAction <Viewport> (comp, l),
|
||||
vertical (vertical_),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = vertical ? comp->isVerticalScrollBarShown()
|
||||
: comp->isHorizontalScrollBarShown();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
if (vertical)
|
||||
getComponent()->setScrollBarsShown (newState, getComponent()->isHorizontalScrollBarShown());
|
||||
else
|
||||
getComponent()->setScrollBarsShown (getComponent()->isVerticalScrollBarShown(), newState);
|
||||
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
if (vertical)
|
||||
getComponent()->setScrollBarsShown (oldState, getComponent()->isHorizontalScrollBarShown());
|
||||
else
|
||||
getComponent()->setScrollBarsShown (getComponent()->isVerticalScrollBarShown(), oldState);
|
||||
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vertical, newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ViewportScrollbarSizeProperty : public SliderPropertyComponent,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
ViewportScrollbarSizeProperty (Viewport* comp, JucerDocument& doc)
|
||||
: SliderPropertyComponent ("scrollbar size", 3.0, 30.0, 1.0, 1.0),
|
||||
component (comp),
|
||||
document (doc)
|
||||
{
|
||||
document.addChangeListener (this);
|
||||
}
|
||||
|
||||
~ViewportScrollbarSizeProperty() override
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setValue (double newValue) override
|
||||
{
|
||||
document.getUndoManager().undoCurrentTransactionOnly();
|
||||
|
||||
document.perform (new ViewportScrollbarSizeChangeAction (component, *document.getComponentLayout(), roundToInt (newValue)),
|
||||
"Change Viewport scrollbar size");
|
||||
}
|
||||
|
||||
double getValue() const override
|
||||
{
|
||||
return component->getScrollBarThickness();
|
||||
}
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
Viewport* component;
|
||||
JucerDocument& document;
|
||||
|
||||
private:
|
||||
class ViewportScrollbarSizeChangeAction : public ComponentUndoableAction <Viewport>
|
||||
{
|
||||
public:
|
||||
ViewportScrollbarSizeChangeAction (Viewport* const comp, ComponentLayout& l, const int newState_)
|
||||
: ComponentUndoableAction <Viewport> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = comp->getScrollBarThickness();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setScrollBarThickness (newState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getComponent()->setScrollBarThickness (newState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
int newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ViewportContentTypeProperty : public ComponentChoiceProperty <Viewport>
|
||||
{
|
||||
public:
|
||||
ViewportContentTypeProperty (Viewport* comp, JucerDocument& doc)
|
||||
: ComponentChoiceProperty <Viewport> ("content", comp, doc)
|
||||
{
|
||||
choices.add ("No content component");
|
||||
choices.add ("Jucer content component");
|
||||
choices.add ("Named content component");
|
||||
}
|
||||
|
||||
void setIndex (int newIndex)
|
||||
{
|
||||
document.perform (new ViewportContentTypeChangeAction (component, *document.getComponentLayout(), newIndex),
|
||||
"Change Viewport content type");
|
||||
}
|
||||
|
||||
int getIndex() const
|
||||
{
|
||||
return getViewportContentType (component);
|
||||
}
|
||||
|
||||
private:
|
||||
class ViewportContentTypeChangeAction : public ComponentUndoableAction <Viewport>
|
||||
{
|
||||
public:
|
||||
ViewportContentTypeChangeAction (Viewport* const comp, ComponentLayout& l, const int newValue_)
|
||||
: ComponentUndoableAction <Viewport> (comp, l),
|
||||
newValue (newValue_)
|
||||
{
|
||||
oldValue = getViewportContentType (comp);
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
setViewportContentType (getComponent(), newValue);
|
||||
changed();
|
||||
layout.getDocument()->refreshAllPropertyComps();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
setViewportContentType (getComponent(), oldValue);
|
||||
changed();
|
||||
layout.getDocument()->refreshAllPropertyComps();
|
||||
return true;
|
||||
}
|
||||
|
||||
int newValue, oldValue;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ViewportJucerFileProperty : public FilePropertyComponent,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
ViewportJucerFileProperty (Viewport* const comp, JucerDocument& doc)
|
||||
: FilePropertyComponent ("Jucer file", false, true),
|
||||
component (comp),
|
||||
document (doc)
|
||||
{
|
||||
document.addChangeListener (this);
|
||||
}
|
||||
|
||||
~ViewportJucerFileProperty() override
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setFile (const File& newFile) override
|
||||
{
|
||||
document.perform (new JucerCompFileChangeAction (component, *document.getComponentLayout(),
|
||||
newFile.getRelativePathFrom (document.getCppFile().getParentDirectory())
|
||||
.replaceCharacter ('\\', '/')),
|
||||
"Change Projucer component file");
|
||||
}
|
||||
|
||||
File getFile() const override
|
||||
{
|
||||
auto filename = getViewportJucerComponentFile (component);
|
||||
|
||||
if (filename.isEmpty())
|
||||
return {};
|
||||
|
||||
return document.getCppFile().getSiblingFile (filename);
|
||||
}
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
Viewport* const component;
|
||||
JucerDocument& document;
|
||||
|
||||
class JucerCompFileChangeAction : public ComponentUndoableAction <Viewport>
|
||||
{
|
||||
public:
|
||||
JucerCompFileChangeAction (Viewport* const comp, ComponentLayout& l, const String& newState_)
|
||||
: ComponentUndoableAction <Viewport> (comp, l),
|
||||
newState (newState_)
|
||||
{
|
||||
oldState = getViewportJucerComponentFile (comp);
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
setViewportJucerComponentFile (getComponent(), newState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
setViewportJucerComponentFile (getComponent(), oldState);
|
||||
changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
String newState, oldState;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ViewportContentClassProperty : public ComponentTextProperty <Viewport>
|
||||
{
|
||||
public:
|
||||
ViewportContentClassProperty (Viewport* comp, JucerDocument& doc)
|
||||
: ComponentTextProperty <Viewport> ("content class", 256, false, comp, doc)
|
||||
{
|
||||
}
|
||||
|
||||
void setText (const String& newText) override
|
||||
{
|
||||
document.perform (new ViewportClassNameChangeAction (component, *document.getComponentLayout(), newText),
|
||||
"Change Viewport content class");
|
||||
}
|
||||
|
||||
String getText() const override
|
||||
{
|
||||
return getViewportGenericComponentClass (component);
|
||||
}
|
||||
|
||||
private:
|
||||
class ViewportClassNameChangeAction : public ComponentUndoableAction <Viewport>
|
||||
{
|
||||
public:
|
||||
ViewportClassNameChangeAction (Viewport* const comp, ComponentLayout& l, const String& newValue_)
|
||||
: ComponentUndoableAction <Viewport> (comp, l),
|
||||
newValue (newValue_)
|
||||
{
|
||||
oldValue = getViewportGenericComponentClass (comp);
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
setViewportGenericComponentClass (getComponent(), newValue);
|
||||
changed();
|
||||
layout.getDocument()->refreshAllPropertyComps();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
setViewportGenericComponentClass (getComponent(), oldValue);
|
||||
changed();
|
||||
layout.getDocument()->refreshAllPropertyComps();
|
||||
return true;
|
||||
}
|
||||
|
||||
String newValue, oldValue;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ConstructorParamsProperty : public ComponentTextProperty <Viewport>
|
||||
{
|
||||
public:
|
||||
ConstructorParamsProperty (Viewport* comp, JucerDocument& doc)
|
||||
: ComponentTextProperty <Viewport> ("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 getViewportConstructorParams (component);
|
||||
}
|
||||
|
||||
private:
|
||||
class ConstructorParamChangeAction : public ComponentUndoableAction <Viewport>
|
||||
{
|
||||
public:
|
||||
ConstructorParamChangeAction (Viewport* const comp, ComponentLayout& l, const String& newValue_)
|
||||
: ComponentUndoableAction <Viewport> (comp, l),
|
||||
newValue (newValue_)
|
||||
{
|
||||
oldValue = getViewportConstructorParams (comp);
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
setViewportConstructorParams (getComponent(), newValue);
|
||||
changed();
|
||||
layout.getDocument()->refreshAllPropertyComps();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
setViewportConstructorParams (getComponent(), oldValue);
|
||||
changed();
|
||||
layout.getDocument()->refreshAllPropertyComps();
|
||||
return true;
|
||||
}
|
||||
|
||||
String newValue, oldValue;
|
||||
};
|
||||
};
|
||||
};
|
Reference in New Issue
Block a user