diff --git a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp index 3da81a2172..ba4d7cb41d 100644 --- a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp +++ b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp @@ -41,7 +41,8 @@ static const char* const metadataTagEnd = "JUCER_" "COMPONENT_METADATA_E //============================================================================== -class ComponentBoundsEditor : public PropertyComponent +class ComponentBoundsEditor : public PropertyComponent, + public ButtonListener { public: enum Type @@ -50,15 +51,28 @@ public: }; //============================================================================== - ComponentBoundsEditor (const String& name, Type type_, const Value& state_) - : PropertyComponent (name, 40), type (type_), state (state_) + ComponentBoundsEditor (ComponentDocument& document_, const String& name, Type type_, + const ValueTree& compState_, const Value& boundsValue_) + : PropertyComponent (name, 40), document (document_), type (type_), + compState (compState_), boundsValue (boundsValue_) { addAndMakeVisible (label = new Label (String::empty, String::empty)); label->setEditable (true, true, false); label->setColour (Label::backgroundColourId, Colours::white); label->setColour (Label::outlineColourId, findColour (ComboBox::outlineColourId)); - label->getTextValue().referTo (Value (new BoundsCoordValueSource (state, type))); + label->getTextValue().referTo (Value (new BoundsCoordValueSource (boundsValue, type))); + + addAndMakeVisible (proportionButton = new TextButton ("%")); + proportionButton->addButtonListener (this); + + addAndMakeVisible (anchorButton1 = new TextButton (String::empty)); + anchorButton1->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnTop | Button::ConnectedOnRight | Button::ConnectedOnBottom); + anchorButton1->addButtonListener (this); + + addAndMakeVisible (anchorButton2 = new TextButton (String::empty)); + anchorButton2->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnTop | Button::ConnectedOnRight | Button::ConnectedOnBottom); + anchorButton2->addButtonListener (this); } ~ComponentBoundsEditor() @@ -68,15 +82,39 @@ public: void resized() { - const Rectangle content (getLookAndFeel().getPropertyComponentContentPosition (*this)); + const Rectangle r (getLookAndFeel().getPropertyComponentContentPosition (*this)); - label->setBounds (content.getX(), content.getY(), content.getWidth(), content.getHeight() / 2); + label->setBounds (r.getX(), r.getY(), r.getWidth() / 2, r.getHeight() / 2); + proportionButton->setBounds (r.getX() + r.getWidth() / 2, r.getY(), + r.getWidth() / 2, r.getHeight() / 2); + anchorButton1->setBounds (r.getX(), r.getY() + r.getHeight() / 2, r.getWidth() / 2, r.getHeight() / 2); + anchorButton2->setBounds (r.getX() + r.getWidth() / 2, r.getY() + r.getHeight() / 2, r.getWidth() / 2, r.getHeight() / 2); } void refresh() { } + void buttonClicked (Button* button) + { + if (button == proportionButton) + { + RectangleCoordinates r (boundsValue.toString()); + Coordinate& coord = getCoord (r); + + ScopedPointer markers (document.createMarkerResolver (compState)); + + coord.toggleProportionality (*markers); + boundsValue = r.toString(); + } + else if (button == anchorButton1) + { + } + else if (button == anchorButton2) + { + } + } + //============================================================================== class BoundsCoordValueSource : public Value::ValueSource, public Value::Listener @@ -94,6 +132,10 @@ public: { RectangleCoordinates r (sourceValue.toString()); Coordinate& coord = getCoord (r); + + if (coord.isProportional()) + return String (coord.getEditableValue()) + "%"; + return coord.getEditableValue(); } @@ -123,26 +165,41 @@ public: Coordinate& getCoord (RectangleCoordinates& r) const { - switch (type) - { - case left: return r.left; - case right: return r.right; - case top: return r.top; - case bottom: return r.bottom; - default: jassertfalse; break; - } - - return r.left; + return getCoordForType (type, r); } BoundsCoordValueSource (const BoundsCoordValueSource&); const BoundsCoordValueSource& operator= (const BoundsCoordValueSource&); }; + static Coordinate& getCoordForType (const Type type, RectangleCoordinates& r) + { + switch (type) + { + case left: return r.left; + case right: return r.right; + case top: return r.top; + case bottom: return r.bottom; + default: jassertfalse; break; + } + + return r.left; + } + private: + ComponentDocument& document; Type type; - Value state; + ValueTree compState; + Value boundsValue; Label* label; + TextButton* proportionButton; + TextButton* anchorButton1; + TextButton* anchorButton2; + + Coordinate& getCoord (RectangleCoordinates& r) + { + return getCoordForType (type, r); + } }; @@ -165,12 +222,9 @@ Value ComponentTypeHandler::getValue (const var::identifier& name, ValueTree& st void ComponentTypeHandler::updateComponent (ComponentDocument& document, Component* comp, const ValueTree& state) { - if (comp->getParentComponent() != 0) - { - RectangleCoordinates pos (state [compBoundsProperty].toString()); - ScopedPointer markers (document.createMarkerResolver (state, comp->getParentComponent())); - comp->setBounds (pos.resolve (*markers)); - } + RectangleCoordinates pos (state [compBoundsProperty].toString()); + ScopedPointer markers (document.createMarkerResolver (state)); + comp->setBounds (pos.resolve (*markers)); comp->setName (state [compNameProperty]); } @@ -188,10 +242,10 @@ void ComponentTypeHandler::initialiseNewItem (ComponentDocument& document, Value void ComponentTypeHandler::createPropertyEditors (ComponentDocument& document, ValueTree& state, Array & props) { - props.add (new ComponentBoundsEditor ("Left", ComponentBoundsEditor::left, getValue (compBoundsProperty, state, document))); - props.add (new ComponentBoundsEditor ("Right", ComponentBoundsEditor::right, getValue (compBoundsProperty, state, document))); - props.add (new ComponentBoundsEditor ("Top", ComponentBoundsEditor::top, getValue (compBoundsProperty, state, document))); - props.add (new ComponentBoundsEditor ("Bottom", ComponentBoundsEditor::bottom, getValue (compBoundsProperty, state, document))); + props.add (new ComponentBoundsEditor (document, "Left", ComponentBoundsEditor::left, state, getValue (compBoundsProperty, state, document))); + props.add (new ComponentBoundsEditor (document, "Right", ComponentBoundsEditor::right, state, getValue (compBoundsProperty, state, document))); + props.add (new ComponentBoundsEditor (document, "Top", ComponentBoundsEditor::top, state, getValue (compBoundsProperty, state, document))); + props.add (new ComponentBoundsEditor (document, "Bottom", ComponentBoundsEditor::bottom, state, getValue (compBoundsProperty, state, document))); } //============================================================================== @@ -415,6 +469,12 @@ void ComponentDocument::checkRootObject() if (getClassName().toString().isEmpty()) getClassName() = "NewComponent"; + + if ((int) getCanvasWidth().getValue() <= 0) + getCanvasWidth() = 640; + + if ((int) getCanvasHeight().getValue() <= 0) + getCanvasHeight() = 480; } //============================================================================== @@ -497,8 +557,10 @@ Component* ComponentDocument::createComponent (int index) class ComponentMarkerResolver : public Coordinate::MarkerResolver { public: - ComponentMarkerResolver (ComponentDocument& doc, const ValueTree& state_, Component* parentComponent_) - : owner (doc), state (state_), parentComponent (parentComponent_) + ComponentMarkerResolver (ComponentDocument& doc, const ValueTree& state_, int parentWidth_, int parentHeight_) + : owner (doc), state (state_), + parentWidth (parentWidth_), + parentHeight (parentHeight_) {} ~ComponentMarkerResolver() {} @@ -509,8 +571,8 @@ public: else if (name == "right") return RectangleCoordinates (state [compBoundsProperty]).right; else if (name == "top") return RectangleCoordinates (state [compBoundsProperty]).top; else if (name == "bottom") return RectangleCoordinates (state [compBoundsProperty]).bottom; - else if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) parentComponent->getWidth(), isHorizontal); - else if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) parentComponent->getHeight(), isHorizontal); + else if (name == Coordinate::parentRightMarkerName) return Coordinate (parentWidth, isHorizontal); + else if (name == Coordinate::parentBottomMarkerName) return Coordinate (parentHeight, isHorizontal); return Coordinate (isHorizontal); } @@ -518,7 +580,7 @@ public: private: ComponentDocument& owner; ValueTree state; - Component* parentComponent; + int parentWidth, parentHeight; }; const RectangleCoordinates ComponentDocument::getCoordsFor (const ValueTree& state) const @@ -526,10 +588,9 @@ const RectangleCoordinates ComponentDocument::getCoordsFor (const ValueTree& sta return RectangleCoordinates (state [compBoundsProperty]); } -Coordinate::MarkerResolver* ComponentDocument::createMarkerResolver (const ValueTree& state, Component* parentComponent) +Coordinate::MarkerResolver* ComponentDocument::createMarkerResolver (const ValueTree& state) { - jassert (parentComponent != 0); - return new ComponentMarkerResolver (*this, state, parentComponent); + return new ComponentMarkerResolver (*this, state, getCanvasWidth().getValue(), getCanvasHeight().getValue()); } void ComponentDocument::updateComponent (Component* comp) @@ -624,8 +685,7 @@ public: const MouseEvent& e, const ResizableBorderComponent::Zone& zone_, Component* parentForOverlays) - : parentComponent (0), - document (document_), + : document (document_), zone (zone_) { for (int i = 0; i < items.size(); ++i) @@ -633,9 +693,6 @@ public: Component* comp = items.getUnchecked(i); jassert (comp != 0); - if (parentComponent == 0) - parentComponent = comp->getParentComponent(); - const ValueTree v (document.getComponentState (comp)); draggedComponents.add (v); @@ -643,7 +700,7 @@ public: { RectangleCoordinates relativePos (v [compBoundsProperty].toString()); - ScopedPointer markers (document.createMarkerResolver (v, parentComponent)); + ScopedPointer markers (document.createMarkerResolver (v)); pos = relativePos.resolve (*markers); originalPositions.add (pos); } @@ -708,7 +765,7 @@ public: const Rectangle newBounds (zone.resizeRectangleBy (originalPos, distance)); RectangleCoordinates pr (v [compBoundsProperty].toString()); - ScopedPointer markers (document.createMarkerResolver (v, parentComponent)); + ScopedPointer markers (document.createMarkerResolver (v)); pr.moveToAbsolute (newBounds, *markers); const String newBoundsString (pr.toString()); @@ -739,7 +796,6 @@ public: } private: - Component* parentComponent; ComponentDocument& document; Array draggedComponents; Array > originalPositions; diff --git a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h index 1bb81896fa..b889ccf93e 100644 --- a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h +++ b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h @@ -49,6 +49,10 @@ public: //============================================================================== Value getClassName() { return getRootValue ("className"); } Value getClassDescription() { return getRootValue ("classDesc"); } + + Value getCanvasWidth() { return root.getPropertyAsValue ("width", 0); } // (deliberately not undoable) + Value getCanvasHeight() { return root.getPropertyAsValue ("height", 0); } + const String getNonExistentMemberName (String suggestedName); //============================================================================== @@ -61,7 +65,7 @@ public: const ValueTree getComponentState (Component* comp) const; void getComponentProperties (Array & props, Component* comp); bool isStateForComponent (const ValueTree& storedState, Component* comp) const; - Coordinate::MarkerResolver* createMarkerResolver (const ValueTree& state, Component* parentComponent); + Coordinate::MarkerResolver* createMarkerResolver (const ValueTree& state); const RectangleCoordinates getCoordsFor (const ValueTree& state) const; void addNewComponentMenuItems (PopupMenu& menu) const; diff --git a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp index 307f1e54eb..5b75b07f42 100644 --- a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp +++ b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp @@ -272,7 +272,8 @@ class ComponentEditor::Canvas : public Component, { public: Canvas (ComponentEditor& editor_) - : editor (editor_), border (14), resizerThickness (4) + : editor (editor_), border (14), resizerThickness (4), + dragStartWidth (0), dragStartHeight (0) { setOpaque (true); addAndMakeVisible (componentHolder = new Component()); @@ -301,48 +302,48 @@ public: g.setFont (border.getBottom() - 5.0f); g.setColour (Colours::grey); g.drawText (String (componentHolder->getWidth()) + " x " + String (componentHolder->getHeight()), - 0, 0, getWidth() - border.getRight(), getHeight(), Justification::bottomRight, false); + 0, 0, jmax (getWidth() - border.getRight(), jmin (60, getWidth())), getHeight(), Justification::bottomRight, false); g.setFont (border.getTop() - 5.0f); g.setColour (Colours::darkgrey); - const int x = border.getLeft(); - const int y = border.getTop(); + g.drawHorizontalLine (border.getTop() - 1, 2.0f, (float) getWidth() - border.getRight()); + g.drawVerticalLine (border.getLeft() - 1, 2.0f, (float) getHeight() - border.getBottom()); + drawXAxis (g, Rectangle (border.getLeft(), 0, componentHolder->getWidth(), border.getTop())); + drawYAxis (g, Rectangle (0, border.getTop(), border.getLeft(), componentHolder->getHeight())); + } - g.drawHorizontalLine (y, 2.0f, (float) getWidth() - border.getRight()); - g.drawVerticalLine (x, 2.0f, (float) getHeight() - border.getBottom()); + void drawXAxis (Graphics& g, const Rectangle& r) + { + TickIterator ticks (0, r.getWidth(), 1.0, 10, 50); + float pos, tickLength; + String label; + + while (ticks.getNextTick (pos, tickLength, label)) { - TickIterator ticks (0, componentHolder->getWidth(), 1.0, 10, 50); - - float pos, tickLength; - String label; - - while (ticks.getNextTick (pos, tickLength, label)) + if (pos > 0) { - if (pos > 0) - { - g.drawVerticalLine (x + (int) pos, y - tickLength * y, (float) y); - g.drawSingleLineText (label, x + (int) pos + 2, (int) y - 6); - } + g.drawVerticalLine (r.getX() + (int) pos, r.getBottom() - tickLength * r.getHeight(), (float) r.getBottom()); + g.drawSingleLineText (label, r.getX() + (int) pos + 2, (int) r.getBottom() - 6); } } + } + void drawYAxis (Graphics& g, const Rectangle& r) + { + TickIterator ticks (0, r.getHeight(), 1.0, 10, 80); + + float pos, tickLength; + String label; + + while (ticks.getNextTick (pos, tickLength, label)) { - TickIterator ticks (0, componentHolder->getHeight(), 1.0, 10, 80); - - float pos, tickLength; - String label; - - while (ticks.getNextTick (pos, tickLength, label)) + if (pos > 0) { - if (pos > 0) - { - g.drawHorizontalLine (y + (int) pos, x - tickLength * x, (float) x); - - g.drawTextAsPath (label, AffineTransform::rotation (float_Pi / -2.0f) - .translated (x - 6.0f, y + pos - 2.0f)); - } + g.drawHorizontalLine (r.getY() + (int) pos, r.getRight() - tickLength * r.getWidth(), (float) r.getRight()); + g.drawTextAsPath (label, AffineTransform::rotation (float_Pi / -2.0f) + .translated (r.getRight() - 6.0f, r.getY() + pos - 2.0f)); } } } @@ -380,6 +381,8 @@ public: void updateComponents() { ComponentDocument& doc = getDocument(); + setSize ((int) doc.getCanvasWidth().getValue() + border.getLeftAndRight(), + (int) doc.getCanvasHeight().getValue() + border.getTopAndBottom()); int i; for (i = componentHolder->getNumChildComponents(); --i >= 0;) @@ -469,19 +472,18 @@ public: void mouseDown (const MouseEvent& e) { updateDragZone (e.getPosition()); - dragStartSize = getBounds(); + dragStartWidth = getDocument().getCanvasWidth().getValue(); + dragStartHeight = getDocument().getCanvasHeight().getValue(); showSizeGuides(); } void mouseDrag (const MouseEvent& e) { - if (dragZone.isDraggingRightEdge() || dragZone.isDraggingBottomEdge()) - { - setSize (dragZone.isDraggingRightEdge() ? jmax (0, dragStartSize.getWidth() + e.getDistanceFromDragStartX()) - : dragStartSize.getWidth(), - dragZone.isDraggingBottomEdge() ? jmax (0, dragStartSize.getHeight() + e.getDistanceFromDragStartY()) - : dragStartSize.getHeight()); - } + if (dragZone.isDraggingRightEdge()) + getDocument().getCanvasWidth() = jmax (1, dragStartWidth + e.getDistanceFromDragStartX()); + + if (dragZone.isDraggingBottomEdge()) + getDocument().getCanvasHeight() = jmax (1, dragStartHeight + e.getDistanceFromDragStartY()); } void mouseUp (const MouseEvent& e) @@ -511,7 +513,7 @@ private: const BorderSize border; const int resizerThickness; ResizableBorderComponent::Zone dragZone; - Rectangle dragStartSize; + int dragStartWidth, dragStartHeight; const Rectangle getContentArea() const { diff --git a/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.cpp b/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.cpp index c2e98e21ef..6ed8b3d87b 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.cpp +++ b/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.cpp @@ -784,6 +784,31 @@ void Coordinate::setEditableValue (const double newValue) value = isProportion ? newValue / 100.0 : newValue; } +void Coordinate::toggleProportionality (MarkerResolver& markerResolver) +{ + const double oldValue = resolve (markerResolver); + + isProportion = ! isProportion; + anchor1 = getOriginMarkerName(); + anchor2 = getExtentMarkerName(); + + moveToAbsolute (oldValue, markerResolver); +} + +void Coordinate::changeAnchor1 (const String& newMarkerName, MarkerResolver& markerResolver) +{ + const double oldValue = resolve (markerResolver); + anchor1 = newMarkerName; + moveToAbsolute (oldValue, markerResolver); +} + +void Coordinate::changeAnchor2 (const String& newMarkerName, MarkerResolver& markerResolver) +{ + const double oldValue = resolve (markerResolver); + anchor2 = newMarkerName; + moveToAbsolute (oldValue, markerResolver); +} + //============================================================================== RectangleCoordinates::RectangleCoordinates() : left (true), right (true), top (false), bottom (false) diff --git a/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.h b/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.h index 310024cb53..b5c048bbe8 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.h @@ -163,6 +163,15 @@ public: const double getEditableValue() const; void setEditableValue (const double newValue); + bool isProportional() const throw() { return isProportion; } + void toggleProportionality (MarkerResolver& markerResolver); + + const String getAnchor1() const { return anchor1; } + void changeAnchor1 (const String& newMarkerName, MarkerResolver& markerResolver); + + const String getAnchor2() const { return anchor2; } + void changeAnchor2 (const String& newMarkerName, MarkerResolver& markerResolver); + //============================================================================== /* Position string formats: diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 7ce496694d..6e17a629d2 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -12019,7 +12019,7 @@ const char* String::toUTF8() const String* const mutableThis = const_cast (this); mutableThis->text = StringHolder::makeUniqueWithSize (mutableThis->text, currentLen + 1 + utf8BytesNeeded / sizeof (juce_wchar)); - char* const otherCopy = reinterpret_cast (text + currentLen); + char* const otherCopy = reinterpret_cast (mutableThis->text + currentLen); copyToUTF8 (otherCopy, std::numeric_limits::max()); return otherCopy; @@ -12210,7 +12210,7 @@ const char* String::toCString() const String* const mutableThis = const_cast (this); mutableThis->text = StringHolder::makeUniqueWithSize (mutableThis->text, (len + 1) * 2); - char* otherCopy = reinterpret_cast (text + len + 1); + char* otherCopy = reinterpret_cast (mutableThis->text + len + 1); CharacterFunctions::copy (otherCopy, text, len); otherCopy [len] = 0; return otherCopy; diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp index 3936ae4644..cf89a4b537 100644 --- a/src/text/juce_String.cpp +++ b/src/text/juce_String.cpp @@ -1931,7 +1931,7 @@ const char* String::toUTF8() const String* const mutableThis = const_cast (this); mutableThis->text = StringHolder::makeUniqueWithSize (mutableThis->text, currentLen + 1 + utf8BytesNeeded / sizeof (juce_wchar)); - char* const otherCopy = reinterpret_cast (text + currentLen); + char* const otherCopy = reinterpret_cast (mutableThis->text + currentLen); copyToUTF8 (otherCopy, std::numeric_limits::max()); return otherCopy; @@ -2123,7 +2123,7 @@ const char* String::toCString() const String* const mutableThis = const_cast (this); mutableThis->text = StringHolder::makeUniqueWithSize (mutableThis->text, (len + 1) * 2); - char* otherCopy = reinterpret_cast (text + len + 1); + char* otherCopy = reinterpret_cast (mutableThis->text + len + 1); CharacterFunctions::copy (otherCopy, text, len); otherCopy [len] = 0; return otherCopy;