diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_ButtonHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_ButtonHandler.h index de0802ef9e..c1be2fcfca 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_ButtonHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_ButtonHandler.h @@ -36,25 +36,30 @@ public: defaultWidth_, defaultHeight_) {} - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, document, props); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); - Button* const b = dynamic_cast (component); + if (multipleSelected) + return; - props.add (new ButtonTextProperty (b, document)); + if (auto* b = dynamic_cast (component)) + { + props.add (new ButtonTextProperty (b, document)); - props.add (new ButtonCallbackProperty (b, document)); + props.add (new ButtonCallbackProperty (b, document)); - props.add (new ButtonRadioGroupProperty (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)); + 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) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { Button* const b = dynamic_cast (comp); @@ -67,7 +72,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { Button* const b = dynamic_cast (comp); @@ -82,12 +87,12 @@ public: return true; } - String getCreationParameters (GeneratedCode&, Component* component) + String getCreationParameters (GeneratedCode&, Component* component) override { return quotedString (component->getName(), false); } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName); @@ -131,7 +136,7 @@ public: code.constructorCode << memberVariableName << "->addListener (this);\n"; } - void fillInGeneratedCode (Component* component, GeneratedCode& code) + void fillInGeneratedCode (Component* component, GeneratedCode& code) override { ComponentTypeHandler::fillInGeneratedCode (component, code); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_ComboBoxHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_ComboBoxHandler.h index e5cdd86ae3..4c9a8fbf58 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_ComboBoxHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_ComboBoxHandler.h @@ -31,12 +31,12 @@ public: : ComponentTypeHandler ("Combo Box", "ComboBox", typeid (ComboBox), 150, 24) {} - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { return new ComboBox ("new combo box"); } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { ComboBox* const c = dynamic_cast (comp); jassert (c != nullptr); @@ -52,7 +52,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout)) return false; @@ -73,26 +73,30 @@ public: return true; } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, document, props); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); - ComboBox* const c = dynamic_cast (component); - jassert (c != nullptr); + if (multipleSelected) + return; - 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)); + if (auto* c = dynamic_cast (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) + String getCreationParameters (GeneratedCode&, Component* component) override { return quotedString (component->getName(), false); } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName); @@ -126,7 +130,7 @@ public: code.constructorCode += s; } - void fillInGeneratedCode (Component* component, GeneratedCode& code) + void fillInGeneratedCode (Component* component, GeneratedCode& code) override { ComponentTypeHandler::fillInGeneratedCode (component, code); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_ComponentTypeHandler.cpp b/extras/Projucer/Source/ComponentEditor/components/jucer_ComponentTypeHandler.cpp index 73b6dd1851..6a34aac501 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_ComponentTypeHandler.cpp +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_ComponentTypeHandler.cpp @@ -78,7 +78,7 @@ ComponentOverlayComponent* ComponentTypeHandler::createOverlayComponent (Compone static void dummyMenuCallback (int, int) {} -void ComponentTypeHandler::showPopupMenu (Component*, ComponentLayout&) +void ComponentTypeHandler::showPopupMenu (Component*, ComponentLayout& layout) { PopupMenu m; @@ -87,6 +87,16 @@ void ComponentTypeHandler::showPopupMenu (Component*, ComponentLayout&) 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); @@ -346,7 +356,12 @@ public: void setPosition (const RelativePositionedRectangle& newPos) { - document.getComponentLayout()->setComponentPosition (component, newPos, true); + auto* layout = document.getComponentLayout(); + + if (layout->getSelectedSet().getNumSelected() > 1) + positionOtherSelectedComponents (ComponentTypeHandler::getComponentPosition (component), newPos); + + layout->setComponentPosition (component, newPos, true); } RelativePositionedRectangle getPosition() const @@ -356,6 +371,41 @@ public: 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); + } + } + } }; @@ -413,27 +463,32 @@ private: //============================================================================== void ComponentTypeHandler::getEditableProperties (Component* component, JucerDocument& document, - Array& props) + Array& props, + bool multipleSelected) { - props.add (new ComponentMemberNameProperty (component, document)); - props.add (new ComponentNameProperty (component, document)); - props.add (new ComponentVirtualClassProperty (component, document)); + if (! multipleSelected) + { + props.add (new ComponentMemberNameProperty (component, document)); + props.add (new ComponentNameProperty (component, document)); + props.add (new ComponentVirtualClassProperty (component, document)); + + if (dynamic_cast (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)); - - if (dynamic_cast (component) != nullptr) - props.add (new TooltipProperty (component, document)); - - props.add (new FocusOrderProperty (component, document)); } -void ComponentTypeHandler::addPropertiesToPropertyPanel (Component* comp, JucerDocument& document, PropertyPanel& panel) +void ComponentTypeHandler::addPropertiesToPropertyPanel (Component* comp, JucerDocument& document, + PropertyPanel& panel, bool multipleSelected) { Array props; - getEditableProperties (comp, document, props); + getEditableProperties (comp, document, props, multipleSelected); panel.addSection (getClassName (comp), props); } diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_ComponentTypeHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_ComponentTypeHandler.h index 281b894925..b20c014fd4 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_ComponentTypeHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_ComponentTypeHandler.h @@ -63,11 +63,13 @@ public: virtual void getEditableProperties (Component* component, JucerDocument& document, - Array& props); + Array& props, + bool multipleSelected); virtual void addPropertiesToPropertyPanel (Component* component, JucerDocument& document, - PropertyPanel& panel); + PropertyPanel& panel, + bool multipleSelected); void registerEditableColour (int colourId, diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_GenericComponentHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_GenericComponentHandler.h index 9300d88f29..b70f36884c 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_GenericComponentHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_GenericComponentHandler.h @@ -75,12 +75,12 @@ public: : ComponentTypeHandler ("Generic Component", "GenericComponent", typeid (GenericComponent), 150, 24) {} - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { return new GenericComponent(); } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout); e->setAttribute ("class", ((GenericComponent*) comp)->actualClassName); @@ -89,7 +89,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout)) return false; @@ -99,25 +99,29 @@ public: return true; } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, document, props); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); + + if (multipleSelected) + return; props.add (new GenericCompClassProperty (dynamic_cast (component), document)); props.add (new GenericCompParamsProperty (dynamic_cast (component), document)); } - String getClassName (Component* comp) const + String getClassName (Component* comp) const override { return static_cast (comp)->actualClassName; } - String getCreationParameters (GeneratedCode&, Component* comp) + String getCreationParameters (GeneratedCode&, Component* comp) override { return static_cast (comp)->constructorParams; } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_GroupComponentHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_GroupComponentHandler.h index 9c7df54108..8707dc0760 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_GroupComponentHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_GroupComponentHandler.h @@ -34,12 +34,12 @@ public: registerColour (GroupComponent::textColourId, "text", "textcol"); } - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { return new GroupComponent ("new group", "group"); } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { GroupComponent* const g = (GroupComponent*) comp; @@ -54,7 +54,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { GroupComponent* const g = (GroupComponent*) comp; @@ -67,7 +67,7 @@ public: return true; } - String getCreationParameters (GeneratedCode& code, Component* component) + String getCreationParameters (GeneratedCode& code, Component* component) override { GroupComponent* g = dynamic_cast (component); @@ -76,7 +76,7 @@ public: + quotedString (g->getText(), code.shouldUseTransMacro()); } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName); @@ -99,12 +99,19 @@ public: code.constructorCode += s; } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, document, props); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); - props.add (new GroupTitleProperty ((GroupComponent*) component, document)); - props.add (new GroupJustificationProperty ((GroupComponent*) component, document)); + if (multipleSelected) + return; + + if (auto* gc = dynamic_cast (component)) + { + props.add (new GroupTitleProperty (gc, document)); + props.add (new GroupJustificationProperty (gc, document)); + } addColourProperties (component, document, props); } diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_HyperlinkButtonHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_HyperlinkButtonHandler.h index cacf0391a9..ebb12cf408 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_HyperlinkButtonHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_HyperlinkButtonHandler.h @@ -33,7 +33,7 @@ public: registerColour (HyperlinkButton::textColourId, "text", "textCol"); } - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { HyperlinkButton* hb = new HyperlinkButton ("new hyperlink", URL ("http://www.juce.com")); @@ -41,15 +41,21 @@ public: return hb; } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - HyperlinkButton* const hb = (HyperlinkButton*) component; - ButtonHandler::getEditableProperties (component, document, props); - props.add (new HyperlinkURLProperty (hb, document)); + ButtonHandler::getEditableProperties (component, document, props, multipleSelected); + + if (multipleSelected) + return; + + if (auto* hb = dynamic_cast (component)) + props.add (new HyperlinkURLProperty (hb, document)); + addColourProperties (component, document, props); } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { HyperlinkButton* const hb = (HyperlinkButton*) comp; XmlElement* const e = ButtonHandler::createXmlFor (comp, layout); @@ -57,7 +63,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { HyperlinkButton* const hb = (HyperlinkButton*) comp; @@ -69,7 +75,7 @@ public: return true; } - String getCreationParameters (GeneratedCode& code, Component* comp) + String getCreationParameters (GeneratedCode& code, Component* comp) override { HyperlinkButton* const hb = dynamic_cast (comp); @@ -79,7 +85,7 @@ public: + ")"; } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ButtonHandler::fillInCreationCode (code, component, memberVariableName); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_ImageButtonHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_ImageButtonHandler.h index 7f850cd172..2bf4e6dcc0 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_ImageButtonHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_ImageButtonHandler.h @@ -40,37 +40,42 @@ public: { } - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { return new ImageButton ("new button"); } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ButtonHandler::getEditableProperties (component, document, props); + ButtonHandler::getEditableProperties (component, document, props, multipleSelected); + + if (multipleSelected) + return; addColourProperties (component, document, props); - ImageButton* const ib = (ImageButton*) component; + if (auto* ib = dynamic_cast (component)) + { + auto& layout = *document.getComponentLayout(); - ComponentLayout& layout = *document.getComponentLayout(); + props.add (new ImageButtonProportionProperty (layout, ib)); - 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, 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, 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)); + 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) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { XmlElement* e = ButtonHandler::createXmlFor (comp, layout); @@ -93,7 +98,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { if (! ButtonHandler::restoreFromXml (xml, comp, layout)) return false; @@ -118,7 +123,7 @@ public: return true; } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ButtonHandler::fillInCreationCode (code, component, memberVariableName); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_JucerComponentHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_JucerComponentHandler.h index a64adc37f3..5cba5dd633 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_JucerComponentHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_JucerComponentHandler.h @@ -42,14 +42,14 @@ public: typeid (TestComponent), 300, 200) {} - Component* createNewComponent (JucerDocument* doc) + Component* createNewComponent (JucerDocument* doc) override { return new TestComponent (doc, 0, false); } - String getXmlTagName() const noexcept { return "JUCERCOMP"; } + String getXmlTagName() const noexcept override { return "JUCERCOMP"; } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { TestComponent* const tc = dynamic_cast (comp); @@ -60,7 +60,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { TestComponent* const tc = dynamic_cast (comp); @@ -73,7 +73,7 @@ public: return true; } - String getClassName (Component* comp) const + String getClassName (Component* comp) const override { TestComponent* const tc = dynamic_cast (comp); @@ -88,23 +88,28 @@ public: return jucerCompClassName; } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - TestComponent* const tc = dynamic_cast (component); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); - ComponentTypeHandler::getEditableProperties (component, document, props); + if (multipleSelected) + return; - props.add (new JucerCompFileProperty (tc, document)); - props.add (new ConstructorParamsProperty (tc, document)); - props.add (new JucerCompOpenDocProperty (tc)); + if (auto* const tc = dynamic_cast (component)) + { + props.add (new JucerCompFileProperty (tc, document)); + props.add (new ConstructorParamsProperty (tc, document)); + props.add (new JucerCompOpenDocProperty (tc)); + } } - String getCreationParameters (GeneratedCode&, Component* component) + String getCreationParameters (GeneratedCode&, Component* component) override { return dynamic_cast (component)->getConstructorParams().trim(); } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_LabelHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_LabelHandler.h index 9e8781a77e..361e845de9 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_LabelHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_LabelHandler.h @@ -38,12 +38,12 @@ public: registerColour (TextEditor::highlightColourId, "highlight", "hiliteCol"); } - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { return new Label ("new label", "label text"); } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { Label* const l = dynamic_cast (comp); @@ -68,7 +68,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { Label* const l = dynamic_cast (comp); @@ -109,7 +109,7 @@ public: label->setFont (f); } - String getCreationParameters (GeneratedCode& code, Component* component) + String getCreationParameters (GeneratedCode& code, Component* component) override { Label* const l = dynamic_cast (component); @@ -118,7 +118,7 @@ public: + quotedString (l->getText(), code.shouldUseTransMacro()); } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName); @@ -146,7 +146,7 @@ public: code.constructorCode += s; } - void fillInGeneratedCode (Component* component, GeneratedCode& code) + void fillInGeneratedCode (Component* component, GeneratedCode& code) override { ComponentTypeHandler::fillInGeneratedCode (component, code); @@ -169,24 +169,30 @@ public: } } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, document, props); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); - Label* const l = dynamic_cast (component); - props.add (new LabelTextProperty (l, document)); - props.add (new LabelJustificationProperty (l, document)); - props.add (new FontNameProperty (l, document)); - props.add (new FontStyleProperty (l, document)); - props.add (new FontSizeProperty (l, document)); - props.add (new FontKerningProperty (l, document)); + if (multipleSelected) + return; + + if (auto* const l = dynamic_cast (component)) + { + props.add (new LabelTextProperty (l, document)); + props.add (new LabelJustificationProperty (l, document)); + props.add (new FontNameProperty (l, document)); + props.add (new FontStyleProperty (l, document)); + props.add (new FontSizeProperty (l, document)); + props.add (new FontKerningProperty (l, document)); + + props.add (new LabelEditableProperty (l, document)); + + if (l->isEditableOnDoubleClick() || l->isEditableOnSingleClick()) + props.add (new LabelLossOfFocusProperty (l, document)); + } addColourProperties (component, document, props); - - props.add (new LabelEditableProperty (l, document)); - - if (l->isEditableOnDoubleClick() || l->isEditableOnSingleClick()) - props.add (new LabelLossOfFocusProperty (l, document)); } static bool needsCallback (Component* label) diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_SliderHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_SliderHandler.h index c52dc9bdc7..5df4cdd442 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_SliderHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_SliderHandler.h @@ -172,23 +172,27 @@ struct SliderHandler : public ComponentTypeHandler } } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) override + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, document, props); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); - Slider* s = dynamic_cast (component); - jassert (s != 0); + if (multipleSelected) + return; - 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)); + if (auto* s = dynamic_cast (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); } diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_TabbedComponentHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_TabbedComponentHandler.h index c3ac40f1ae..b7fb0bdbd1 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_TabbedComponentHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_TabbedComponentHandler.h @@ -31,7 +31,7 @@ public: : ComponentTypeHandler ("Tabbed Component", "TabbedComponent", typeid (TabbedComponent), 200, 150) {} - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { TabbedComponent* const t = new TabbedComponent (TabbedButtonBar::TabsAtTop); t->setName ("new tabbed component"); @@ -42,7 +42,7 @@ public: return t; } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { TabbedComponent* const t = dynamic_cast (comp); XmlElement* const e = ComponentTypeHandler::createXmlFor (comp, layout); @@ -61,7 +61,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout)) return false; @@ -90,27 +90,33 @@ public: return true; } - void getEditableProperties (Component* component, JucerDocument& doc, Array& props) + void getEditableProperties (Component* component, JucerDocument& doc, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, doc, props); + ComponentTypeHandler::getEditableProperties (component, doc, props, multipleSelected); - TabbedComponent* const t = dynamic_cast (component); + if (multipleSelected) + return; - props.add (new TabOrientationProperty (t, doc)); - props.add (new TabDepthProperty (t, doc)); + if (auto* t = dynamic_cast (component)) + { + props.add (new TabOrientationProperty (t, doc)); + props.add (new TabDepthProperty (t, doc)); - if (t->getNumTabs() > 0) - props.add (new TabInitialTabProperty (t, doc)); + if (t->getNumTabs() > 0) + props.add (new TabInitialTabProperty (t, doc)); - props.add (new TabAddTabProperty (t, doc)); + props.add (new TabAddTabProperty (t, doc)); - if (t->getNumTabs() > 0) - props.add (new TabRemoveTabProperty (t, doc)); + if (t->getNumTabs() > 0) + props.add (new TabRemoveTabProperty (t, doc)); + } } - void addPropertiesToPropertyPanel (Component* comp, JucerDocument& doc, PropertyPanel& panel) + void addPropertiesToPropertyPanel (Component* comp, JucerDocument& doc, + PropertyPanel& panel, bool multipleSelected) override { - ComponentTypeHandler::addPropertiesToPropertyPanel (comp, doc, panel); + ComponentTypeHandler::addPropertiesToPropertyPanel (comp, doc, panel, multipleSelected); TabbedComponent* const t = dynamic_cast (comp); @@ -136,7 +142,7 @@ public: } } - String getCreationParameters (GeneratedCode&, Component* comp) + String getCreationParameters (GeneratedCode&, Component* comp) override { TabbedComponent* const t = dynamic_cast (comp); @@ -152,7 +158,7 @@ public: return {}; } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { TabbedComponent* const t = dynamic_cast (component); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_TextButtonHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_TextButtonHandler.h index 7754d18db5..5349d4f50d 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_TextButtonHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_TextButtonHandler.h @@ -36,28 +36,33 @@ public: registerColour (TextButton::textColourOnId, "text colour (on)", "textColOn"); } - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { return new TextButton ("new button", String()); } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ButtonHandler::getEditableProperties (component, document, props); + ButtonHandler::getEditableProperties (component, document, props, multipleSelected); + + if (multipleSelected) + return; + addColourProperties (component, document, props); } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { return ButtonHandler::createXmlFor (comp, layout); } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* 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) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ButtonHandler::fillInCreationCode (code, component, memberVariableName); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_TextEditorHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_TextEditorHandler.h index 80b5d3fb6c..446ca831ac 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_TextEditorHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_TextEditorHandler.h @@ -38,12 +38,12 @@ public: registerColour (CaretComponent::caretColourId, "caret", "caretcol"); } - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { return new TextEditor ("new text editor"); } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout); TextEditor* te = (TextEditor*) comp; @@ -60,7 +60,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout)) return false; @@ -81,29 +81,33 @@ public: return true; } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, document, props); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); - TextEditor* const t = dynamic_cast (component); - jassert (t != nullptr); + if (multipleSelected) + return; - 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)); + if (auto* t = dynamic_cast (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); + addColourProperties (t, document, props); + } } - String getCreationParameters (GeneratedCode&, Component* component) + String getCreationParameters (GeneratedCode&, Component* component) override { return quotedString (component->getName(), false); } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_ToggleButtonHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_ToggleButtonHandler.h index af62fae9bd..29460c1eab 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_ToggleButtonHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_ToggleButtonHandler.h @@ -33,21 +33,26 @@ public: registerColour (ToggleButton::textColourId, "text colour", "txtcol"); } - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { return new ToggleButton ("new toggle button"); } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ButtonHandler::getEditableProperties (component, document, props); + ButtonHandler::getEditableProperties (component, document, props, multipleSelected); - props.add (new ToggleButtonStateProperty ((ToggleButton*) component, document)); + if (multipleSelected) + return; + + if (auto* tb = dynamic_cast (component)) + props.add (new ToggleButtonStateProperty (tb, document)); addColourProperties (component, document, props); } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { ToggleButton* tb = (ToggleButton*) comp; @@ -57,7 +62,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { ToggleButton* const tb = (ToggleButton*) comp; @@ -68,7 +73,7 @@ public: return true; } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { ButtonHandler::fillInCreationCode (code, component, memberVariableName); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_TreeViewHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_TreeViewHandler.h index 1f6deb120f..f4890b2aa7 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_TreeViewHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_TreeViewHandler.h @@ -34,12 +34,12 @@ public: registerColour (TreeView::linesColourId, "lines", "linecol"); } - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { return new DemoTreeView(); } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { TreeView* const t = dynamic_cast (comp); XmlElement* const e = ComponentTypeHandler::createXmlFor (comp, layout); @@ -50,7 +50,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout)) return false; @@ -64,10 +64,15 @@ public: return true; } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, document, props); - TreeView* const t = dynamic_cast (component); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); + + if (multipleSelected) + return; + + auto* t = dynamic_cast (component); props.add (new TreeViewRootItemProperty (t, document)); props.add (new TreeViewRootOpennessProperty (t, document)); @@ -75,12 +80,12 @@ public: addColourProperties (t, document, props); } - String getCreationParameters (GeneratedCode&, Component* comp) + String getCreationParameters (GeneratedCode&, Component* comp) override { return quotedString (comp->getName(), false); } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { TreeView defaultTreeView; TreeView* const t = dynamic_cast (component); diff --git a/extras/Projucer/Source/ComponentEditor/components/jucer_ViewportHandler.h b/extras/Projucer/Source/ComponentEditor/components/jucer_ViewportHandler.h index 38131eab37..3ad3fa7e9c 100644 --- a/extras/Projucer/Source/ComponentEditor/components/jucer_ViewportHandler.h +++ b/extras/Projucer/Source/ComponentEditor/components/jucer_ViewportHandler.h @@ -31,7 +31,7 @@ public: : ComponentTypeHandler ("Viewport", "Viewport", typeid (UpdatingViewport), 150, 150) {} - Component* createNewComponent (JucerDocument*) + Component* createNewComponent (JucerDocument*) override { Viewport* const v = new UpdatingViewport ("new viewport"); v->setViewedComponent (new ViewportDemoContentComp()); @@ -39,7 +39,7 @@ public: return v; } - XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) + XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override { Viewport* const v = dynamic_cast (comp); XmlElement* const e = ComponentTypeHandler::createXmlFor (comp, layout); @@ -56,7 +56,7 @@ public: return e; } - bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) + bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override { if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout)) return false; @@ -76,11 +76,15 @@ public: return true; } - void getEditableProperties (Component* component, JucerDocument& document, Array& props) + void getEditableProperties (Component* component, JucerDocument& document, + Array& props, bool multipleSelected) override { - ComponentTypeHandler::getEditableProperties (component, document, props); + ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected); - Viewport* const v = dynamic_cast (component); + if (multipleSelected) + return; + + auto* v = dynamic_cast (component); props.add (new ViewportScrollbarShownProperty (v, document, true)); props.add (new ViewportScrollbarShownProperty (v, document, false)); @@ -99,12 +103,12 @@ public: } } - String getCreationParameters (GeneratedCode&, Component* comp) + String getCreationParameters (GeneratedCode&, Component* comp) override { return quotedString (comp->getName(), false); } - void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) + void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override { Viewport defaultViewport; Viewport* const v = dynamic_cast (component); diff --git a/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp b/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp index a55de9dc63..e0a39b574c 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp +++ b/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp @@ -331,6 +331,68 @@ void ComponentLayout::selectedToBack() componentToBack (temp.getSelectedItem(i), true); } +void ComponentLayout::alignTop() +{ + if (selected.getNumSelected() > 1) + { + auto* main = selected.getSelectedItem (0); + auto yPos = main->getY(); + + for (auto* other : selected) + { + if (other != main) + setComponentBoundsAndProperties (other, + other->getBounds().withPosition (other->getX(), yPos), + main, true); + } + } +} + +void ComponentLayout::alignRight() +{ + if (selected.getNumSelected() > 1) + { + auto* main = selected.getSelectedItem (0); + auto rightPos = main->getRight(); + + for (auto* other : selected) + { + if (other != main) + setComponentBoundsAndProperties (other, other->getBounds().withPosition (rightPos - other->getWidth(), other->getY()), main, true); + } + } +} + +void ComponentLayout::alignBottom() +{ + if (selected.getNumSelected() > 1) + { + auto* main = selected.getSelectedItem (0); + auto bottomPos = main->getBottom(); + + for (auto* other : selected) + { + if (other != main) + setComponentBoundsAndProperties (other, other->getBounds().withPosition (other->getX(), bottomPos - other->getHeight()), main, true); + } + } +} + +void ComponentLayout::alignLeft() +{ + if (selected.getNumSelected() > 1) + { + auto* main = selected.getSelectedItem (0); + auto xPos = main->getX(); + + for (auto* other : selected) + { + if (other != main) + setComponentBoundsAndProperties (other, other->getBounds().withPosition (xPos, other->getY()), main, true); + } + } +} + void ComponentLayout::bringLostItemsBackOnScreen (int width, int height) { for (int i = components.size(); --i >= 0;) @@ -558,6 +620,42 @@ private: RelativePositionedRectangle newPos, oldPos; }; +class ChangeCompBoundsAndPropertiesAction : public ComponentUndoableAction +{ +public: + ChangeCompBoundsAndPropertiesAction (Component* const comp, ComponentLayout& l, + const Rectangle& bounds, const NamedValueSet& props) + : ComponentUndoableAction (comp, l), + newBounds (bounds), + oldBounds (comp->getBounds()), + newProps (props), + oldProps(comp->getProperties()) + { + } + + bool perform() + { + showCorrectTab(); + getComponent()->setBounds (newBounds); + getComponent()->getProperties() = newProps; + layout.updateStoredComponentPosition (getComponent(), false); + return true; + } + + bool undo() + { + showCorrectTab(); + getComponent()->setBounds (oldBounds); + getComponent()->getProperties() = oldProps; + layout.updateStoredComponentPosition (getComponent(), false); + return true; + } + +private: + Rectangle newBounds, oldBounds; + NamedValueSet newProps, oldProps; +}; + void ComponentLayout::setComponentPosition (Component* comp, const RelativePositionedRectangle& newPos, const bool undoable) @@ -576,6 +674,42 @@ void ComponentLayout::setComponentPosition (Component* comp, } } +void ComponentLayout::setComponentBoundsAndProperties (Component* componentToPosition, const Rectangle& newBounds, + Component* referenceComponent, const bool undoable) +{ + auto props = NamedValueSet (componentToPosition->getProperties()); + + auto rect = ComponentTypeHandler::getComponentPosition (componentToPosition).rect; + auto referenceComponentPosition = ComponentTypeHandler::getComponentPosition (referenceComponent); + auto referenceComponentRect = referenceComponentPosition.rect; + + rect.setModes (referenceComponentRect.getAnchorPointX(), referenceComponentRect.getPositionModeX(), + referenceComponentRect.getAnchorPointY(), referenceComponentRect.getPositionModeY(), + referenceComponentRect.getWidthMode(), referenceComponentRect.getHeightMode(), + componentToPosition->getBounds()); + + props.set ("pos", rect.toString()); + props.set ("relativeToX", String::toHexString (referenceComponentPosition.relativeToX)); + props.set ("relativeToY", String::toHexString (referenceComponentPosition.relativeToY)); + props.set ("relativeToW", String::toHexString (referenceComponentPosition.relativeToW)); + props.set ("relativeToH", String::toHexString (referenceComponentPosition.relativeToH)); + + if (componentToPosition->getBounds() != newBounds || componentToPosition->getProperties() != props) + { + if (undoable) + { + perform (new ChangeCompBoundsAndPropertiesAction (componentToPosition, *this, newBounds, props), "Change component bounds"); + } + else + { + componentToPosition->setBounds (newBounds); + componentToPosition->getProperties() = props; + updateStoredComponentPosition (componentToPosition, false); + changed(); + } + } +} + void ComponentLayout::updateStoredComponentPosition (Component* comp, const bool undoable) { RelativePositionedRectangle newPos (ComponentTypeHandler::getComponentPosition (comp)); diff --git a/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.h b/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.h index d1f659bfd0..8172b15f5d 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.h +++ b/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.h @@ -65,6 +65,7 @@ public: void componentToBack (Component* comp, const bool undoable); void setComponentPosition (Component* comp, const RelativePositionedRectangle& newPos, const bool undoable); + void setComponentBoundsAndProperties (Component* comp, const Rectangle& newBounds, Component* referenceComponent, const bool undoable); void updateStoredComponentPosition (Component* comp, const bool undoable); //============================================================================== @@ -96,6 +97,11 @@ public: void selectedToFront(); void selectedToBack(); + void alignTop(); + void alignRight(); + void alignBottom(); + void alignLeft(); + void startDragging(); void dragSelectedComps (int dxFromDragStart, int dyFromDragStart, const bool allowSnap = true); void endDragging(); diff --git a/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp b/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp index 5540ad09ea..c91444e93e 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp +++ b/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp @@ -221,6 +221,15 @@ void JucerDocument::setInitialSize (int w, int h) } } +void JucerDocument::setLastSelectedTabIndex (int index) +{ + if (index != lastTab) + { + lastTab = index; + flushChangesToDocuments (nullptr); + } +} + //============================================================================== bool JucerDocument::isSnapActive (const bool disableIfCtrlKeyDown) const noexcept { @@ -350,6 +359,7 @@ XmlElement* JucerDocument::createXml() const doc->setAttribute ("fixedSize", fixedSize); doc->setAttribute ("initialWidth", initialWidth); doc->setAttribute ("initialHeight", initialHeight); + doc->setAttribute ("lastSelectedTab", lastTab); if (activeExtraMethods.size() > 0) { @@ -382,6 +392,7 @@ bool JucerDocument::loadFromXml (const XmlElement& xml) fixedSize = xml.getBoolAttribute ("fixedSize", false); initialWidth = xml.getIntAttribute ("initialWidth", 300); initialHeight = xml.getIntAttribute ("initialHeight", 200); + lastTab = xml.getIntAttribute ("lastSelectedTab", 1); snapGridPixels = xml.getIntAttribute ("snapPixels", snapGridPixels); snapActive = xml.getBoolAttribute ("snapActive", snapActive); diff --git a/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.h b/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.h index f69269adc9..e060d55939 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.h +++ b/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.h @@ -93,6 +93,9 @@ public: int getInitialWidth() const noexcept { return initialWidth; } int getInitialHeight() const noexcept { return initialHeight; } + void setLastSelectedTabIndex (int index); + int getLastSelectedTabIndex() const noexcept { return lastTab; } + //============================================================================== virtual int getNumPaintRoutines() const = 0; virtual StringArray getPaintRoutineNames() const = 0; @@ -147,6 +150,7 @@ protected: bool fixedSize = false; int initialWidth = 600, initialHeight = 400; + int lastTab = 1; BinaryResources resources; diff --git a/extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.cpp b/extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.cpp index 6f182bd15c..b35483a7e0 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.cpp +++ b/extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.cpp @@ -376,6 +376,68 @@ void PaintRoutine::selectedToBack() elementToBack (temp.getSelectedItem(i), true); } +void PaintRoutine::alignTop() +{ + if (selectedElements.getNumSelected() > 1) + { + auto* main = selectedElements.getSelectedItem (0); + auto yPos = main->getY(); + + for (auto* other : selectedElements) + { + if (other != main) + other->setPaintElementBoundsAndProperties (other, other->getBounds().withPosition (other->getX(), + yPos), main, true); + } + } +} +void PaintRoutine::alignRight() +{ + if (selectedElements.getNumSelected() > 1) + { + auto* main = selectedElements.getSelectedItem (0); + auto rightPos = main->getRight(); + + for (auto* other : selectedElements) + { + if (other != main) + other->setPaintElementBoundsAndProperties (other, other->getBounds().withPosition (rightPos - other->getWidth(), + other->getY()), main, true); + } + } +} + +void PaintRoutine::alignBottom() +{ + if (selectedElements.getNumSelected() > 1) + { + auto* main = selectedElements.getSelectedItem (0); + auto bottomPos = main->getBottom(); + + for (auto* other : selectedElements) + { + if (other != main) + other->setPaintElementBoundsAndProperties (other, other->getBounds().withPosition (other->getX(), + bottomPos - other->getHeight()), main, true); + } + } +} +void PaintRoutine::alignLeft() +{ + if (selectedElements.getNumSelected() > 1) + { + auto* main = selectedElements.getSelectedItem (0); + auto xPos = main->getX(); + + for (auto* other : selectedElements) + { + if (other != main) + other->setPaintElementBoundsAndProperties (other, other->getBounds().withPosition (xPos, + other->getY()), main, true); + } + } +} + void PaintRoutine::groupSelected() { PaintElementGroup::groupSelected (this); diff --git a/extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.h b/extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.h index 6ffafe83ce..4f040ac356 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.h +++ b/extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.h @@ -83,6 +83,11 @@ public: void selectedToFront(); void selectedToBack(); + void alignTop(); + void alignRight(); + void alignBottom(); + void alignLeft(); + void groupSelected(); void ungroupSelected(); diff --git a/extras/Projucer/Source/ComponentEditor/jucer_UtilityFunctions.h b/extras/Projucer/Source/ComponentEditor/jucer_UtilityFunctions.h index d697977ea1..324ea1598d 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_UtilityFunctions.h +++ b/extras/Projucer/Source/ComponentEditor/jucer_UtilityFunctions.h @@ -88,7 +88,7 @@ inline void drawResizableBorder (Graphics& g, int w, int h, const bool isMouseOver, Colour borderColour) { - g.setColour (borderColour.withAlpha (isMouseOver ? 0.6f : 0.5f)); + g.setColour (borderColour); g.fillRect (0, 0, w, borderSize.getTop()); g.fillRect (0, 0, borderSize.getLeft(), h); diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_ColouredElement.cpp b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_ColouredElement.cpp index cd5350b10e..bc59eb7ad6 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_ColouredElement.cpp +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_ColouredElement.cpp @@ -506,10 +506,12 @@ ColouredElement::~ColouredElement() } //============================================================================== -void ColouredElement::getEditableProperties (Array & props) +void ColouredElement::getEditableProperties (Array & props, bool multipleSelected) { - PaintElement::getEditableProperties (props); - getColourSpecificProperties (props); + PaintElement::getEditableProperties (props, multipleSelected); + + if (! multipleSelected) + getColourSpecificProperties (props); } void ColouredElement::getColourSpecificProperties (Array & props) diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_ColouredElement.h b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_ColouredElement.h index 6ced64ac10..3fb01d1226 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_ColouredElement.h +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_ColouredElement.h @@ -47,7 +47,7 @@ public: ~ColouredElement(); //============================================================================== - void getEditableProperties (Array& props); + void getEditableProperties (Array& props, bool multipleSelected) override; void getColourSpecificProperties (Array& props); //============================================================================== @@ -62,10 +62,10 @@ public: void setStrokeFill (const JucerFillType& newType, const bool undoable); //============================================================================== - Rectangle getCurrentBounds (const Rectangle& parentArea) const; - void setCurrentBounds (const Rectangle& newBounds, const Rectangle& parentArea, const bool undoable); + Rectangle getCurrentBounds (const Rectangle& parentArea) const override; + void setCurrentBounds (const Rectangle& newBounds, const Rectangle& parentArea, const bool undoable) override; - void createSiblingComponents(); + void createSiblingComponents() override; //============================================================================== void addColourAttributes (XmlElement* const e) const; diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.cpp b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.cpp index 102f5cfc8f..082b0ca395 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.cpp +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.cpp @@ -118,6 +118,74 @@ public: RelativePositionedRectangle newState, oldState; }; +class ChangePaintElementBoundsAction : public PaintElementUndoableAction +{ +public: + ChangePaintElementBoundsAction (PaintElement* const element, const Rectangle& bounds) + : PaintElementUndoableAction (element), + newBounds (bounds), + oldBounds (element->getBounds()) + { + } + + bool perform() + { + showCorrectTab(); + getElement()->setBounds (newBounds); + return true; + } + + bool undo() + { + showCorrectTab(); + getElement()->setBounds (oldBounds); + return true; + } + +private: + Rectangle newBounds, oldBounds; +}; + +class ChangePaintElementBoundsAndPropertiesAction : public PaintElementUndoableAction +{ +public: + ChangePaintElementBoundsAndPropertiesAction (PaintElement* const element, const Rectangle& bounds, + const NamedValueSet& props) + : PaintElementUndoableAction (element), + newBounds (bounds), + oldBounds (element->getBounds()), + newProps (props), + oldProps (element->getProperties()) + { + } + + bool perform() + { + showCorrectTab(); + + if (auto* pe = dynamic_cast (getElement()->getParentComponent())) + getElement()->setCurrentBounds (newBounds, pe->getComponentArea(), false); + + getElement()->getProperties() = newProps; + return true; + } + + bool undo() + { + showCorrectTab(); + + if (auto* pe = dynamic_cast (getElement()->getParentComponent())) + getElement()->setCurrentBounds (oldBounds, pe->getComponentArea(), false); + + getElement()->getProperties() = oldProps; + return true; + } + +private: + Rectangle newBounds, oldBounds; + NamedValueSet newProps, oldProps; +}; + void PaintElement::setPosition (const RelativePositionedRectangle& newPosition, const bool undoable) { if (position != newPosition) @@ -137,6 +205,60 @@ void PaintElement::setPosition (const RelativePositionedRectangle& newPosition, } } +void PaintElement::setPaintElementBounds (const Rectangle& newBounds, const bool undoable) +{ + if (getBounds() != newBounds) + { + if (undoable) + { + perform (new ChangePaintElementBoundsAction (this, newBounds), "Change paint element bounds"); + } + else + { + setBounds (newBounds); + changed(); + } + } +} + +void PaintElement::setPaintElementBoundsAndProperties (PaintElement* elementToPosition, const Rectangle& newBounds, + PaintElement* referenceElement, const bool undoable) +{ + auto props = NamedValueSet (elementToPosition->getProperties()); + + auto rect = elementToPosition->getPosition().rect; + auto referenceElementPosition = referenceElement->getPosition(); + auto referenceElementRect = referenceElementPosition.rect; + + rect.setModes (referenceElementRect.getAnchorPointX(), referenceElementRect.getPositionModeX(), + referenceElementRect.getAnchorPointY(), referenceElementRect.getPositionModeY(), + referenceElementRect.getWidthMode(), referenceElementRect.getHeightMode(), + elementToPosition->getBounds()); + + props.set ("pos", rect.toString()); + props.set ("relativeToX", String::toHexString (referenceElementPosition.relativeToX)); + props.set ("relativeToY", String::toHexString (referenceElementPosition.relativeToY)); + props.set ("relativeToW", String::toHexString (referenceElementPosition.relativeToW)); + props.set ("relativeToH", String::toHexString (referenceElementPosition.relativeToH)); + + if (elementToPosition->getBounds() != newBounds || elementToPosition->getProperties() != props) + { + if (undoable) + { + perform (new ChangePaintElementBoundsAndPropertiesAction (elementToPosition, newBounds, props), + "Change paint element bounds"); + } + else + { + if (auto* pe = dynamic_cast (elementToPosition->getParentComponent())) + elementToPosition->setCurrentBounds (newBounds, pe->getComponentArea(), false); + + elementToPosition->getProperties() = props; + owner->changed(); + } + } +} + //============================================================================== Rectangle PaintElement::getCurrentBounds (const Rectangle& parentArea) const { @@ -181,13 +303,17 @@ public: ComponentPositionDimension dimension_) : PositionPropertyBase (e, name, dimension_, true, false, e->getDocument()->getComponentLayout()), - listener (e) + listener (e), + element (e) { listener.setPropertyToRefresh (*this); } void setPosition (const RelativePositionedRectangle& newPos) { + if (element->getOwner()->getSelectedElements().getNumSelected() > 1) + positionOtherSelectedElements (getPosition(), newPos); + listener.owner->setPosition (newPos, true); } @@ -196,12 +322,51 @@ public: return listener.owner->getPosition(); } +private: ElementListener listener; + PaintElement* element; + + void positionOtherSelectedElements (const RelativePositionedRectangle& oldPos, const RelativePositionedRectangle& newPos) + { + for (auto* s : element->getOwner()->getSelectedElements()) + { + if (s != element) + { + auto currentPos = s->getPosition(); + 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); + } + + s->setPosition (currentPos, true); + } + } + } }; //============================================================================== -void PaintElement::getEditableProperties (Array & props) +void PaintElement::getEditableProperties (Array & props, bool multipleSelected) { + ignoreUnused (multipleSelected); + props.add (new ElementPositionProperty (this, "x", PositionPropertyBase::componentX)); props.add (new ElementPositionProperty (this, "y", PositionPropertyBase::componentY)); props.add (new ElementPositionProperty (this, "width", PositionPropertyBase::componentWidth)); @@ -258,10 +423,11 @@ void PaintElement::paint (Graphics& g) if (selected) { const BorderSize borderSize (border->getBorderThickness()); + auto baseColour = findColour (defaultHighlightColourId); drawResizableBorder (g, getWidth(), getHeight(), borderSize, (isMouseOverOrDragging() || border->isMouseOverOrDragging()), - findColour (defaultHighlightColourId)); + baseColour.withAlpha (owner->getSelectedElements().getSelectedItem (0) == this ? 1.0f : 0.3f)); } else if (isMouseOverOrDragging()) { @@ -405,9 +571,32 @@ void PaintElement::applyBoundsToComponent (Component&, Rectangle newBounds) { getDocument()->getUndoManager().undoCurrentTransactionOnly(); + auto dX = newBounds.getX() - getX(); + auto dY = newBounds.getY() - getY(); + auto dW = newBounds.getWidth() - getWidth(); + auto dH = newBounds.getHeight() - getHeight(); + if (auto* pe = dynamic_cast (getParentComponent())) setCurrentBounds (newBounds.expanded (-borderThickness, -borderThickness), - pe->getComponentArea(), true); + pe->getComponentArea(), true); + + if (owner->getSelectedElements().getNumSelected() > 1) + { + for (auto selectedElement : owner->getSelectedElements()) + { + if (selectedElement != this) + { + if (auto* pe = dynamic_cast (selectedElement->getParentComponent())) + { + Rectangle r { selectedElement->getX() + dX, selectedElement->getY() + dY, + selectedElement->getWidth() + dW, selectedElement->getHeight() + dH }; + + selectedElement->setCurrentBounds (r.expanded (-borderThickness, -borderThickness), + pe->getComponentArea(), true); + } + } + } + } } } @@ -481,6 +670,16 @@ void PaintElement::showPopupMenu() m.addCommandItem (commandManager, JucerCommandIDs::toFront); m.addCommandItem (commandManager, JucerCommandIDs::toBack); m.addSeparator(); + + if (owner->getSelectedElements().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); diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.h b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.h index 248b6c10e0..c2c25d28ae 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.h +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.h @@ -56,6 +56,9 @@ public: const RelativePositionedRectangle& getPosition() const; void setPosition (const RelativePositionedRectangle& newPosition, const bool undoable); + void setPaintElementBounds (const Rectangle& newBounds, const bool undoable); + void setPaintElementBoundsAndProperties (PaintElement* elementToPosition, const Rectangle& newBounds, + PaintElement* referenceElement, const bool undoable); void updateBounds (const Rectangle& activeArea); @@ -69,7 +72,7 @@ public: virtual void drawExtraEditorGraphics (Graphics& g, const Rectangle& relativeTo); - virtual void getEditableProperties (Array& props); + virtual void getEditableProperties (Array& props, bool multipleSelected); virtual void showPopupMenu(); diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementEllipse.h b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementEllipse.h index f8e935c45a..e3a8d231d9 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementEllipse.h +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementEllipse.h @@ -38,7 +38,7 @@ public: { } - void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) + void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) override { fillType.setFillType (g, getDocument(), parentArea); @@ -54,13 +54,13 @@ public: } } - void getEditableProperties (Array& props) + void getEditableProperties (Array& props, bool multipleSelected) override { - ColouredElement::getEditableProperties (props); + ColouredElement::getEditableProperties (props, multipleSelected); props.add (new ShapeToPathProperty (this)); } - void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) + void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override { if (fillType.isInvisible() && (strokeType.isInvisible() || ! isStrokePresent)) return; @@ -101,7 +101,7 @@ public: paintMethodCode += s; } - void applyCustomPaintSnippets (StringArray& snippets) + void applyCustomPaintSnippets (StringArray& snippets) override { customPaintCode.clear(); @@ -114,7 +114,7 @@ public: static const char* getTagName() noexcept { return "ELLIPSE"; } - XmlElement* createXml() const + XmlElement* createXml() const override { XmlElement* e = new XmlElement (getTagName()); position.applyToXml (*e); @@ -123,7 +123,7 @@ public: return e; } - bool loadFromXml (const XmlElement& xml) + bool loadFromXml (const XmlElement& xml) override { if (xml.hasTagName (getTagName())) { diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementGroup.h b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementGroup.h index fb926664e5..03aed722fc 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementGroup.h +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementGroup.h @@ -106,11 +106,11 @@ public: } //============================================================================== - void setInitialBounds (int /*parentWidth*/, int /*parentHeight*/) + void setInitialBounds (int /*parentWidth*/, int /*parentHeight*/) override { } - Rectangle getCurrentBounds (const Rectangle& parentArea) const + Rectangle getCurrentBounds (const Rectangle& parentArea) const override { Rectangle r; @@ -125,7 +125,7 @@ public: return r; } - void setCurrentBounds (const Rectangle& b, const Rectangle& parentArea, const bool undoable) + void setCurrentBounds (const Rectangle& b, const Rectangle& parentArea, const bool undoable) override { Rectangle newBounds (b); newBounds.setSize (jmax (1, newBounds.getWidth()), @@ -162,18 +162,19 @@ public: } //============================================================================== - void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) + void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) override { for (int i = 0; i < subElements.size(); ++i) subElements.getUnchecked(i)->draw (g, layout, parentArea); } - void getEditableProperties (Array& props) + void getEditableProperties (Array& props, bool multipleSelected) override { - props.add (new UngroupProperty (this)); + if (! multipleSelected) + props.add (new UngroupProperty (this)); } - void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) + void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override { for (int i = 0; i < subElements.size(); ++i) subElements.getUnchecked(i)->fillInGeneratedCode (code, paintMethodCode); @@ -181,7 +182,7 @@ public: static const char* getTagName() noexcept { return "GROUP"; } - XmlElement* createXml() const + XmlElement* createXml() const override { XmlElement* e = new XmlElement (getTagName()); @@ -194,7 +195,7 @@ public: return e; } - bool loadFromXml (const XmlElement& xml) + bool loadFromXml (const XmlElement& xml) override { if (xml.hasTagName (getTagName())) { @@ -209,7 +210,7 @@ public: return false; } - void applyCustomPaintSnippets (StringArray& snippets) + void applyCustomPaintSnippets (StringArray& snippets) override { for (auto* e : subElements) e->applyCustomPaintSnippets (snippets); diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementImage.h b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementImage.h index 2ca70c810b..5e67db372c 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementImage.h +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementImage.h @@ -58,7 +58,7 @@ public: return nullptr; } - void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) + void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) override { const Rectangle r (position.getRectangle (parentArea, layout)); @@ -83,9 +83,9 @@ public: } //============================================================================== - void getEditableProperties (Array & props) + void getEditableProperties (Array & props, bool multipleSelected) override { - PaintElement::getEditableProperties (props); + PaintElement::getEditableProperties (props, multipleSelected); props.add (new ImageElementResourceProperty (this)); props.add (new StretchModeProperty (this)); @@ -93,7 +93,7 @@ public: props.add (new ResetSizeProperty (this)); } - void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) + void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override { if (opacity > 0) { @@ -177,7 +177,7 @@ public: } } - void applyCustomPaintSnippets (StringArray& snippets) + void applyCustomPaintSnippets (StringArray& snippets) override { customPaintCode.clear(); @@ -362,7 +362,7 @@ public: } //============================================================================== - XmlElement* createXml() const + XmlElement* createXml() const override { XmlElement* e = new XmlElement (getTagName()); position.applyToXml (*e); @@ -373,7 +373,7 @@ public: return e; } - bool loadFromXml (const XmlElement& xml) + bool loadFromXml (const XmlElement& xml) override { if (xml.hasTagName (getTagName())) { diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.cpp b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.cpp index 32318482df..916cfdcd80 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.cpp +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.cpp @@ -349,8 +349,11 @@ void PaintElementPath::pointListChanged() } //============================================================================== -void PaintElementPath::getEditableProperties (Array & props) +void PaintElementPath::getEditableProperties (Array & props, bool multipleSelected) { + if (multipleSelected) + return; + props.add (new PathWindingModeProperty (this)); getColourSpecificProperties (props); } @@ -1453,9 +1456,12 @@ void PathPoint::changePointType (const Path::Iterator::PathElementType newType, } } -void PathPoint::getEditableProperties (Array& props) +void PathPoint::getEditableProperties (Array& props, bool multipleSelected) { - const int index = owner->points.indexOf (this); + if (multipleSelected) + return; + + auto index = owner->points.indexOf (this); jassert (index >= 0); switch (type) diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.h b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.h index 252f0fb346..dd740dff6c 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.h +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.h @@ -52,7 +52,7 @@ public: const bool undoable); void deleteFromPath(); - void getEditableProperties (Array& props); + void getEditableProperties (Array& props, bool multipleSelected); private: PathPoint withChangedPointType (const Path::Iterator::PathElementType newType, @@ -68,9 +68,9 @@ public: ~PaintElementPath(); //============================================================================== - void setInitialBounds (int parentWidth, int parentHeight); - Rectangle getCurrentBounds (const Rectangle& parentArea) const; - void setCurrentBounds (const Rectangle& b, const Rectangle& parentArea, const bool undoable); + void setInitialBounds (int parentWidth, int parentHeight) override; + Rectangle getCurrentBounds (const Rectangle& parentArea) const override; + void setCurrentBounds (const Rectangle& b, const Rectangle& parentArea, const bool undoable) override; //============================================================================== bool getPoint (int index, int pointNumber, double& x, double& y, const Rectangle& parentArea) const; @@ -98,31 +98,31 @@ public: void setNonZeroWinding (const bool nonZero, const bool undoable); //============================================================================== - void getEditableProperties (Array& props); + void getEditableProperties (Array& props, bool multipleSelected) override; - void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode); - void applyCustomPaintSnippets (StringArray& snippets); + void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override; + void applyCustomPaintSnippets (StringArray& snippets) override; //============================================================================== static const char* getTagName() noexcept { return "PATH"; } - XmlElement* createXml() const; - bool loadFromXml (const XmlElement& xml); + XmlElement* createXml() const override; + bool loadFromXml (const XmlElement& xml) override; void setToPath (const Path& p); //============================================================================== - void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea); - void drawExtraEditorGraphics (Graphics& g, const Rectangle& relativeTo); + void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) override; + void drawExtraEditorGraphics (Graphics& g, const Rectangle& relativeTo) override; - void resized(); - void parentSizeChanged(); + void resized() override; + void parentSizeChanged() override; - void mouseDown (const MouseEvent& e); - void mouseDrag (const MouseEvent& e); - void mouseUp (const MouseEvent& e); + void mouseDown (const MouseEvent& e) override; + void mouseDrag (const MouseEvent& e) override; + void mouseUp (const MouseEvent& e) override; - void createSiblingComponents(); - void changed(); + void createSiblingComponents() override; + void changed() override; private: friend class PathPoint; diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRectangle.h b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRectangle.h index 2e083957b7..5a42f56181 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRectangle.h +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRectangle.h @@ -38,17 +38,17 @@ public: { } - Rectangle getCurrentBounds (const Rectangle& parentArea) const + Rectangle getCurrentBounds (const Rectangle& parentArea) const override { return PaintElement::getCurrentBounds (parentArea); // bypass the ColouredElement implementation } - void setCurrentBounds (const Rectangle& newBounds, const Rectangle& parentArea, const bool undoable) + void setCurrentBounds (const Rectangle& newBounds, const Rectangle& parentArea, const bool undoable) override { PaintElement::setCurrentBounds (newBounds, parentArea, undoable); // bypass the ColouredElement implementation } - void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) + void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) override { Component tempParentComp; tempParentComp.setBounds (parentArea); @@ -67,14 +67,14 @@ public: } } - void getEditableProperties (Array & props) + void getEditableProperties (Array & props, bool multipleSelected) override { - ColouredElement::getEditableProperties (props); + ColouredElement::getEditableProperties (props, multipleSelected); props.add (new ShapeToPathProperty (this)); } - void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) + void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override { if (fillType.isInvisible() && (strokeType.isInvisible() || ! isStrokePresent)) return; @@ -114,7 +114,7 @@ public: paintMethodCode += s; } - void applyCustomPaintSnippets (StringArray& snippets) + void applyCustomPaintSnippets (StringArray& snippets) override { customPaintCode.clear(); @@ -127,7 +127,7 @@ public: static const char* getTagName() noexcept { return "RECT"; } - XmlElement* createXml() const + XmlElement* createXml() const override { XmlElement* e = new XmlElement (getTagName()); position.applyToXml (*e); @@ -137,7 +137,7 @@ public: return e; } - bool loadFromXml (const XmlElement& xml) + bool loadFromXml (const XmlElement& xml) override { if (xml.hasTagName (getTagName())) { diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRoundedRectangle.h b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRoundedRectangle.h index b61d877de5..ca069a48de 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRoundedRectangle.h +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRoundedRectangle.h @@ -39,7 +39,7 @@ public: cornerSize = 10.0; } - void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) + void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) override { double x, y, w, h; position.getRectangleDouble (x, y, w, h, parentArea, layout); @@ -56,11 +56,11 @@ public: } } - void getEditableProperties (Array& props) + void getEditableProperties (Array& props, bool multipleSelected) override { props.add (new CornerSizeProperty (this)); - ColouredElement::getEditableProperties (props); + ColouredElement::getEditableProperties (props, multipleSelected); props.add (new ShapeToPathProperty (this)); } @@ -114,7 +114,7 @@ public: double getCornerSize() const noexcept { return cornerSize; } //============================================================================== - void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) + void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override { if (fillType.isInvisible() && (strokeType.isInvisible() || ! isStrokePresent)) return; @@ -156,7 +156,7 @@ public: paintMethodCode += s; } - void applyCustomPaintSnippets (StringArray& snippets) + void applyCustomPaintSnippets (StringArray& snippets) override { customPaintCode.clear(); @@ -169,7 +169,7 @@ public: static const char* getTagName() noexcept { return "ROUNDRECT"; } - XmlElement* createXml() const + XmlElement* createXml() const override { XmlElement* const e = new XmlElement (getTagName()); @@ -180,7 +180,7 @@ public: return e; } - bool loadFromXml (const XmlElement& xml) + bool loadFromXml (const XmlElement& xml) override { if (xml.hasTagName (getTagName())) { diff --git a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementText.h b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementText.h index 6e433a978f..e99ac84861 100644 --- a/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementText.h +++ b/extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementText.h @@ -48,7 +48,7 @@ public: } //============================================================================== - void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) + void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) override { fillType.setFillType (g, getDocument(), parentArea); @@ -66,10 +66,13 @@ public: return s; } - void getEditableProperties (Array& props) + void getEditableProperties (Array& props, bool multipleSelected) override { - ColouredElement::getEditableProperties (props); + ColouredElement::getEditableProperties (props, multipleSelected); + if (multipleSelected) + return; + props.add (new TextProperty (this)); props.add (new FontNameProperty (this)); props.add (new FontStyleProperty (this)); @@ -79,7 +82,7 @@ public: props.add (new TextToPathProperty (this)); } - void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) + void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override { if (! fillType.isInvisible()) { @@ -103,7 +106,7 @@ public: } } - void applyCustomPaintSnippets (StringArray& snippets) + void applyCustomPaintSnippets (StringArray& snippets) override { customPaintCode.clear(); @@ -116,7 +119,7 @@ public: static const char* getTagName() noexcept { return "TEXT"; } - XmlElement* createXml() const + XmlElement* createXml() const override { XmlElement* e = new XmlElement (getTagName()); position.applyToXml (*e); @@ -136,7 +139,7 @@ public: return e; } - bool loadFromXml (const XmlElement& xml) + bool loadFromXml (const XmlElement& xml) override { if (xml.hasTagName (getTagName())) { diff --git a/extras/Projucer/Source/ComponentEditor/ui/jucer_ComponentLayoutPanel.h b/extras/Projucer/Source/ComponentEditor/ui/jucer_ComponentLayoutPanel.h index 6982fad813..9a1b7e4a31 100644 --- a/extras/Projucer/Source/ComponentEditor/ui/jucer_ComponentLayoutPanel.h +++ b/extras/Projucer/Source/ComponentEditor/ui/jucer_ComponentLayoutPanel.h @@ -102,11 +102,13 @@ private: { clear(); - if (layout.getSelectedSet().getNumSelected() == 1) // xxx need to cope with multiple + auto numSelected = layout.getSelectedSet().getNumSelected(); + + if (numSelected > 0) // xxx need to cope with multiple { - if (Component* comp = layout.getSelectedSet().getSelectedItem (0)) - if (ComponentTypeHandler* const type = ComponentTypeHandler::getHandlerFor (*comp)) - type->addPropertiesToPropertyPanel (comp, document, propsPanel); + if (auto* comp = layout.getSelectedSet().getSelectedItem (0)) + if (auto* type = ComponentTypeHandler::getHandlerFor (*comp)) + type->addPropertiesToPropertyPanel (comp, document, propsPanel, numSelected > 1); } } diff --git a/extras/Projucer/Source/ComponentEditor/ui/jucer_ComponentOverlayComponent.cpp b/extras/Projucer/Source/ComponentEditor/ui/jucer_ComponentOverlayComponent.cpp index cf20e6f0d3..17ba21f382 100644 --- a/extras/Projucer/Source/ComponentEditor/ui/jucer_ComponentOverlayComponent.cpp +++ b/extras/Projucer/Source/ComponentEditor/ui/jucer_ComponentOverlayComponent.cpp @@ -81,11 +81,14 @@ void ComponentOverlayComponent::paint (Graphics& g) border->setColour (backgroundColourId, Colours::transparentBlack); if (selected) { + auto selectedItems = layout.getSelectedSet(); + auto baseColour = findColour (defaultHighlightColourId); + const BorderSize borderSize (border->getBorderThickness()); drawResizableBorder (g, getWidth(), getHeight(), borderSize, (isMouseOverOrDragging() || border->isMouseOverOrDragging()), - findColour (defaultHighlightColourId)); + baseColour.withAlpha (selectedItems.getSelectedItem (0) == target ? 1.0f : 0.3f)); } else if (isMouseOverOrDragging()) { @@ -240,6 +243,11 @@ void ComponentOverlayComponent::applyBoundsToComponent (Component& component, Re { layout.getDocument()->getUndoManager().undoCurrentTransactionOnly(); + auto dX = b.getX() - component.getX(); + auto dY = b.getY() - component.getY(); + auto dW = b.getWidth() - component.getWidth(); + auto dH = b.getHeight() - component.getHeight(); + component.setBounds (b); if (auto* parent = target->getParentComponent()) @@ -249,6 +257,18 @@ void ComponentOverlayComponent::applyBoundsToComponent (Component& component, Re b.getHeight() - borderThickness * 2); layout.updateStoredComponentPosition (target, true); + + if (layout.getSelectedSet().getNumSelected() > 1) + { + for (auto s : layout.getSelectedSet()) + { + if (s != target) + { + s->setBounds (s->getX() + dX, s->getY() + dY, s->getWidth() + dW, s->getHeight() + dH); + layout.updateStoredComponentPosition (s, true); + } + } + } } } diff --git a/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerCommandIDs.h b/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerCommandIDs.h index 4b00fed94f..11027570ed 100644 --- a/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerCommandIDs.h +++ b/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerCommandIDs.h @@ -58,6 +58,11 @@ namespace JucerCommandIDs newDocumentBase = 0xf32001, newComponentBase = 0xf30001, - newElementBase = 0xf31001 + newElementBase = 0xf31001, + + alignTop = 0xf33000, + alignRight = 0xf33001, + alignBottom = 0xf33002, + alignLeft = 0xf33003, }; } diff --git a/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.cpp b/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.cpp index f638ecda18..30efe2da13 100644 --- a/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.cpp +++ b/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.cpp @@ -348,7 +348,7 @@ JucerDocumentEditor::JucerDocumentEditor (JucerDocument* const doc) updateTabs(); - tabbedComponent.setCurrentTabIndex (1); + tabbedComponent.setCurrentTabIndex (document->getLastSelectedTabIndex()); document->addChangeListener (this); @@ -361,6 +361,9 @@ JucerDocumentEditor::JucerDocumentEditor (JucerDocument* const doc) JucerDocumentEditor::~JucerDocumentEditor() { + if (document != nullptr) + document->setLastSelectedTabIndex (tabbedComponent.getCurrentTabIndex()); + tabbedComponent.clearTabs(); } @@ -598,15 +601,26 @@ void JucerDocumentEditor::addComponent (const int index) //============================================================================== bool JucerDocumentEditor::isSomethingSelected() const { - if (ComponentLayout* layout = getCurrentLayout()) + if (auto* layout = getCurrentLayout()) return layout->getSelectedSet().getNumSelected() > 0; - if (PaintRoutine* routine = getCurrentPaintRoutine()) + if (auto* routine = getCurrentPaintRoutine()) return routine->getSelectedElements().getNumSelected() > 0; return false; } +bool JucerDocumentEditor::areMultipleThingsSelected() const +{ + if (auto* layout = getCurrentLayout()) + return layout->getSelectedSet().getNumSelected() > 1; + + if (auto* routine = getCurrentPaintRoutine()) + return routine->getSelectedElements().getNumSelected() > 1; + + return false; +} + //============================================================================== void JucerDocumentEditor::getAllCommands (Array & commands) { @@ -630,6 +644,10 @@ void JucerDocumentEditor::getAllCommands (Array & commands) JucerCommandIDs::compOverlay33, JucerCommandIDs::compOverlay66, JucerCommandIDs::compOverlay100, + JucerCommandIDs::alignTop, + JucerCommandIDs::alignRight, + JucerCommandIDs::alignBottom, + JucerCommandIDs::alignLeft, StandardApplicationCommandIDs::undo, StandardApplicationCommandIDs::redo, StandardApplicationCommandIDs::cut, @@ -812,6 +830,34 @@ void JucerDocumentEditor::getCommandInfo (const CommandID commandID, Application } break; + case JucerCommandIDs::alignTop: + result.setInfo (TRANS ("Align top"), + TRANS ("Aligns the top edges of all selected components to the first component that was selected."), + CommandCategories::editing, 0); + result.setActive (areMultipleThingsSelected()); + break; + + case JucerCommandIDs::alignRight: + result.setInfo (TRANS ("Align right"), + TRANS ("Aligns the right edges of all selected components to the first component that was selected."), + CommandCategories::editing, 0); + result.setActive (areMultipleThingsSelected()); + break; + + case JucerCommandIDs::alignBottom: + result.setInfo (TRANS ("Align bottom"), + TRANS ("Aligns the bottom edges of all selected components to the first component that was selected."), + CommandCategories::editing, 0); + result.setActive (areMultipleThingsSelected()); + break; + + case JucerCommandIDs::alignLeft: + result.setInfo (TRANS ("Align left"), + TRANS ("Aligns the left edges of all selected components to the first component that was selected."), + CommandCategories::editing, 0); + result.setActive (areMultipleThingsSelected()); + break; + case StandardApplicationCommandIDs::undo: result.setInfo (TRANS ("Undo"), TRANS ("Undo"), "Editing", 0); result.setActive (document != nullptr && document->getUndoManager().canUndo()); @@ -1005,6 +1051,38 @@ bool JucerDocumentEditor::perform (const InvocationInfo& info) currentPaintRoutine->ungroupSelected(); break; + case JucerCommandIDs::alignTop: + if (currentLayout != nullptr) + currentLayout->alignTop(); + else if (currentPaintRoutine != nullptr) + currentPaintRoutine->alignTop(); + + break; + + case JucerCommandIDs::alignRight: + if (currentLayout != nullptr) + currentLayout->alignRight(); + else if (currentPaintRoutine != nullptr) + currentPaintRoutine->alignRight(); + + break; + + case JucerCommandIDs::alignBottom: + if (currentLayout != nullptr) + currentLayout->alignBottom(); + else if (currentPaintRoutine != nullptr) + currentPaintRoutine->alignBottom(); + + break; + + case JucerCommandIDs::alignLeft: + if (currentLayout != nullptr) + currentLayout->alignLeft(); + else if (currentPaintRoutine != nullptr) + currentPaintRoutine->alignLeft(); + + break; + case StandardApplicationCommandIDs::cut: if (currentLayout != nullptr) { diff --git a/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.h b/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.h index 0318808cbe..3756637588 100644 --- a/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.h +++ b/extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.h @@ -89,6 +89,7 @@ private: double currentZoomLevel = 1.0; bool isSomethingSelected() const; + bool areMultipleThingsSelected() const; // only non-zero if a layout tab is selected ComponentLayout* getCurrentLayout() const; diff --git a/extras/Projucer/Source/ComponentEditor/ui/jucer_PaintRoutinePanel.cpp b/extras/Projucer/Source/ComponentEditor/ui/jucer_PaintRoutinePanel.cpp index acc66fd33e..601e917475 100644 --- a/extras/Projucer/Source/ComponentEditor/ui/jucer_PaintRoutinePanel.cpp +++ b/extras/Projucer/Source/ComponentEditor/ui/jucer_PaintRoutinePanel.cpp @@ -125,14 +125,16 @@ public: if (state != nullptr) propsPanel->restoreOpennessState (*state); - if (paintRoutine.getSelectedElements().getNumSelected() == 1) // xxx need to cope with multiple + auto numSelected = paintRoutine.getSelectedElements().getNumSelected(); + + if (numSelected > 0) // xxx need to cope with multiple { - if (PaintElement* const pe = paintRoutine.getSelectedElements().getSelectedItem (0)) + if (auto* pe = paintRoutine.getSelectedElements().getSelectedItem (0)) { if (paintRoutine.containsElement (pe)) { Array props; - pe->getEditableProperties (props); + pe->getEditableProperties (props, numSelected); propsPanel->addSection (pe->getTypeName(), props); } @@ -141,10 +143,10 @@ public: if (paintRoutine.getSelectedPoints().getNumSelected() == 1) // xxx need to cope with multiple { - if (PathPoint* const point = paintRoutine.getSelectedPoints().getSelectedItem (0)) + if (auto* point = paintRoutine.getSelectedPoints().getSelectedItem (0)) { Array props; - point->getEditableProperties (props); + point->getEditableProperties (props, false); propsPanel->addSection ("Path segment", props); } diff --git a/extras/Projucer/Source/Utility/jucer_ProjucerLookAndFeel.cpp b/extras/Projucer/Source/Utility/jucer_ProjucerLookAndFeel.cpp index 58351b9642..39bf3f50bd 100644 --- a/extras/Projucer/Source/Utility/jucer_ProjucerLookAndFeel.cpp +++ b/extras/Projucer/Source/Utility/jucer_ProjucerLookAndFeel.cpp @@ -571,4 +571,5 @@ void ProjucerLookAndFeel::setupColours() setColour (TreeView::selectedItemBackgroundColourId, findColour (defaultHighlightColourId)); setColour (PopupMenu::highlightedBackgroundColourId, findColour (defaultHighlightColourId).withAlpha (0.75f)); setColour (PopupMenu::highlightedTextColourId, findColour (defaultHighlightedTextColourId)); + setColour (0x1000440, /*LassoComponent::lassoFillColourId*/ findColour (defaultHighlightColourId).withAlpha (0.3f)); }