|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-9 by Raw Material Software Ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the GNU General
- Public License (Version 2), as published by the Free Software Foundation.
- A copy of the license is included in the JUCE distribution, or can be found
- online at www.gnu.org/licenses.
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.rawmaterialsoftware.com/juce for more information.
-
- ==============================================================================
- */
-
- #include "../../jucer_Headers.h"
- #include "jucer_ComponentEditorCanvas.h"
- #include "jucer_ComponentEditor.h"
-
- const float snapDistance = 8.0f;
- static const Colour alignmentMarkerColour (0x77ff0000);
- static const Colour resizableBorderColour (0x7066aaff);
-
- #include "jucer_ComponentDragOperation.h"
-
-
- //==============================================================================
- class ComponentEditorCanvas::ComponentResizeFrame : public ComponentEditorCanvas::OverlayItemComponent,
- public ComponentListener
- {
- public:
- ComponentResizeFrame (ComponentEditorCanvas& canvas_, Component* componentToAttachTo)
- : OverlayItemComponent (canvas_),
- component (componentToAttachTo),
- borderThickness (4)
- {
- component->addComponentListener (this);
- }
-
- ~ComponentResizeFrame()
- {
- if (component != 0)
- component->removeComponentListener (this);
- }
-
- void paint (Graphics& g)
- {
- g.setColour (resizableBorderColour);
- g.drawRect (0, 0, getWidth(), getHeight(), borderThickness);
- }
-
- void componentMovedOrResized (Component&, bool, bool) { updatePosition(); }
-
- void mouseEnter (const MouseEvent& e) { updateDragZone (e.getPosition()); }
- void mouseExit (const MouseEvent& e) { updateDragZone (e.getPosition()); }
- void mouseMove (const MouseEvent& e) { updateDragZone (e.getPosition()); }
-
- void mouseDown (const MouseEvent& e)
- {
- jassert (component != 0);
-
- if (component != 0)
- {
- updateDragZone (e.getPosition());
- canvas.beginDrag (e, dragZone);
- canvas.showSizeGuides();
- }
- }
-
- void mouseDrag (const MouseEvent& e)
- {
- if (component != 0)
- canvas.continueDrag (e);
- }
-
- void mouseUp (const MouseEvent& e)
- {
- canvas.hideSizeGuides();
-
- if (component != 0)
- canvas.endDrag (e);
-
- updateDragZone (e.getPosition());
- }
-
- bool hitTest (int x, int y)
- {
- return ! getCentreArea().contains (x, y);
- }
-
- void updatePosition()
- {
- if (component != 0)
- setBoundsInTargetSpace (component->getBounds().expanded (borderThickness, borderThickness));
- }
-
- const String getTargetComponentID() const { return component == 0 ? String::empty : ComponentDocument::getJucerIDFor (component); }
-
- //==============================================================================
- class SizeGuideComponent : public OverlayItemComponent,
- public ComponentListener
- {
- public:
- enum Type { left, right, top, bottom };
-
- //==============================================================================
- SizeGuideComponent (ComponentEditorCanvas& canvas_, const ValueTree& state_, Component* component_, Type type_)
- : OverlayItemComponent (canvas_), state (state_), component (component_), type (type_)
- {
- component->addComponentListener (this);
-
- setAlwaysOnTop (true);
- canvas.addAndMakeVisible (this);
- setInterceptsMouseClicks (false, false);
- updatePosition();
- }
-
- ~SizeGuideComponent()
- {
- if (component != 0)
- component->removeComponentListener (this);
- }
-
- //==============================================================================
- void paint (Graphics& g)
- {
- const float dashes[] = { 4.0f, 3.0f };
-
- g.setColour (resizableBorderColour);
- g.drawDashedLine (0.5f, 0.5f, getWidth() - 0.5f, getHeight() - 0.5f, dashes, 2, 1.0f);
- }
-
- void componentMovedOrResized (Component&, bool, bool) { updatePosition(); }
-
- void componentBeingDeleted (Component&)
- {
- setVisible (false);
- component = 0;
- }
-
- //==============================================================================
- void updatePosition()
- {
- if (component != 0)
- {
- RectangleCoordinates coords (getDocument().getCoordsFor (state));
- Coordinate coord (false);
- Rectangle<int> r;
-
- switch (type)
- {
- case left: coord = coords.left; r.setBounds (component->getX(), 0, 1, component->getY()); break;
- case right: coord = coords.right; r.setBounds (component->getRight(), 0, 1, component->getY()); break;
- case top: coord = coords.top; r.setBounds (0, component->getY(), component->getX(), 1); break;
- case bottom: coord = coords.bottom; r.setBounds (0, component->getBottom(), component->getX(), 1); break;
- default: jassertfalse; break;
- }
-
- setBoundsInTargetSpace (r);
- label.update (getParentComponent(), coord.toString(), resizableBorderColour.withAlpha (0.9f), getX(), getY(), type != left, type != top);
- }
- }
-
- private:
- ValueTree state;
- Component* component;
- Type type;
- FloatingLabelComponent label;
- Point<int> lineEnd1, lineEnd2;
- };
-
- void showSizeGuides()
- {
- if (sizeGuides.size() == 0)
- {
- const ValueTree v (getDocument().getComponentState (component));
- sizeGuides.add (new SizeGuideComponent (canvas, v, component, SizeGuideComponent::left));
- sizeGuides.add (new SizeGuideComponent (canvas, v, component, SizeGuideComponent::right));
- sizeGuides.add (new SizeGuideComponent (canvas, v, component, SizeGuideComponent::top));
- sizeGuides.add (new SizeGuideComponent (canvas, v, component, SizeGuideComponent::bottom));
- }
- }
-
- void hideSizeGuides()
- {
- sizeGuides.clear();
- }
-
- private:
- Component::SafePointer<Component> component;
- ResizableBorderComponent::Zone dragZone;
- const int borderThickness;
- OwnedArray <SizeGuideComponent> sizeGuides;
-
- const Rectangle<int> getCentreArea() const
- {
- return getLocalBounds().reduced (borderThickness, borderThickness);
- }
-
- void updateDragZone (const Point<int>& p)
- {
- ResizableBorderComponent::Zone newZone
- = ResizableBorderComponent::Zone::fromPositionOnBorder (getLocalBounds(),
- BorderSize (borderThickness), p);
-
- if (dragZone != newZone)
- {
- dragZone = newZone;
- setMouseCursor (newZone.getMouseCursor());
- }
- }
- };
-
- //==============================================================================
- class ComponentEditorCanvas::MarkerComponent : public ComponentEditorCanvas::OverlayItemComponent,
- public ValueTree::Listener
- {
- public:
- MarkerComponent (ComponentEditorCanvas& canvas_, const ValueTree& marker_, bool isX_, int headSize_)
- : OverlayItemComponent (canvas_), marker (marker_), isX (isX_), headSize (headSize_ - 2),
- dragStartPos (0), isDragging (false)
- {
- marker.addListener (this);
- }
-
- ~MarkerComponent()
- {
- marker.removeListener (this);
- }
-
- void paint (Graphics& g)
- {
- g.setColour (Colours::darkgreen.withAlpha (isMouseOverOrDragging() ? 0.8f : 0.4f));
- g.fillPath (path);
- }
-
- void updatePosition()
- {
- Coordinate coord (getMarkerList().getCoordinate (marker));
- const int pos = roundToInt (coord.resolve (getMarkerList()));
- const int width = 8;
-
- if (isX)
- setBoundsInTargetSpace (Rectangle<int> (pos - width, -headSize, width * 2, getParentHeight()));
- else
- setBoundsInTargetSpace (Rectangle<int> (-headSize, pos - width, getParentWidth(), width * 2));
-
- labelText = "name: " + getMarkerList().getName (marker) + "\nposition: " + coord.toString();
- updateLabel();
- }
-
- void updateLabel()
- {
- if (isMouseOverOrDragging() && (getWidth() > 1 || getHeight() > 1))
- label.update (getParentComponent(), labelText, Colours::darkgreen,
- isX ? getBounds().getCentreX() : getX() + headSize,
- isX ? getY() + headSize : getBounds().getCentreY(), true, true);
- else
- label.remove();
- }
-
- bool hitTest (int x, int y)
- {
- return (isX ? y : x) < headSize;
- }
-
- void resized()
- {
- const float lineThickness = 1.0f;
- path.clear();
-
- if (isX)
- {
- const float centre = getWidth() / 2 + 0.5f;
- path.addLineSegment (centre, 2.0f, centre, getHeight() + 1.0f, lineThickness);
- path.addTriangle (1.0f, 0.0f, centre * 2.0f - 1.0f, 0.0f, centre, headSize + 1.0f);
- }
- else
- {
- const float centre = getHeight() / 2 + 0.5f;
- path.addLineSegment (2.0f, centre, getWidth() + 1.0f, centre, lineThickness);
- path.addTriangle (0.0f, centre * 2.0f - 1.0f, 0.0f, 1.0f, headSize + 1.0f, centre);
- }
-
- updateLabel();
- }
-
- void mouseDown (const MouseEvent& e)
- {
- toFront (false);
- updateLabel();
-
- canvas.getSelection().selectOnly (marker [ComponentDocument::idProperty]);
-
- if (e.mods.isPopupMenu())
- {
- isDragging = false;
- }
- else
- {
- isDragging = true;
- getDocument().beginNewTransaction();
-
- Coordinate coord (getMarkerList().getCoordinate (marker));
- dragStartPos = coord.resolve (getMarkerList());
- }
- }
-
- void mouseDrag (const MouseEvent& e)
- {
- if (isDragging)
- {
- ComponentDocument& doc = getDocument();
- doc.getUndoManager()->undoCurrentTransactionOnly();
-
- Rectangle<int> axis;
- if (isX)
- axis.setBounds (0, 0, getParentWidth(), headSize);
- else
- axis.setBounds (0, 0, headSize, getParentHeight());
-
- if (axis.expanded (30, 30).contains (e.x, e.y))
- {
- Coordinate coord (getMarkerList().getCoordinate (marker));
- coord.moveToAbsolute (jmax (0.0, dragStartPos + (isX ? e.getDistanceFromDragStartX()
- : e.getDistanceFromDragStartY())),
- getMarkerList());
- getMarkerList().setCoordinate (marker, coord);
- }
- else
- {
- getMarkerList().deleteMarker (marker);
- }
- }
- }
-
- void mouseUp (const MouseEvent& e)
- {
- getDocument().beginNewTransaction();
- updateLabel();
- }
-
- void mouseEnter (const MouseEvent& e)
- {
- updateLabel();
- repaint();
- }
-
- void mouseExit (const MouseEvent& e)
- {
- updateLabel();
- repaint();
- }
-
- ComponentDocument::MarkerList& getMarkerList() { return getDocument().getMarkerList (isX); }
-
- void valueTreePropertyChanged (ValueTree&, const var::identifier&) { updatePosition(); }
- void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged) {}
- void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) {}
-
- ValueTree marker;
- const bool isX;
-
- private:
- const int headSize;
- Path path;
- double dragStartPos;
- bool isDragging;
- FloatingLabelComponent label;
- String labelText;
- };
-
- //==============================================================================
- class ComponentEditorCanvas::ComponentHolder : public Component
- {
- public:
- ComponentHolder() {}
- ~ComponentHolder() {}
-
- void updateComponents (ComponentDocument& doc, SelectedItems& selection)
- {
- int i;
- for (i = getNumChildComponents(); --i >= 0;)
- {
- Component* c = getChildComponent (i);
-
- if (! doc.containsComponent (c))
- {
- selection.deselect (ComponentDocument::getJucerIDFor (c));
- delete c;
- }
- }
-
- Array <Component*> componentsInOrder;
-
- const int num = doc.getNumComponents();
- for (i = 0; i < num; ++i)
- {
- const ValueTree v (doc.getComponent (i));
- Component* c = getComponentForState (doc, v);
-
- if (c == 0)
- {
- c = doc.createComponent (i);
- addAndMakeVisible (c);
- }
-
- doc.updateComponent (c);
- componentsInOrder.add (c);
- }
-
- // Make sure the z-order is correct..
- if (num > 0)
- {
- componentsInOrder.getLast()->toFront (false);
-
- for (i = num - 1; --i >= 0;)
- componentsInOrder.getUnchecked(i)->toBehind (componentsInOrder.getUnchecked (i + 1));
- }
- }
-
- Component* getComponentForState (ComponentDocument& doc, const ValueTree& state) const
- {
- for (int i = getNumChildComponents(); --i >= 0;)
- {
- Component* const c = getChildComponent (i);
-
- if (doc.isStateForComponent (state, c))
- return c;
- }
-
- return 0;
- }
-
- Component* findComponentWithID (const String& uid) const
- {
- for (int i = getNumChildComponents(); --i >= 0;)
- {
- Component* const c = getChildComponent(i);
-
- if (ComponentDocument::getJucerIDFor (c) == uid)
- return c;
- }
-
- return 0;
- }
-
- Component* findComponentAt (const Point<int>& pos) const
- {
- for (int i = getNumChildComponents(); --i >= 0;)
- {
- Component* const c = getChildComponent(i);
- if (c->getBounds().contains (pos))
- return c;
- }
-
- return 0;
- }
-
- void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, const Rectangle<int>& lassoArea)
- {
- for (int i = getNumChildComponents(); --i >= 0;)
- {
- Component* c = getChildComponent(i);
- if (c->getBounds().intersects (lassoArea))
- itemsFound.add (ComponentDocument::getJucerIDFor (c));
- }
- }
- };
-
-
- //==============================================================================
- class ComponentEditorCanvas::OverlayComponent : public Component,
- public LassoSource <SelectedItems::ItemType>,
- public ChangeListener,
- public ValueTree::Listener
- {
- public:
- OverlayComponent (ComponentEditorCanvas& canvas_)
- : canvas (canvas_)
- {
- setWantsKeyboardFocus (true);
- canvas.getSelection().addChangeListener (this);
-
- markerRootX = getDocument().getMarkerListX().getGroup();
- markerRootY = getDocument().getMarkerListY().getGroup();
- markerRootX.addListener (this);
- markerRootY.addListener (this);
- }
-
- ~OverlayComponent()
- {
- markerRootX.removeListener (this);
- markerRootY.removeListener (this);
-
- canvas.getSelection().removeChangeListener (this);
-
- lasso = 0;
- deleteAllChildren();
- }
-
- //==============================================================================
- void mouseDown (const MouseEvent& e)
- {
- lasso = 0;
- mouseDownCompUID = String::empty;
- isDraggingClickedComp = false;
-
- Component* underMouse = canvas.getComponentHolder()->findComponentAt (e.getEventRelativeTo (canvas.getComponentHolder()).getPosition());
-
- if (e.mods.isPopupMenu())
- {
- if (underMouse != 0)
- {
- if (! canvas.getSelection().isSelected (ComponentDocument::getJucerIDFor (underMouse)))
- canvas.getSelection().selectOnly (ComponentDocument::getJucerIDFor (underMouse));
- }
-
- PopupMenu m;
-
- if (underMouse != 0)
- {
- m.addCommandItem (commandManager, CommandIDs::toFront);
- m.addCommandItem (commandManager, CommandIDs::toBack);
- m.addSeparator();
- m.addCommandItem (commandManager, StandardApplicationCommandIDs::del);
- const int r = m.show();
- (void) r;
- }
- else
- {
- getDocument().addNewComponentMenuItems (m);
- const int r = m.show();
- getDocument().performNewComponentMenuItem (r);
- }
- }
- else
- {
- if (underMouse == 0 || e.mods.isAltDown())
- {
- canvas.deselectNonComponents();
- addAndMakeVisible (lasso = new LassoComponent <SelectedItems::ItemType>());
- lasso->beginLasso (e, this);
- }
- else
- {
- mouseDownCompUID = ComponentDocument::getJucerIDFor (underMouse);
- canvas.deselectNonComponents();
- mouseDownResult = canvas.getSelection().addToSelectionOnMouseDown (mouseDownCompUID, e.mods);
-
- updateResizeFrames();
- hideSizeGuides();
- showSizeGuides();
- }
- }
- }
-
- void mouseDrag (const MouseEvent& e)
- {
- if (lasso != 0)
- {
- lasso->dragLasso (e);
- }
- else if (mouseDownCompUID.isNotEmpty() && (! e.mouseWasClicked()) && (! e.mods.isPopupMenu()))
- {
- if (! isDraggingClickedComp)
- {
- isDraggingClickedComp = true;
- canvas.getSelection().addToSelectionOnMouseUp (mouseDownCompUID, e.mods, true, mouseDownResult);
- canvas.beginDrag (e, ResizableBorderComponent::Zone (ResizableBorderComponent::Zone::centre));
- }
-
- canvas.continueDrag (e);
- showSizeGuides();
- }
- }
-
- void mouseUp (const MouseEvent& e)
- {
- hideSizeGuides();
-
- if (lasso != 0)
- {
- lasso->endLasso();
- lasso = 0;
-
- if (e.mouseWasClicked())
- canvas.getSelection().deselectAll();
- }
- else if (! e.mods.isPopupMenu())
- {
- if (! isDraggingClickedComp)
- canvas.getSelection().addToSelectionOnMouseUp (mouseDownCompUID, e.mods, ! e.mouseWasClicked(), mouseDownResult);
- }
-
- canvas.endDrag (e);
- }
-
- void mouseDoubleClick (const MouseEvent& e)
- {
- const BorderSize& border = canvas.border;
- const Rectangle<int> xAxis (border.getLeft(), 0, getWidth() - border.getLeftAndRight(), border.getTop());
- const Rectangle<int> yAxis (0, border.getTop(), border.getLeft(), getHeight() - border.getTopAndBottom());
-
- if (xAxis.contains (e.x, e.y))
- {
- getDocument().getMarkerListX().createMarker ("Marker", e.x - xAxis.getX());
- }
- else if (yAxis.contains (e.x, e.y))
- {
- getDocument().getMarkerListY().createMarker ("Marker", e.y - yAxis.getY());
- }
- }
-
- void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, int x, int y, int width, int height)
- {
- canvas.getComponentHolder()->findLassoItemsInArea (itemsFound, Rectangle<int> (x, y, width, height)
- + relativePositionToOtherComponent (canvas.getComponentHolder(), Point<int>()));
- }
-
- SelectedItems& getLassoSelection() { return canvas.getSelection(); }
-
- void resized()
- {
- updateMarkers();
- }
-
- void changeListenerCallback (void*)
- {
- updateResizeFrames();
- }
-
- void modifierKeysChanged (const ModifierKeys&)
- {
- Desktop::getInstance().getMainMouseSource().triggerFakeMove();
- }
-
- void showSizeGuides()
- {
- for (int i = getNumChildComponents(); --i >= 0;)
- {
- ComponentResizeFrame* resizer = dynamic_cast <ComponentResizeFrame*> (getChildComponent(i));
- if (resizer != 0)
- resizer->showSizeGuides();
- }
- }
-
- void hideSizeGuides()
- {
- for (int i = getNumChildComponents(); --i >= 0;)
- {
- ComponentResizeFrame* resizer = dynamic_cast <ComponentResizeFrame*> (getChildComponent(i));
- if (resizer != 0)
- resizer->hideSizeGuides();
- }
- }
-
- void valueTreePropertyChanged (ValueTree&, const var::identifier&) { updateMarkers(); }
- void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged) { updateMarkers(); }
- void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) {}
-
- private:
- //==============================================================================
- ComponentEditorCanvas& canvas;
- ValueTree markerRootX, markerRootY;
- ScopedPointer <LassoComponent <SelectedItems::ItemType> > lasso;
- bool mouseDownResult, isDraggingClickedComp;
- SelectedItems::ItemType mouseDownCompUID;
-
- ComponentDocument& getDocument() { return canvas.getDocument(); }
-
- void updateResizeFrames()
- {
- SelectedItems& selection = canvas.getSelection();
- StringArray requiredIds (canvas.getSelectedIds());
-
- int i;
- for (i = getNumChildComponents(); --i >= 0;)
- {
- ComponentResizeFrame* resizer = dynamic_cast <ComponentResizeFrame*> (getChildComponent(i));
-
- if (resizer != 0)
- {
- if (selection.isSelected (resizer->getTargetComponentID()))
- requiredIds.removeString (resizer->getTargetComponentID());
- else
- delete resizer;
- }
- }
-
- for (i = requiredIds.size(); --i >= 0;)
- {
- Component* c = canvas.getComponentHolder()->findComponentWithID (requiredIds[i]);
-
- if (c != 0)
- {
- ComponentResizeFrame* frame = new ComponentResizeFrame (canvas, c);
- addAndMakeVisible (frame);
- frame->updatePosition();
- }
- }
- }
-
- void updateMarkers (bool isX)
- {
- ComponentDocument& doc = getDocument();
- ComponentDocument::MarkerList& markerList = doc.getMarkerList (isX);
- Array<ValueTree> requiredMarkers;
-
- int i;
- for (i = doc.getMarkerList (isX).size(); --i >= 0;)
- requiredMarkers.add (markerList.getMarker (i));
-
- for (i = getNumChildComponents(); --i >= 0;)
- {
- MarkerComponent* marker = dynamic_cast <MarkerComponent*> (getChildComponent(i));
-
- if (marker != 0 && marker->isX == isX)
- {
- if (requiredMarkers.contains (marker->marker))
- {
- marker->setVisible (true);
- marker->updatePosition();
- requiredMarkers.removeValue (marker->marker);
- }
- else
- {
- if (marker->isMouseButtonDown())
- marker->setBounds (-1, -1, 1, 1);
- else
- delete marker;
- }
- }
- }
-
- for (i = requiredMarkers.size(); --i >= 0;)
- {
- MarkerComponent* marker = new MarkerComponent (canvas, requiredMarkers.getReference(i),
- isX, isX ? canvas.border.getTop()
- : canvas.border.getLeft());
- addAndMakeVisible (marker);
- marker->updatePosition();
- }
- }
-
- void updateMarkers()
- {
- updateMarkers (true);
- updateMarkers (false);
- }
- };
-
- //==============================================================================
- class ComponentEditorCanvas::WholeComponentResizer : public Component
- {
- public:
- WholeComponentResizer (ComponentEditorCanvas& canvas_)
- : canvas (canvas_), dragStartWidth (0), dragStartHeight (0), resizerThickness (4)
- {
- }
-
- ~WholeComponentResizer()
- {
- }
-
- void paint (Graphics& g)
- {
- const Rectangle<int> content (getContentArea());
-
- g.setColour (Colour::greyLevel (0.7f).withAlpha (0.4f));
- g.drawRect (content.expanded (resizerThickness, resizerThickness), resizerThickness);
-
- const int bottomGap = getHeight() - content.getBottom();
- g.setFont (bottomGap - 5.0f);
-
- g.setColour (Colours::grey);
- g.drawText (String (content.getWidth()) + " x " + String (content.getHeight()),
- 0, 0, jmax (content.getRight(), jmin (60, getWidth())), getHeight(), Justification::bottomRight, false);
- }
-
- void mouseMove (const MouseEvent& e)
- {
- updateDragZone (e.getPosition());
- }
-
- void mouseDown (const MouseEvent& e)
- {
- updateDragZone (e.getPosition());
- dragStartWidth = getDocument().getCanvasWidth().getValue();
- dragStartHeight = getDocument().getCanvasHeight().getValue();
- canvas.showSizeGuides();
- }
-
- void mouseDrag (const MouseEvent& e)
- {
- 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)
- {
- canvas.hideSizeGuides();
- updateDragZone (e.getPosition());
- }
-
- void updateDragZone (const Point<int>& p)
- {
- ResizableBorderComponent::Zone newZone
- = ResizableBorderComponent::Zone::fromPositionOnBorder (getContentArea().expanded (resizerThickness, resizerThickness),
- BorderSize (0, 0, resizerThickness, resizerThickness), p);
-
- if (dragZone != newZone)
- {
- dragZone = newZone;
- setMouseCursor (newZone.getMouseCursor());
- }
- }
-
- bool hitTest (int x, int y)
- {
- const Rectangle<int> content (getContentArea());
-
- return (x >= content.getRight() || y >= content.getBottom())
- && (! content.contains (x, y))
- && content.expanded (resizerThickness, resizerThickness).contains (x, y);
- }
-
- private:
- ComponentEditorCanvas& canvas;
- ResizableBorderComponent::Zone dragZone;
- int dragStartWidth, dragStartHeight;
- const int resizerThickness;
-
- ComponentDocument& getDocument() { return canvas.getDocument(); }
- const Rectangle<int> getContentArea() const { return canvas.getContentArea(); }
- };
-
-
- //==============================================================================
- ComponentEditorCanvas::ComponentEditorCanvas (ComponentEditor& editor_)
- : editor (editor_), border (14)
- {
- setOpaque (true);
- addAndMakeVisible (componentHolder = new ComponentHolder());
- addAndMakeVisible (overlay = new OverlayComponent (*this));
- overlay->addAndMakeVisible (resizeFrame = new WholeComponentResizer (*this));
-
- setSize (500, 500);
-
- getDocument().getRoot().addListener (this);
- updateComponents();
- }
-
- ComponentEditorCanvas::~ComponentEditorCanvas()
- {
- dragger = 0;
- getDocument().getRoot().removeListener (this);
- componentHolder->deleteAllChildren();
- deleteAllChildren();
- }
-
- //==============================================================================
- ComponentEditor& ComponentEditorCanvas::getEditor() { return editor; }
- ComponentDocument& ComponentEditorCanvas::getDocument() { return editor.getDocument(); }
- ComponentEditorCanvas::SelectedItems& ComponentEditorCanvas::getSelection() { return selection; }
- ComponentEditorCanvas::ComponentHolder* ComponentEditorCanvas::getComponentHolder() const { return componentHolder; }
-
- void ComponentEditorCanvas::timerCallback()
- {
- stopTimer();
-
- if (! Component::isMouseButtonDownAnywhere())
- getDocument().beginNewTransaction();
- }
-
- //==============================================================================
- void ComponentEditorCanvas::paint (Graphics& g)
- {
- g.fillAll (Colours::white);
-
- g.setFont (border.getTop() - 5.0f);
- g.setColour (Colours::darkgrey);
-
- 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<int> (border.getLeft(), 0, componentHolder->getWidth(), border.getTop()));
- drawYAxis (g, Rectangle<int> (0, border.getTop(), border.getLeft(), componentHolder->getHeight()));
- }
-
- void ComponentEditorCanvas::drawXAxis (Graphics& g, const Rectangle<int>& r)
- {
- TickIterator ticks (0, r.getWidth(), 1.0, 10, 50);
- float pos, tickLength;
- String label;
-
- while (ticks.getNextTick (pos, tickLength, label))
- {
- if (pos > 0)
- {
- 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 ComponentEditorCanvas::drawYAxis (Graphics& g, const Rectangle<int>& r)
- {
- TickIterator ticks (0, r.getHeight(), 1.0, 10, 80);
- float pos, tickLength;
- String label;
-
- while (ticks.getNextTick (pos, tickLength, label))
- {
- if (pos > 0)
- {
- 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));
- }
- }
- }
-
- const Rectangle<int> ComponentEditorCanvas::getContentArea() const
- {
- return border.subtractedFrom (getLocalBounds());
- }
-
- //==============================================================================
- void ComponentEditorCanvas::resized()
- {
- componentHolder->setBounds (getContentArea());
- overlay->setBounds (getLocalBounds());
- resizeFrame->setBounds (getLocalBounds());
- updateComponents();
- }
-
- void ComponentEditorCanvas::updateComponents()
- {
- setSize ((int) getDocument().getCanvasWidth().getValue() + border.getLeftAndRight(),
- (int) getDocument().getCanvasHeight().getValue() + border.getTopAndBottom());
-
- componentHolder->updateComponents (getDocument(), selection);
- startTimer (500);
- }
-
- //==============================================================================
- const StringArray ComponentEditorCanvas::getSelectedIds() const
- {
- StringArray ids;
- const int num = selection.getNumSelected();
- for (int i = 0; i < num; ++i)
- ids.add (selection.getSelectedItem(i));
-
- return ids;
- }
-
- void ComponentEditorCanvas::getSelectedItemProperties (Array <PropertyComponent*>& props)
- {
- getDocument().createItemProperties (props, getSelectedIds());
- }
-
- void ComponentEditorCanvas::deleteSelection()
- {
- getDocument().beginNewTransaction();
-
- for (int i = selection.getNumSelected(); --i >= 0;)
- {
- Component* c = componentHolder->findComponentWithID (selection.getSelectedItem (0));
-
- if (c != 0)
- getDocument().removeComponent (getDocument().getComponentState (c));
- }
-
- selection.deselectAll();
-
- getDocument().beginNewTransaction();
- }
-
- void ComponentEditorCanvas::deselectNonComponents()
- {
- for (int i = getSelection().getNumSelected(); --i >= 0;)
- if (! getDocument().getComponentWithID (getSelection().getSelectedItem (i)).isValid())
- getSelection().deselect (getSelection().getSelectedItem (i));
- }
-
- void ComponentEditorCanvas::selectionToFront()
- {
- getDocument().beginNewTransaction();
-
- int index = 0;
- for (int i = getDocument().getNumComponents(); --i >= 0;)
- {
- const ValueTree comp (getDocument().getComponent (index));
- Component* c = componentHolder->getComponentForState (getDocument(), comp);
-
- if (c != 0 && selection.isSelected (ComponentDocument::getJucerIDFor (c)))
- {
- ValueTree parent (comp.getParent());
- parent.moveChild (parent.indexOf (comp), -1, getDocument().getUndoManager());
- }
- else
- {
- ++index;
- }
- }
-
- getDocument().beginNewTransaction();
- }
-
- void ComponentEditorCanvas::selectionToBack()
- {
- getDocument().beginNewTransaction();
-
- int index = getDocument().getNumComponents() - 1;
- for (int i = getDocument().getNumComponents(); --i >= 0;)
- {
- const ValueTree comp (getDocument().getComponent (index));
- Component* c = componentHolder->getComponentForState (getDocument(), comp);
-
- if (c != 0 && selection.isSelected (ComponentDocument::getJucerIDFor (c)))
- {
- ValueTree parent (comp.getParent());
- parent.moveChild (parent.indexOf (comp), 0, getDocument().getUndoManager());
- }
- else
- {
- --index;
- }
- }
-
- getDocument().beginNewTransaction();
- }
-
- //==============================================================================
- void ComponentEditorCanvas::showSizeGuides() { overlay->showSizeGuides(); }
- void ComponentEditorCanvas::hideSizeGuides() { overlay->hideSizeGuides(); }
-
-
- //==============================================================================
- const Array<Component*> ComponentEditorCanvas::getSelectedComps() const
- {
- Array<Component*> comps;
-
- for (int i = 0; i < selection.getNumSelected(); ++i)
- {
- Component* c = componentHolder->findComponentWithID (selection.getSelectedItem (i));
- jassert (c != 0);
- if (c != 0)
- comps.add (c);
- }
-
- return comps;
- }
-
- const Array<Component*> ComponentEditorCanvas::getUnselectedComps() const
- {
- Array<Component*> comps;
-
- for (int i = componentHolder->getNumChildComponents(); --i >= 0;)
- if (! selection.isSelected (ComponentDocument::getJucerIDFor (componentHolder->getChildComponent(i))))
- comps.add (componentHolder->getChildComponent(i));
-
- return comps;
- }
-
- //==============================================================================
- void ComponentEditorCanvas::beginDrag (const MouseEvent& e, const ResizableBorderComponent::Zone& zone)
- {
- dragger = new DragOperation (*this, getSelectedComps(), getUnselectedComps(), e, overlay, zone);
- }
-
- void ComponentEditorCanvas::continueDrag (const MouseEvent& e)
- {
- if (dragger != 0)
- dragger->drag (e);
- }
-
- void ComponentEditorCanvas::endDrag (const MouseEvent& e)
- {
- if (dragger != 0)
- {
- dragger->drag (e);
- dragger = 0;
- }
- }
-
- //==============================================================================
- ComponentEditorCanvas::OverlayItemComponent::OverlayItemComponent (ComponentEditorCanvas& canvas_)
- : canvas (canvas_)
- {
- }
-
- void ComponentEditorCanvas::OverlayItemComponent::setBoundsInTargetSpace (const Rectangle<int>& r)
- {
- setBounds (r + canvas.getComponentHolder()->relativePositionToOtherComponent (getParentComponent(), Point<int>()));
- }
|