mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Small tweaks to InterprocessLock. Jucer development.
This commit is contained in:
parent
9d5954c08d
commit
5673b7ed5d
16 changed files with 750 additions and 183 deletions
|
|
@ -36,24 +36,24 @@ public:
|
|||
Component* createComponent() { return new TextButton (String::empty); }
|
||||
const Rectangle<int> getDefaultSize() { return Rectangle<int> (0, 0, 150, 24); }
|
||||
|
||||
void updateComponent (Component* comp, const ValueTree& state)
|
||||
void updateComponent (ComponentDocument& document, Component* comp, const ValueTree& state)
|
||||
{
|
||||
TextButton* tb = dynamic_cast <TextButton*> (comp);
|
||||
jassert (tb != 0);
|
||||
|
||||
ComponentTypeHandler::updateComponent (comp, state);
|
||||
ComponentTypeHandler::updateComponent (document, comp, state);
|
||||
tb->setButtonText (state ["text"].toString());
|
||||
}
|
||||
|
||||
void initialiseNewItem (ValueTree& state, ComponentDocument& document)
|
||||
void initialiseNewItem (ComponentDocument& document, ValueTree& state)
|
||||
{
|
||||
ComponentTypeHandler::initialiseNewItem (state, document);
|
||||
ComponentTypeHandler::initialiseNewItem (document, state);
|
||||
state.setProperty ("text", "New Toggle Button", 0);
|
||||
}
|
||||
|
||||
void createPropertyEditors (ValueTree& state, ComponentDocument& document, Array <PropertyComponent*>& props)
|
||||
void createPropertyEditors (ComponentDocument& document, ValueTree& state, Array <PropertyComponent*>& props)
|
||||
{
|
||||
ComponentTypeHandler::createPropertyEditors (state, document, props);
|
||||
ComponentTypeHandler::createPropertyEditors (document, state, props);
|
||||
props.add (new TextPropertyComponent (getValue ("text", state, document), "Button Text", 1024, false));
|
||||
props.getLast()->setTooltip ("The button's text.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,24 +36,24 @@ public:
|
|||
Component* createComponent() { return new ToggleButton (String::empty); }
|
||||
const Rectangle<int> getDefaultSize() { return Rectangle<int> (0, 0, 180, 24); }
|
||||
|
||||
void updateComponent (Component* comp, const ValueTree& state)
|
||||
void updateComponent (ComponentDocument& document, Component* comp, const ValueTree& state)
|
||||
{
|
||||
ToggleButton* tb = dynamic_cast <ToggleButton*> (comp);
|
||||
jassert (tb != 0);
|
||||
|
||||
ComponentTypeHandler::updateComponent (comp, state);
|
||||
ComponentTypeHandler::updateComponent (document, comp, state);
|
||||
tb->setButtonText (state ["text"].toString());
|
||||
}
|
||||
|
||||
void initialiseNewItem (ValueTree& state, ComponentDocument& document)
|
||||
void initialiseNewItem (ComponentDocument& document, ValueTree& state)
|
||||
{
|
||||
ComponentTypeHandler::initialiseNewItem (state, document);
|
||||
ComponentTypeHandler::initialiseNewItem (document, state);
|
||||
state.setProperty ("text", "New Toggle Button", 0);
|
||||
}
|
||||
|
||||
void createPropertyEditors (ValueTree& state, ComponentDocument& document, Array <PropertyComponent*>& props)
|
||||
void createPropertyEditors (ComponentDocument& document, ValueTree& state, Array <PropertyComponent*>& props)
|
||||
{
|
||||
ComponentTypeHandler::createPropertyEditors (state, document, props);
|
||||
ComponentTypeHandler::createPropertyEditors (document, state, props);
|
||||
props.add (new TextPropertyComponent (getValue ("text", state, document), "Button Text", 1024, false));
|
||||
props.getLast()->setTooltip ("The button's text.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,28 +57,30 @@ Value ComponentTypeHandler::getValue (const var::identifier& name, ValueTree& st
|
|||
return state.getPropertyAsValue (name, document.getUndoManager());
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::updateComponent (Component* comp, const ValueTree& state)
|
||||
void ComponentTypeHandler::updateComponent (ComponentDocument& document, Component* comp, const ValueTree& state)
|
||||
{
|
||||
if (comp->getParentComponent() != 0)
|
||||
{
|
||||
PositionedRectangle pos (state [compBoundsProperty].toString());
|
||||
comp->setBounds (pos.getRectangle (comp->getParentComponent()->getLocalBounds()));
|
||||
RectangleCoordinates pos (state [compBoundsProperty].toString());
|
||||
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (state, comp->getParentComponent()));
|
||||
comp->setBounds (pos.resolve (*markers));
|
||||
}
|
||||
|
||||
comp->setName (state [compNameProperty]);
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::initialiseNewItem (ValueTree& state, ComponentDocument& document)
|
||||
void ComponentTypeHandler::initialiseNewItem (ComponentDocument& document, ValueTree& state)
|
||||
{
|
||||
state.setProperty (compNameProperty, String::empty, 0);
|
||||
state.setProperty (memberNameProperty, document.getNonExistentMemberName (getMemberNameRoot()), 0);
|
||||
state.setProperty (compBoundsProperty,
|
||||
getDefaultSize().withPosition (Point<int> (Random::getSystemRandom().nextInt (100) + 100,
|
||||
Random::getSystemRandom().nextInt (100) + 100)).toString(), 0);
|
||||
|
||||
const Rectangle<int> bounds (getDefaultSize().withPosition (Point<int> (Random::getSystemRandom().nextInt (100) + 100,
|
||||
Random::getSystemRandom().nextInt (100) + 100)));
|
||||
|
||||
state.setProperty (compBoundsProperty, RectangleCoordinates (bounds).toString(), 0);
|
||||
}
|
||||
|
||||
void ComponentTypeHandler::createPropertyEditors (ValueTree& state, ComponentDocument& document,
|
||||
Array <PropertyComponent*>& props)
|
||||
void ComponentTypeHandler::createPropertyEditors (ComponentDocument& document, ValueTree& state, Array <PropertyComponent*>& props)
|
||||
{
|
||||
props.add (new TextPropertyComponent (getValue (compBoundsProperty, state, document), "Bounds", 512, false));
|
||||
props.getLast()->setTooltip ("The component's position.");
|
||||
|
|
@ -100,7 +102,7 @@ public:
|
|||
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (ComponentTypeManager);
|
||||
|
||||
Component* createFromStoredType (const ValueTree& value)
|
||||
Component* createFromStoredType (ComponentDocument& document, const ValueTree& value)
|
||||
{
|
||||
ComponentTypeHandler* handler = getHandlerFor (value.getType());
|
||||
if (handler == 0)
|
||||
|
|
@ -108,7 +110,7 @@ public:
|
|||
|
||||
Component* c = handler->createComponent();
|
||||
if (c != 0)
|
||||
handler->updateComponent (c, value);
|
||||
handler->updateComponent (document, c, value);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
|
@ -331,7 +333,7 @@ void ComponentDocument::performNewComponentMenuItem (int menuResultCode)
|
|||
{
|
||||
ValueTree state (handler->getXmlTag());
|
||||
state.setProperty (idProperty, createAlphaNumericUID(), 0);
|
||||
handler->initialiseNewItem (state, *this);
|
||||
handler->initialiseNewItem (*this, state);
|
||||
|
||||
getComponentGroup().addChild (state, -1, getUndoManager());
|
||||
}
|
||||
|
|
@ -368,13 +370,13 @@ const ValueTree ComponentDocument::getComponentWithMemberName (const String& nam
|
|||
return ValueTree::invalid;
|
||||
}
|
||||
|
||||
Component* ComponentDocument::createComponent (int index) const
|
||||
Component* ComponentDocument::createComponent (int index)
|
||||
{
|
||||
const ValueTree v (getComponentGroup().getChild (index));
|
||||
|
||||
if (v.isValid())
|
||||
{
|
||||
Component* c = ComponentTypeManager::getInstance()->createFromStoredType (v);
|
||||
Component* c = ComponentTypeManager::getInstance()->createFromStoredType (*this, v);
|
||||
c->getProperties().set (idProperty, v[idProperty]);
|
||||
jassert (c->getProperties()[idProperty].toString().isNotEmpty());
|
||||
return c;
|
||||
|
|
@ -383,7 +385,46 @@ Component* ComponentDocument::createComponent (int index) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ComponentDocument::updateComponent (Component* comp) const
|
||||
//==============================================================================
|
||||
class ComponentMarkerResolver : public Coordinate::MarkerResolver
|
||||
{
|
||||
public:
|
||||
ComponentMarkerResolver (ComponentDocument& doc, const ValueTree& state_, Component* parentComponent_)
|
||||
: owner (doc), state (state_), parentComponent (parentComponent_)
|
||||
{}
|
||||
|
||||
~ComponentMarkerResolver() {}
|
||||
|
||||
const Coordinate findMarker (const String& name, bool isHorizontal)
|
||||
{
|
||||
if (name == "left") return RectangleCoordinates (state [compBoundsProperty]).left;
|
||||
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);
|
||||
|
||||
return Coordinate (isHorizontal);
|
||||
}
|
||||
|
||||
private:
|
||||
ComponentDocument& owner;
|
||||
ValueTree state;
|
||||
Component* parentComponent;
|
||||
};
|
||||
|
||||
const RectangleCoordinates ComponentDocument::getCoordsFor (const ValueTree& state) const
|
||||
{
|
||||
return RectangleCoordinates (state [compBoundsProperty]);
|
||||
}
|
||||
|
||||
Coordinate::MarkerResolver* ComponentDocument::createMarkerResolver (const ValueTree& state, Component* parentComponent)
|
||||
{
|
||||
jassert (parentComponent != 0);
|
||||
return new ComponentMarkerResolver (*this, state, parentComponent);
|
||||
}
|
||||
|
||||
void ComponentDocument::updateComponent (Component* comp)
|
||||
{
|
||||
const ValueTree v (getComponentState (comp));
|
||||
|
||||
|
|
@ -393,7 +434,7 @@ void ComponentDocument::updateComponent (Component* comp) const
|
|||
jassert (handler != 0);
|
||||
|
||||
if (handler != 0)
|
||||
handler->updateComponent (comp, v);
|
||||
handler->updateComponent (*this, comp, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -431,7 +472,7 @@ void ComponentDocument::getComponentProperties (Array <PropertyComponent*>& prop
|
|||
jassert (handler != 0);
|
||||
|
||||
if (handler != 0)
|
||||
handler->createPropertyEditors (v, *this, props);
|
||||
handler->createPropertyEditors (*this, v, props);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -473,8 +514,10 @@ public:
|
|||
DragHandler (ComponentDocument& document_,
|
||||
const Array<Component*>& items,
|
||||
const MouseEvent& e,
|
||||
const ResizableBorderComponent::Zone& zone_)
|
||||
: document (document_),
|
||||
const ResizableBorderComponent::Zone& zone_,
|
||||
Component* parentForOverlays)
|
||||
: parentComponent (0),
|
||||
document (document_),
|
||||
zone (zone_)
|
||||
{
|
||||
for (int i = 0; i < items.size(); ++i)
|
||||
|
|
@ -482,14 +525,20 @@ public:
|
|||
Component* comp = items.getUnchecked(i);
|
||||
jassert (comp != 0);
|
||||
|
||||
parentComponentSize.setSize (comp->getParentWidth(), comp->getParentHeight());
|
||||
jassert (! parentComponentSize.isEmpty());
|
||||
if (parentComponent == 0)
|
||||
parentComponent = comp->getParentComponent();
|
||||
|
||||
const ValueTree v (document.getComponentState (comp));
|
||||
draggedComponents.add (v);
|
||||
|
||||
PositionedRectangle pos (v [compBoundsProperty].toString());
|
||||
originalPositions.add (pos.getRectangle (parentComponentSize));
|
||||
Rectangle<int> pos;
|
||||
|
||||
{
|
||||
RectangleCoordinates relativePos (v [compBoundsProperty].toString());
|
||||
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (v, parentComponent));
|
||||
pos = relativePos.resolve (*markers);
|
||||
originalPositions.add (pos);
|
||||
}
|
||||
|
||||
const Rectangle<float> floatPos ((float) pos.getX(), (float) pos.getY(),
|
||||
(float) pos.getWidth(), (float) pos.getHeight());
|
||||
|
|
@ -525,18 +574,42 @@ public:
|
|||
{
|
||||
document.getUndoManager()->undoCurrentTransactionOnly();
|
||||
|
||||
for (int i = 0; i < draggedComponents.size(); ++i)
|
||||
move (draggedComponents.getReference(i), e.getOffsetFromDragStart(), originalPositions.getReference(i));
|
||||
for (int n = 50;;)
|
||||
{
|
||||
// Need to repeatedly apply the new positions until they all settle down, in case some of
|
||||
// the coords are relative to each other..
|
||||
bool anyUpdated = false;
|
||||
|
||||
for (int i = 0; i < draggedComponents.size(); ++i)
|
||||
if (dragItem (draggedComponents.getReference(i), e.getOffsetFromDragStart(), originalPositions.getReference(i)))
|
||||
anyUpdated = true;
|
||||
|
||||
if (! anyUpdated)
|
||||
break;
|
||||
|
||||
if (--n == 0)
|
||||
{
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void move (ValueTree& v, const Point<int>& distance, const Rectangle<int>& originalPos)
|
||||
bool dragItem (ValueTree& v, const Point<int>& distance, const Rectangle<int>& originalPos)
|
||||
{
|
||||
Rectangle<int> newBounds (zone.resizeRectangleBy (originalPos, distance));
|
||||
const Rectangle<int> newBounds (zone.resizeRectangleBy (originalPos, distance));
|
||||
|
||||
PositionedRectangle pr (v [compBoundsProperty].toString());
|
||||
pr.updateFrom (newBounds, parentComponentSize);
|
||||
RectangleCoordinates pr (v [compBoundsProperty].toString());
|
||||
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (v, parentComponent));
|
||||
|
||||
v.setProperty (compBoundsProperty, pr.toString(), document.getUndoManager());
|
||||
pr.moveToAbsolute (newBounds, *markers);
|
||||
const String newBoundsString (pr.toString());
|
||||
|
||||
if (v[compBoundsProperty] == newBoundsString)
|
||||
return false;
|
||||
|
||||
v.setProperty (compBoundsProperty, newBoundsString, document.getUndoManager());
|
||||
return true;
|
||||
}
|
||||
|
||||
const Array<float> getVerticalSnapPositions (const Point<int>& distance) const
|
||||
|
|
@ -558,7 +631,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
Rectangle<int> parentComponentSize;
|
||||
Component* parentComponent;
|
||||
ComponentDocument& document;
|
||||
Array <ValueTree> draggedComponents;
|
||||
Array <Rectangle<int> > originalPositions;
|
||||
|
|
@ -566,9 +639,10 @@ private:
|
|||
const ResizableBorderComponent::Zone zone;
|
||||
};
|
||||
|
||||
void ComponentDocument::beginDrag (const Array<Component*>& items, const MouseEvent& e, const ResizableBorderComponent::Zone& zone)
|
||||
void ComponentDocument::beginDrag (const Array<Component*>& items, const MouseEvent& e,
|
||||
Component* parentForOverlays, const ResizableBorderComponent::Zone& zone)
|
||||
{
|
||||
dragger = new DragHandler (*this, items, e, zone);
|
||||
dragger = new DragHandler (*this, items, e, zone, parentForOverlays);
|
||||
}
|
||||
|
||||
void ComponentDocument::continueDrag (const MouseEvent& e)
|
||||
|
|
|
|||
|
|
@ -55,19 +55,21 @@ public:
|
|||
int getNumComponents() const;
|
||||
const ValueTree getComponent (int index) const;
|
||||
const ValueTree getComponentWithMemberName (const String& name) const;
|
||||
Component* createComponent (int index) const;
|
||||
void updateComponent (Component* comp) const;
|
||||
Component* createComponent (int index);
|
||||
void updateComponent (Component* comp);
|
||||
bool containsComponent (Component* comp) const;
|
||||
const ValueTree getComponentState (Component* comp) const;
|
||||
void getComponentProperties (Array <PropertyComponent*>& props, Component* comp);
|
||||
bool isStateForComponent (const ValueTree& storedState, Component* comp) const;
|
||||
Coordinate::MarkerResolver* createMarkerResolver (const ValueTree& state, Component* parentComponent);
|
||||
const RectangleCoordinates getCoordsFor (const ValueTree& state) const;
|
||||
|
||||
void addNewComponentMenuItems (PopupMenu& menu) const;
|
||||
void performNewComponentMenuItem (int menuResultCode);
|
||||
|
||||
//==============================================================================
|
||||
void beginDrag (const Array<Component*>& items, const MouseEvent& e,
|
||||
const ResizableBorderComponent::Zone& zone);
|
||||
Component* parentForOverlays, const ResizableBorderComponent::Zone& zone);
|
||||
void continueDrag (const MouseEvent& e);
|
||||
void endDrag (const MouseEvent& e);
|
||||
|
||||
|
|
@ -114,9 +116,9 @@ public:
|
|||
virtual Component* createComponent() = 0;
|
||||
virtual const Rectangle<int> getDefaultSize() = 0;
|
||||
|
||||
virtual void updateComponent (Component* comp, const ValueTree& state);
|
||||
virtual void initialiseNewItem (ValueTree& state, ComponentDocument& document);
|
||||
virtual void createPropertyEditors (ValueTree& state, ComponentDocument& document, Array <PropertyComponent*>& props);
|
||||
virtual void updateComponent (ComponentDocument& document, Component* comp, const ValueTree& state);
|
||||
virtual void initialiseNewItem (ComponentDocument& document, ValueTree& state);
|
||||
virtual void createPropertyEditors (ComponentDocument& document, ValueTree& state, Array <PropertyComponent*>& props);
|
||||
|
||||
Value getValue (const var::identifier& name, ValueTree& state, ComponentDocument& document) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,134 @@
|
|||
#include "jucer_ComponentEditor.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class SizeGuideComponent : public Component,
|
||||
public ComponentListener
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
left, right, top, bottom
|
||||
};
|
||||
|
||||
SizeGuideComponent (ComponentDocument& document_, const ValueTree& state_, Component* component_,
|
||||
Component* parentForOverlays, Type type_)
|
||||
: document (document_), state (state_), component (component_), type (type_),
|
||||
font (10.0f)
|
||||
{
|
||||
component->addComponentListener (this);
|
||||
|
||||
setAlwaysOnTop (true);
|
||||
parentForOverlays->addAndMakeVisible (this);
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
~SizeGuideComponent()
|
||||
{
|
||||
if (component != 0)
|
||||
component->removeComponentListener (this);
|
||||
}
|
||||
|
||||
void updatePosition()
|
||||
{
|
||||
RectangleCoordinates coords (document.getCoordsFor (state));
|
||||
Coordinate coord (false);
|
||||
bool isHorizontal = false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case left: coord = coords.left; isHorizontal = true; break;
|
||||
case right: coord = coords.right; isHorizontal = true; break;
|
||||
case top: coord = coords.top; break;
|
||||
case bottom: coord = coords.bottom; break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
setName (coord.toString());
|
||||
|
||||
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (state, component->getParentComponent()));
|
||||
int anchor1 = coord.getAnchorPoint1().resolve (*markers);
|
||||
int anchor2 = coord.getAnchorPoint2().resolve (*markers);
|
||||
|
||||
Point<int> p1, p2;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case left: p1 = Point<int> (component->getX(), component->getY() + component->proportionOfHeight (0.33f));
|
||||
p2 = Point<int> (anchor1, p1.getY()); break;
|
||||
case right: p1 = Point<int> (component->getRight(), component->getY() + component->proportionOfHeight (0.66f));
|
||||
p2 = Point<int> (anchor1, p1.getY()); break;
|
||||
case top: p1 = Point<int> (component->getX() + component->proportionOfWidth (0.33f), component->getY());
|
||||
p2 = Point<int> (p1.getX(), anchor1); break;
|
||||
case bottom: p1 = Point<int> (component->getX() + component->proportionOfWidth (0.66f), component->getBottom());
|
||||
p2 = Point<int> (p1.getX(), anchor1); break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
Rectangle<int> bounds (Rectangle<int> (p1, p2).expanded (4, 4));
|
||||
Point<int> textPos ((p1.getX() + p2.getX()) / 2,
|
||||
(p1.getY() + p2.getY()) / 2);
|
||||
int textW = (int) font.getStringWidth (getName());
|
||||
int textH = (int) font.getHeight();
|
||||
Rectangle<int> textRect (textPos.getX() - textW / 2, textPos.getY() - textH / 2, textW, textH);
|
||||
|
||||
if (isHorizontal)
|
||||
textRect = textRect - Point<int> (0, textH / 2 + 4);
|
||||
|
||||
bounds = bounds.getUnion (textRect);
|
||||
setBounds (bounds);
|
||||
|
||||
lineEnd1 = p1 - bounds.getPosition();
|
||||
lineEnd2 = p2 - bounds.getPosition();
|
||||
textArea = textRect - bounds.getPosition();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void paint (Graphics& g)
|
||||
{
|
||||
Path p;
|
||||
p.addLineSegment (lineEnd1.getX(), lineEnd1.getY(), lineEnd2.getX(), lineEnd2.getY(), 1.6f);
|
||||
const float startBlobSize = 2.0f;
|
||||
p.addEllipse (lineEnd1.getX() - startBlobSize, lineEnd1.getY() - startBlobSize, startBlobSize * 2.0f, startBlobSize * 2.0f);
|
||||
const float endBlobSize = 4.0f;
|
||||
p.addEllipse (lineEnd2.getX() - endBlobSize, lineEnd2.getY() - endBlobSize, endBlobSize * 2.0f, endBlobSize * 2.0f);
|
||||
|
||||
g.setColour (Colours::black.withAlpha (0.3f));
|
||||
g.fillPath (p);
|
||||
|
||||
g.setFont (font);
|
||||
g.setColour (Colours::white);
|
||||
|
||||
for (int y = -1; y <= 1; ++y)
|
||||
for (int x = -1; x <= 1; ++x)
|
||||
g.drawText (getName(), textArea.getX() + x, textArea.getY() + y, textArea.getWidth(), textArea.getHeight(), Justification::centred, 1);
|
||||
|
||||
g.setColour (Colours::black);
|
||||
g.drawText (getName(), textArea.getX(), textArea.getY(), textArea.getWidth(), textArea.getHeight(), Justification::centred, 1);
|
||||
}
|
||||
|
||||
void componentMovedOrResized (Component&, bool, bool)
|
||||
{
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void componentBeingDeleted (Component&)
|
||||
{
|
||||
setVisible (false);
|
||||
component = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
ComponentDocument& document;
|
||||
ValueTree state;
|
||||
Component* component;
|
||||
Type type;
|
||||
Font font;
|
||||
Point<int> lineEnd1, lineEnd2;
|
||||
Rectangle<int> textArea;
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class ComponentEditor::Canvas : public Component,
|
||||
public ValueTree::Listener,
|
||||
|
|
@ -116,10 +244,8 @@ public:
|
|||
c = doc.createComponent (i);
|
||||
componentHolder->addAndMakeVisible (c);
|
||||
}
|
||||
else
|
||||
{
|
||||
doc.updateComponent (c);
|
||||
}
|
||||
|
||||
doc.updateComponent (c);
|
||||
}
|
||||
|
||||
startTimer (500);
|
||||
|
|
@ -175,9 +301,57 @@ public:
|
|||
getDocument().beginNewTransaction();
|
||||
}
|
||||
|
||||
void mouseMove (const MouseEvent& e)
|
||||
{
|
||||
updateDragZone (e.getPosition());
|
||||
}
|
||||
|
||||
void mouseDown (const MouseEvent& e)
|
||||
{
|
||||
updateDragZone (e.getPosition());
|
||||
dragStartSize = getBounds();
|
||||
}
|
||||
|
||||
void mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
if (dragZone.isDraggingRightEdge() || dragZone.isDraggingBottomEdge())
|
||||
{
|
||||
showSizeGuides();
|
||||
setSize (jmax (0, dragStartSize.getWidth() + e.getDistanceFromDragStartX()),
|
||||
jmax (0, dragStartSize.getHeight() + e.getDistanceFromDragStartY()));
|
||||
}
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& e)
|
||||
{
|
||||
hideSizeGuides();
|
||||
updateDragZone (e.getPosition());
|
||||
}
|
||||
|
||||
void updateDragZone (const Point<int>& p)
|
||||
{
|
||||
ResizableBorderComponent::Zone newZone
|
||||
= ResizableBorderComponent::Zone::fromPositionOnBorder (getLocalBounds(),
|
||||
BorderSize (borderThickness), p);
|
||||
|
||||
newZone = ResizableBorderComponent::Zone (newZone.getZoneFlags()
|
||||
& (ResizableBorderComponent::Zone::right | ResizableBorderComponent::Zone::bottom));
|
||||
|
||||
if (dragZone != newZone)
|
||||
{
|
||||
dragZone = newZone;
|
||||
setMouseCursor (newZone.getMouseCursor());
|
||||
}
|
||||
}
|
||||
|
||||
void showSizeGuides() { overlay->showSizeGuides(); }
|
||||
void hideSizeGuides() { overlay->hideSizeGuides(); }
|
||||
|
||||
private:
|
||||
ComponentEditor& editor;
|
||||
const int borderThickness;
|
||||
ResizableBorderComponent::Zone dragZone;
|
||||
Rectangle<int> dragStartSize;
|
||||
|
||||
//==============================================================================
|
||||
class ComponentResizeFrame : public Component,
|
||||
|
|
@ -230,18 +404,23 @@ private:
|
|||
if (component != 0)
|
||||
{
|
||||
updateDragZone (e.getPosition());
|
||||
canvas.getDocument().beginDrag (canvas.getSelectedComps(), e, dragZone);
|
||||
canvas.getDocument().beginDrag (canvas.getSelectedComps(), e, getParentComponent(), dragZone);
|
||||
}
|
||||
}
|
||||
|
||||
void mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
if (component != 0)
|
||||
{
|
||||
canvas.showSizeGuides();
|
||||
canvas.getDocument().continueDrag (e);
|
||||
}
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& e)
|
||||
{
|
||||
canvas.hideSizeGuides();
|
||||
|
||||
if (component != 0)
|
||||
canvas.getDocument().endDrag (e);
|
||||
|
||||
|
|
@ -261,11 +440,29 @@ private:
|
|||
|
||||
uint32 getTargetComponentUID() const { return component == 0 ? 0 : component->getComponentUID(); }
|
||||
|
||||
void showSizeGuides()
|
||||
{
|
||||
if (sizeGuides.size() == 0)
|
||||
{
|
||||
const ValueTree v (canvas.getDocument().getComponentState (component));
|
||||
sizeGuides.add (new SizeGuideComponent (canvas.getDocument(), v, component, getParentComponent(), SizeGuideComponent::left));
|
||||
sizeGuides.add (new SizeGuideComponent (canvas.getDocument(), v, component, getParentComponent(), SizeGuideComponent::right));
|
||||
sizeGuides.add (new SizeGuideComponent (canvas.getDocument(), v, component, getParentComponent(), SizeGuideComponent::top));
|
||||
sizeGuides.add (new SizeGuideComponent (canvas.getDocument(), v, component, getParentComponent(), SizeGuideComponent::bottom));
|
||||
}
|
||||
}
|
||||
|
||||
void hideSizeGuides()
|
||||
{
|
||||
sizeGuides.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
Canvas& canvas;
|
||||
Component::SafePointer<Component> component;
|
||||
ResizableBorderComponent::Zone dragZone;
|
||||
const int borderThickness;
|
||||
OwnedArray <SizeGuideComponent> sizeGuides;
|
||||
|
||||
const Rectangle<int> getCentreArea() const
|
||||
{
|
||||
|
|
@ -354,16 +551,19 @@ private:
|
|||
{
|
||||
isDraggingClickedComp = true;
|
||||
canvas.getSelection().addToSelectionOnMouseUp (mouseDownCompUID, e.mods, true, mouseDownResult);
|
||||
canvas.getDocument().beginDrag (canvas.getSelectedComps(), e,
|
||||
canvas.getDocument().beginDrag (canvas.getSelectedComps(), e, getParentComponent(),
|
||||
ResizableBorderComponent::Zone (ResizableBorderComponent::Zone::centre));
|
||||
}
|
||||
|
||||
canvas.getDocument().continueDrag (e);
|
||||
showSizeGuides();
|
||||
}
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& e)
|
||||
{
|
||||
hideSizeGuides();
|
||||
|
||||
if (lasso != 0)
|
||||
{
|
||||
lasso->endLasso();
|
||||
|
|
@ -377,6 +577,8 @@ private:
|
|||
if (! isDraggingClickedComp)
|
||||
canvas.getSelection().addToSelectionOnMouseUp (mouseDownCompUID, e.mods, ! e.mouseWasClicked(), mouseDownResult);
|
||||
}
|
||||
|
||||
canvas.getDocument().endDrag (e);
|
||||
}
|
||||
|
||||
void findLassoItemsInArea (Array <ComponentDocument::SelectedItems::ItemType>& itemsFound, int x, int y, int width, int height)
|
||||
|
|
@ -403,6 +605,26 @@ private:
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Canvas& canvas;
|
||||
ScopedPointer <LassoComponent <ComponentDocument::SelectedItems::ItemType> > lasso;
|
||||
|
|
|
|||
|
|
@ -505,152 +505,326 @@ int indexOfLineStartingWith (const StringArray& lines, const String& text, int s
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativePosition::RelativePosition()
|
||||
: value (0), isRelative (false)
|
||||
const char* Coordinate::parentLeftMarkerName = "parent.left";
|
||||
const char* Coordinate::parentRightMarkerName = "parent.right";
|
||||
const char* Coordinate::parentTopMarkerName = "parent.top";
|
||||
const char* Coordinate::parentBottomMarkerName = "parent.bottom";
|
||||
|
||||
Coordinate::Coordinate (bool isHorizontal_)
|
||||
: value (0), isProportion (false), isHorizontal (isHorizontal_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePosition::RelativePosition (double absoluteDistanceFromOrigin)
|
||||
: value (absoluteDistanceFromOrigin), isRelative (false)
|
||||
Coordinate::Coordinate (double absoluteDistanceFromOrigin, bool isHorizontal_)
|
||||
: value (absoluteDistanceFromOrigin), isProportion (false), isHorizontal (isHorizontal_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePosition::RelativePosition (double absoluteDistance, const String& source)
|
||||
: nameOfSource1 (source), value (absoluteDistance), isRelative (false)
|
||||
Coordinate::Coordinate (double absoluteDistance, const String& source, bool isHorizontal_)
|
||||
: anchor1 (source), value (absoluteDistance), isProportion (false), isHorizontal (isHorizontal_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePosition::RelativePosition (double relativeProportion, const String& pos1, const String& pos2)
|
||||
: nameOfSource1 (pos1), nameOfSource2 (pos2), value (relativeProportion), isRelative (true)
|
||||
Coordinate::Coordinate (double relativeProportion, const String& pos1, const String& pos2, bool isHorizontal_)
|
||||
: anchor1 (pos1), anchor2 (pos2), value (relativeProportion), isProportion (true), isHorizontal (isHorizontal_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePosition::~RelativePosition()
|
||||
Coordinate::~Coordinate()
|
||||
{
|
||||
}
|
||||
|
||||
bool RelativePosition::isOrigin (const String& name)
|
||||
const Coordinate Coordinate::getAnchorPoint1() const
|
||||
{
|
||||
return name.isEmpty() || name == parentOriginMarkerName;
|
||||
return Coordinate (0.0, anchor1, isHorizontal);
|
||||
}
|
||||
|
||||
const String RelativePosition::checkName (const String& name)
|
||||
const Coordinate Coordinate::getAnchorPoint2() const
|
||||
{
|
||||
return name.isEmpty() ? parentOriginMarkerName : name;
|
||||
return Coordinate (0.0, anchor2, isHorizontal);
|
||||
}
|
||||
|
||||
double RelativePosition::getPosition (const String& name, PositionFinder& positionFinder) const
|
||||
bool Coordinate::isOrigin (const String& name)
|
||||
{
|
||||
return name.isEmpty() || name == parentLeftMarkerName || name == parentTopMarkerName;
|
||||
}
|
||||
|
||||
const String Coordinate::getOriginMarkerName() const
|
||||
{
|
||||
return isHorizontal ? parentLeftMarkerName : parentTopMarkerName;
|
||||
}
|
||||
|
||||
const String Coordinate::getExtentMarkerName() const
|
||||
{
|
||||
return isHorizontal ? parentRightMarkerName : parentBottomMarkerName;
|
||||
}
|
||||
|
||||
const String Coordinate::checkName (const String& name) const
|
||||
{
|
||||
return name.isEmpty() ? getOriginMarkerName() : name;
|
||||
}
|
||||
|
||||
double Coordinate::getPosition (const String& name, MarkerResolver& markerResolver, int recursionCounter) const
|
||||
{
|
||||
if (isOrigin (name))
|
||||
return 0.0;
|
||||
|
||||
RelativePosition* const pos = positionFinder.findPosition (nameOfSource1);
|
||||
return markerResolver.findMarker (name, isHorizontal)
|
||||
.resolve (markerResolver, recursionCounter + 1);
|
||||
}
|
||||
|
||||
if (pos != 0)
|
||||
return pos->resolve (positionFinder);
|
||||
struct RecursivePositionException
|
||||
{
|
||||
};
|
||||
|
||||
double Coordinate::resolve (MarkerResolver& markerResolver, int recursionCounter) const
|
||||
{
|
||||
if (recursionCounter > 100)
|
||||
{
|
||||
jassertfalse
|
||||
throw RecursivePositionException();
|
||||
}
|
||||
|
||||
const double pos1 = getPosition (anchor1, markerResolver, recursionCounter);
|
||||
|
||||
return isProportion ? pos1 + (getPosition (anchor2, markerResolver, recursionCounter) - pos1) * value
|
||||
: pos1 + value;
|
||||
}
|
||||
|
||||
double Coordinate::resolve (MarkerResolver& markerResolver) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return resolve (markerResolver, 0);
|
||||
}
|
||||
catch (RecursivePositionException&)
|
||||
{}
|
||||
|
||||
jassertfalse;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double RelativePosition::resolve (PositionFinder& positionFinder) const
|
||||
void Coordinate::moveToAbsolute (double newPos, MarkerResolver& markerResolver)
|
||||
{
|
||||
const double pos1 = getPos1 (positionFinder);
|
||||
|
||||
return isRelative ? pos1 + (getPos2 (positionFinder) - pos1) * value
|
||||
: pos1 + value;
|
||||
}
|
||||
|
||||
void RelativePosition::moveToAbsolute (double newPos, PositionFinder& positionFinder)
|
||||
{
|
||||
const double pos1 = getPos1 (positionFinder);
|
||||
|
||||
if (isRelative)
|
||||
value = (newPos - pos1) / (getPos2 (positionFinder) - pos1);
|
||||
else
|
||||
value = newPos - pos1;
|
||||
}
|
||||
|
||||
RelativePosition::RelativePosition (const String& stringVersion)
|
||||
{
|
||||
jassertfalse //todo
|
||||
}
|
||||
|
||||
const String RelativePosition::toString (int decimalPlaces) const
|
||||
{
|
||||
if (isRelative)
|
||||
try
|
||||
{
|
||||
const String percent (value * 100.0, 2);
|
||||
const double pos1 = getPosition (anchor1, markerResolver, 0);
|
||||
|
||||
if (isOrigin (nameOfSource1))
|
||||
if (isProportion)
|
||||
{
|
||||
if (nameOfSource2 == parentExtentMarkerName)
|
||||
return percent + "%";
|
||||
else
|
||||
return percent + "% of " + checkName (nameOfSource2);
|
||||
const double size = getPosition (anchor2, markerResolver, 0) - pos1;
|
||||
|
||||
if (size != 0)
|
||||
value = (newPos - pos1) / size;
|
||||
}
|
||||
else
|
||||
return percent + "% of " + checkName (nameOfSource1) + " to " + checkName (nameOfSource2);
|
||||
{
|
||||
value = newPos - pos1;
|
||||
}
|
||||
}
|
||||
catch (RecursivePositionException&)
|
||||
{}
|
||||
}
|
||||
|
||||
bool Coordinate::isRecursive (MarkerResolver& markerResolver) const
|
||||
{
|
||||
try
|
||||
{
|
||||
resolve (markerResolver, 0);
|
||||
}
|
||||
catch (RecursivePositionException&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Coordinate::skipWhitespace (const String& s, int& i)
|
||||
{
|
||||
while (CharacterFunctions::isWhitespace (s[i]))
|
||||
++i;
|
||||
}
|
||||
|
||||
const String Coordinate::readMarkerName (const String& s, int& i)
|
||||
{
|
||||
skipWhitespace (s, i);
|
||||
|
||||
if (CharacterFunctions::isLetter (s[i]) || s[i] == '_')
|
||||
{
|
||||
int start = i;
|
||||
|
||||
while (CharacterFunctions::isLetterOrDigit (s[i]) || s[i] == '_' || s[i] == '.')
|
||||
++i;
|
||||
|
||||
return s.substring (start, i);
|
||||
}
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
|
||||
double Coordinate::readNumber (const String& s, int& i)
|
||||
{
|
||||
skipWhitespace (s, i);
|
||||
|
||||
int start = i;
|
||||
|
||||
if (CharacterFunctions::isDigit (s[i]) || s[i] == '.' || s[i] == '-')
|
||||
++i;
|
||||
|
||||
while (CharacterFunctions::isDigit (s[i]) || s[i] == '.')
|
||||
++i;
|
||||
|
||||
if ((s[i] == 'e' || s[i] == 'E')
|
||||
&& (CharacterFunctions::isDigit (s[i + 1])
|
||||
|| s[i + 1] == '-'
|
||||
|| s[i + 1] == '+'))
|
||||
{
|
||||
i += 2;
|
||||
|
||||
while (CharacterFunctions::isDigit (s[i]))
|
||||
++i;
|
||||
}
|
||||
|
||||
const double value = s.substring (start, i).getDoubleValue();
|
||||
|
||||
while (CharacterFunctions::isWhitespace (s[i]) || s[i] == ',')
|
||||
++i;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
Coordinate::Coordinate (const String& s, bool isHorizontal_)
|
||||
: value (0), isProportion (false), isHorizontal (isHorizontal_)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
anchor1 = readMarkerName (s, i);
|
||||
|
||||
if (anchor1.isNotEmpty())
|
||||
{
|
||||
skipWhitespace (s, i);
|
||||
|
||||
if (s[i] == '+')
|
||||
value = readNumber (s, ++i);
|
||||
else if (s[i] == '-')
|
||||
value = -readNumber (s, ++i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isOrigin (nameOfSource1))
|
||||
return String (value, decimalPlaces);
|
||||
else if (value != 0)
|
||||
return checkName (nameOfSource1) + " + " + String (value, decimalPlaces);
|
||||
else
|
||||
return checkName (nameOfSource1);
|
||||
value = readNumber (s, i);
|
||||
skipWhitespace (s, i);
|
||||
|
||||
if (s[i] == '%')
|
||||
{
|
||||
isProportion = true;
|
||||
value /= 100.0;
|
||||
skipWhitespace (s, ++i);
|
||||
|
||||
if (s[i] == '*')
|
||||
{
|
||||
anchor1 = readMarkerName (s, ++i);
|
||||
skipWhitespace (s, i);
|
||||
|
||||
if (s[i] == '-' && s[i + 1] == '>')
|
||||
{
|
||||
i += 2;
|
||||
anchor2 = readMarkerName (s, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
anchor2 = anchor1;
|
||||
anchor1 = getOriginMarkerName();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
anchor1 = getOriginMarkerName();
|
||||
anchor2 = getExtentMarkerName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* RelativePosition::parentOriginMarkerName = "origin";
|
||||
const char* RelativePosition::parentExtentMarkerName = "size";
|
||||
const String Coordinate::toString() const
|
||||
{
|
||||
if (isProportion)
|
||||
{
|
||||
const String percent (value * 100.0);
|
||||
|
||||
if (isOrigin (anchor1))
|
||||
{
|
||||
if (anchor2 == parentRightMarkerName || anchor2 == parentBottomMarkerName)
|
||||
return percent + "%";
|
||||
else
|
||||
return percent + "% * " + checkName (anchor2);
|
||||
}
|
||||
else
|
||||
return percent + "% * " + checkName (anchor1) + " -> " + checkName (anchor2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isOrigin (anchor1))
|
||||
return String (value);
|
||||
else if (value > 0)
|
||||
return checkName (anchor1) + " + " + String (value);
|
||||
else if (value < 0)
|
||||
return checkName (anchor1) + " - " + String (-value);
|
||||
else
|
||||
return checkName (anchor1);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativeRectangle::RelativeRectangle()
|
||||
RectangleCoordinates::RectangleCoordinates()
|
||||
: left (true), right (true), top (false), bottom (false)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeRectangle::RelativeRectangle (const Rectangle<int>& rect)
|
||||
: left (rect.getX()),
|
||||
right (rect.getRight()),
|
||||
top (rect.getY()),
|
||||
bottom (rect.getBottom())
|
||||
RectangleCoordinates::RectangleCoordinates (const Rectangle<int>& rect)
|
||||
: left (rect.getX(), true),
|
||||
right (rect.getWidth(), "left", true),
|
||||
top (rect.getY(), false),
|
||||
bottom (rect.getHeight(), "top", false)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeRectangle::RelativeRectangle (const String& stringVersion)
|
||||
RectangleCoordinates::RectangleCoordinates (const String& stringVersion)
|
||||
: left (true), right (true), top (false), bottom (false)
|
||||
{
|
||||
jassertfalse // todo
|
||||
StringArray tokens;
|
||||
tokens.addTokens (stringVersion, ",", String::empty);
|
||||
|
||||
left = Coordinate (tokens [0], true);
|
||||
top = Coordinate (tokens [1], false);
|
||||
right = Coordinate (tokens [2], true);
|
||||
bottom = Coordinate (tokens [3], false);
|
||||
}
|
||||
|
||||
const Rectangle<int> RelativeRectangle::resolve (RelativePosition::PositionFinder& positionFinder) const
|
||||
bool RectangleCoordinates::isRecursive (Coordinate::MarkerResolver& markerResolver) const
|
||||
{
|
||||
const int l = roundToInt (left.resolve (positionFinder));
|
||||
const int r = roundToInt (right.resolve (positionFinder));
|
||||
const int t = roundToInt (top.resolve (positionFinder));
|
||||
const int b = roundToInt (bottom.resolve (positionFinder));
|
||||
return left.isRecursive (markerResolver) || right.isRecursive (markerResolver)
|
||||
|| top.isRecursive (markerResolver) || bottom.isRecursive (markerResolver);
|
||||
}
|
||||
|
||||
const Rectangle<int> RectangleCoordinates::resolve (Coordinate::MarkerResolver& markerResolver) const
|
||||
{
|
||||
const int l = roundToInt (left.resolve (markerResolver));
|
||||
const int r = roundToInt (right.resolve (markerResolver));
|
||||
const int t = roundToInt (top.resolve (markerResolver));
|
||||
const int b = roundToInt (bottom.resolve (markerResolver));
|
||||
|
||||
return Rectangle<int> (l, t, r - l, b - t);
|
||||
}
|
||||
|
||||
void RelativeRectangle::moveToAbsolute (const Rectangle<int>& newPos, RelativePosition::PositionFinder& positionFinder)
|
||||
void RectangleCoordinates::moveToAbsolute (const Rectangle<int>& newPos, Coordinate::MarkerResolver& markerResolver)
|
||||
{
|
||||
left.moveToAbsolute (newPos.getX(), positionFinder);
|
||||
right.moveToAbsolute (newPos.getRight(), positionFinder);
|
||||
top.moveToAbsolute (newPos.getY(), positionFinder);
|
||||
bottom.moveToAbsolute (newPos.getBottom(), positionFinder);
|
||||
|
||||
// do it all again in case there were dependencies between some of the positions..
|
||||
left.moveToAbsolute (newPos.getX(), positionFinder);
|
||||
right.moveToAbsolute (newPos.getRight(), positionFinder);
|
||||
top.moveToAbsolute (newPos.getY(), positionFinder);
|
||||
bottom.moveToAbsolute (newPos.getBottom(), positionFinder);
|
||||
left.moveToAbsolute (newPos.getX(), markerResolver);
|
||||
right.moveToAbsolute (newPos.getRight(), markerResolver);
|
||||
top.moveToAbsolute (newPos.getY(), markerResolver);
|
||||
bottom.moveToAbsolute (newPos.getBottom(), markerResolver);
|
||||
}
|
||||
|
||||
const String RelativeRectangle::toString (int decimalPlaces) const
|
||||
const String RectangleCoordinates::toString() const
|
||||
{
|
||||
return left.toString (decimalPlaces) + ", " + top.toString (decimalPlaces)
|
||||
+ ", " + right.toString (decimalPlaces) + ", " + bottom.toString (decimalPlaces);
|
||||
return left.toString() + ", " + top.toString() + ", " + right.toString() + ", " + bottom.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,56 +111,113 @@ private:
|
|||
|
||||
|
||||
//==============================================================================
|
||||
class RelativePosition
|
||||
/**
|
||||
Holds a co-ordinate along the x or y axis, expressed either as an absolute
|
||||
position, or relative to other named marker positions.
|
||||
*/
|
||||
class Coordinate
|
||||
{
|
||||
public:
|
||||
RelativePosition();
|
||||
explicit RelativePosition (const String& stringVersion);
|
||||
explicit RelativePosition (double absoluteDistanceFromOrigin);
|
||||
RelativePosition (double absoluteDistance, const String& source);
|
||||
RelativePosition (double relativeProportion, const String& pos1, const String& pos2);
|
||||
~RelativePosition();
|
||||
//==============================================================================
|
||||
/** Creates a zero coordinate. */
|
||||
Coordinate (bool isHorizontal);
|
||||
|
||||
class PositionFinder
|
||||
/** Recreates a coordinate from its stringified version. */
|
||||
explicit Coordinate (const String& stringVersion, bool isHorizontal);
|
||||
|
||||
/** Creates an absolute position from the parent origin. */
|
||||
explicit Coordinate (double absoluteDistanceFromOrigin, bool isHorizontal);
|
||||
|
||||
/** Creates an absolute position relative to a named marker. */
|
||||
Coordinate (double absolutePosition, const String& relativeToMarker, bool isHorizontal);
|
||||
|
||||
/** Creates a relative position between two named markers. */
|
||||
Coordinate (double relativePosition, const String& marker1, const String& marker2, bool isHorizontal);
|
||||
|
||||
/** Destructor. */
|
||||
~Coordinate();
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Provides an interface for looking up the position of a named marker.
|
||||
*/
|
||||
class MarkerResolver
|
||||
{
|
||||
public:
|
||||
virtual ~PositionFinder() {}
|
||||
virtual RelativePosition* findPosition (const String& name) = 0;
|
||||
virtual ~MarkerResolver() {}
|
||||
virtual const Coordinate findMarker (const String& name, bool isHorizontal) = 0;
|
||||
};
|
||||
|
||||
const String getName() const { return name; }
|
||||
void setName (const String& newName) { name = newName; }
|
||||
/** Calculates the absolute position of this co-ordinate. */
|
||||
double resolve (MarkerResolver& markerResolver) const;
|
||||
|
||||
double resolve (PositionFinder& positionFinder) const;
|
||||
void moveToAbsolute (double newPos, PositionFinder& positionFinder);
|
||||
/** Returns true if this co-ordinate is expressed in terms of markers that form a recursive loop. */
|
||||
bool isRecursive (MarkerResolver& markerResolver) const;
|
||||
|
||||
const String toString (int decimalPlaces) const;
|
||||
/** Changes the value of this marker to make it resolve to the specified position. */
|
||||
void moveToAbsolute (double newPos, MarkerResolver& markerResolver);
|
||||
|
||||
static const char* parentOriginMarkerName;
|
||||
static const char* parentExtentMarkerName;
|
||||
const Coordinate getAnchorPoint1() const;
|
||||
const Coordinate getAnchorPoint2() const;
|
||||
|
||||
//==============================================================================
|
||||
/*
|
||||
Position string formats:
|
||||
123 = absolute pixels from parent origin
|
||||
marker
|
||||
marker + 123
|
||||
marker - 123
|
||||
50% = percentage between parent origin and parent extent
|
||||
50% * marker = percentage between parent origin and marker
|
||||
50% * marker1 -> marker2 = percentage between two markers
|
||||
|
||||
standard marker names:
|
||||
"origin" = parent origin
|
||||
"size" = parent right or bottom
|
||||
"top", "left", "bottom", "right" = refer to the component's own left, right, top and bottom.
|
||||
*/
|
||||
const String toString() const;
|
||||
|
||||
//==============================================================================
|
||||
static const char* parentLeftMarkerName;
|
||||
static const char* parentRightMarkerName;
|
||||
static const char* parentTopMarkerName;
|
||||
static const char* parentBottomMarkerName;
|
||||
|
||||
private:
|
||||
String name, nameOfSource1, nameOfSource2;
|
||||
//==============================================================================
|
||||
String anchor1, anchor2;
|
||||
double value;
|
||||
bool isRelative;
|
||||
bool isProportion, isHorizontal;
|
||||
|
||||
double getPos1 (PositionFinder& positionFinder) const { return getPosition (nameOfSource1, positionFinder); }
|
||||
double getPos2 (PositionFinder& positionFinder) const { return getPosition (nameOfSource2, positionFinder); }
|
||||
double getPosition (const String& name, PositionFinder& positionFinder) const;
|
||||
static const String checkName (const String& name);
|
||||
double resolve (MarkerResolver& markerResolver, int recursionCounter) const;
|
||||
double getPosition (const String& name, MarkerResolver& markerResolver, int recursionCounter) const;
|
||||
const String checkName (const String& name) const;
|
||||
const String getOriginMarkerName() const;
|
||||
const String getExtentMarkerName() const;
|
||||
static bool isOrigin (const String& name);
|
||||
static void skipWhitespace (const String& s, int& i);
|
||||
static const String readMarkerName (const String& s, int& i);
|
||||
static double readNumber (const String& s, int& i);
|
||||
};
|
||||
|
||||
class RelativeRectangle
|
||||
//==============================================================================
|
||||
/**
|
||||
Describes a rectangle as a set of Coordinate values.
|
||||
*/
|
||||
class RectangleCoordinates
|
||||
{
|
||||
public:
|
||||
RelativeRectangle();
|
||||
explicit RelativeRectangle (const Rectangle<int>& rect);
|
||||
explicit RelativeRectangle (const String& stringVersion);
|
||||
//==============================================================================
|
||||
RectangleCoordinates();
|
||||
explicit RectangleCoordinates (const Rectangle<int>& rect);
|
||||
explicit RectangleCoordinates (const String& stringVersion);
|
||||
|
||||
const Rectangle<int> resolve (RelativePosition::PositionFinder& positionFinder) const;
|
||||
void moveToAbsolute (const Rectangle<int>& newPos, RelativePosition::PositionFinder& positionFinder);
|
||||
const String toString (int decimalPlaces) const;
|
||||
//==============================================================================
|
||||
const Rectangle<int> resolve (Coordinate::MarkerResolver& markerResolver) const;
|
||||
bool isRecursive (Coordinate::MarkerResolver& markerResolver) const;
|
||||
void moveToAbsolute (const Rectangle<int>& newPos, Coordinate::MarkerResolver& markerResolver);
|
||||
const String toString() const;
|
||||
|
||||
RelativePosition left, right, top, bottom;
|
||||
Coordinate left, right, top, bottom;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -60932,13 +60932,13 @@ const Rectangle<int> ResizableBorderComponent::Zone::resizeRectangleBy (Rectangl
|
|||
b.setLeft (b.getX() + offset.getX());
|
||||
|
||||
if (isDraggingRightEdge())
|
||||
b.setWidth (b.getWidth() + offset.getX());
|
||||
b.setWidth (jmax (0, b.getWidth() + offset.getX()));
|
||||
|
||||
if (isDraggingTopEdge())
|
||||
b.setTop (b.getY() + offset.getY());
|
||||
|
||||
if (isDraggingBottomEdge())
|
||||
b.setHeight (b.getHeight() + offset.getY());
|
||||
b.setHeight (jmax (0, b.getHeight() + offset.getY()));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
|
@ -211817,6 +211817,9 @@ void InterProcessLock::exit()
|
|||
{
|
||||
const ScopedLock sl (lock);
|
||||
|
||||
// Trying to release the lock too many times!
|
||||
jassert (pimpl != 0);
|
||||
|
||||
if (pimpl != 0 && --(pimpl->refCount) == 0)
|
||||
pimpl = 0;
|
||||
}
|
||||
|
|
@ -228044,6 +228047,9 @@ void InterProcessLock::exit()
|
|||
{
|
||||
const ScopedLock sl (lock);
|
||||
|
||||
// Trying to release the lock too many times!
|
||||
jassert (pimpl != 0);
|
||||
|
||||
if (pimpl != 0 && --(pimpl->refCount) == 0)
|
||||
pimpl = 0;
|
||||
}
|
||||
|
|
@ -238095,6 +238101,9 @@ void InterProcessLock::exit()
|
|||
{
|
||||
const ScopedLock sl (lock);
|
||||
|
||||
// Trying to release the lock too many times!
|
||||
jassert (pimpl != 0);
|
||||
|
||||
if (pimpl != 0 && --(pimpl->refCount) == 0)
|
||||
pimpl = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8723,13 +8723,16 @@ public:
|
|||
{
|
||||
public:
|
||||
|
||||
inline explicit ScopedLockType (InterProcessLock& lock) : lock_ (lock) { lock.enter(); }
|
||||
explicit ScopedLockType (InterProcessLock& lock) : lock_ (lock) { lockWasSuccessful = lock.enter(); }
|
||||
|
||||
inline ~ScopedLockType() { lock_.exit(); }
|
||||
|
||||
bool isLocked() const throw() { return lockWasSuccessful; }
|
||||
|
||||
private:
|
||||
|
||||
InterProcessLock& lock_;
|
||||
bool lockWasSuccessful;
|
||||
|
||||
ScopedLockType (const ScopedLockType&);
|
||||
ScopedLockType& operator= (const ScopedLockType&);
|
||||
|
|
@ -10062,6 +10065,11 @@ public:
|
|||
return Rectangle (x + deltaPosition.getX(), y + deltaPosition.getY(), w, h);
|
||||
}
|
||||
|
||||
const Rectangle operator- (const Point<ValueType>& deltaPosition) const throw()
|
||||
{
|
||||
return Rectangle (x - deltaPosition.getX(), y - deltaPosition.getY(), w, h);
|
||||
}
|
||||
|
||||
void expand (const ValueType deltaX,
|
||||
const ValueType deltaY) throw()
|
||||
{
|
||||
|
|
@ -22888,6 +22896,8 @@ public:
|
|||
const Rectangle<int> resizeRectangleBy (Rectangle<int> original,
|
||||
const Point<int>& distance) const throw();
|
||||
|
||||
int getZoneFlags() const throw() { return zone; }
|
||||
|
||||
private:
|
||||
|
||||
int zone;
|
||||
|
|
|
|||
|
|
@ -99,13 +99,13 @@ const Rectangle<int> ResizableBorderComponent::Zone::resizeRectangleBy (Rectangl
|
|||
b.setLeft (b.getX() + offset.getX());
|
||||
|
||||
if (isDraggingRightEdge())
|
||||
b.setWidth (b.getWidth() + offset.getX());
|
||||
b.setWidth (jmax (0, b.getWidth() + offset.getX()));
|
||||
|
||||
if (isDraggingTopEdge())
|
||||
b.setTop (b.getY() + offset.getY());
|
||||
|
||||
if (isDraggingBottomEdge())
|
||||
b.setHeight (b.getHeight() + offset.getY());
|
||||
b.setHeight (jmax (0, b.getHeight() + offset.getY()));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,9 @@ public:
|
|||
const Rectangle<int> resizeRectangleBy (Rectangle<int> original,
|
||||
const Point<int>& distance) const throw();
|
||||
|
||||
/** Returns the raw flags for this zone. */
|
||||
int getZoneFlags() const throw() { return zone; }
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
int zone;
|
||||
|
|
|
|||
|
|
@ -221,6 +221,12 @@ public:
|
|||
return Rectangle (x + deltaPosition.getX(), y + deltaPosition.getY(), w, h);
|
||||
}
|
||||
|
||||
/** Returns a rectangle which is the same as this one moved by a given amount. */
|
||||
const Rectangle operator- (const Point<ValueType>& deltaPosition) const throw()
|
||||
{
|
||||
return Rectangle (x - deltaPosition.getX(), y - deltaPosition.getY(), w, h);
|
||||
}
|
||||
|
||||
/** Expands the rectangle by a given amount.
|
||||
|
||||
Effectively, its new size is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2).
|
||||
|
|
|
|||
|
|
@ -570,6 +570,9 @@ void InterProcessLock::exit()
|
|||
{
|
||||
const ScopedLock sl (lock);
|
||||
|
||||
// Trying to release the lock too many times!
|
||||
jassert (pimpl != 0);
|
||||
|
||||
if (pimpl != 0 && --(pimpl->refCount) == 0)
|
||||
pimpl = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -418,6 +418,9 @@ void InterProcessLock::exit()
|
|||
{
|
||||
const ScopedLock sl (lock);
|
||||
|
||||
// Trying to release the lock too many times!
|
||||
jassert (pimpl != 0);
|
||||
|
||||
if (pimpl != 0 && --(pimpl->refCount) == 0)
|
||||
pimpl = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,11 +86,14 @@ public:
|
|||
when the ScopedLockType object is deleted, the InterProcessLock will
|
||||
be unlocked.
|
||||
|
||||
Note that since an InterprocessLock can fail due to errors, you should check
|
||||
isLocked() to make sure that the lock was successful before using it.
|
||||
|
||||
Make sure this object is created and deleted by the same thread,
|
||||
otherwise there are no guarantees what will happen! Best just to use it
|
||||
as a local stack object, rather than creating one with the new() operator.
|
||||
*/
|
||||
inline explicit ScopedLockType (InterProcessLock& lock) : lock_ (lock) { lock.enter(); }
|
||||
explicit ScopedLockType (InterProcessLock& lock) : lock_ (lock) { lockWasSuccessful = lock.enter(); }
|
||||
|
||||
/** Destructor.
|
||||
|
||||
|
|
@ -101,9 +104,13 @@ public:
|
|||
*/
|
||||
inline ~ScopedLockType() { lock_.exit(); }
|
||||
|
||||
/** Returns true if the InterProcessLock was successfully locked. */
|
||||
bool isLocked() const throw() { return lockWasSuccessful; }
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
InterProcessLock& lock_;
|
||||
bool lockWasSuccessful;
|
||||
|
||||
ScopedLockType (const ScopedLockType&);
|
||||
ScopedLockType& operator= (const ScopedLockType&);
|
||||
|
|
|
|||
|
|
@ -86,10 +86,7 @@ public:
|
|||
*/
|
||||
inline ~ScopedTryLock() throw() { if (lockWasSuccessful) lock_.exit(); }
|
||||
|
||||
/** Lock state
|
||||
|
||||
@return True if the CriticalSection is locked.
|
||||
*/
|
||||
/** Returns true if the CriticalSection was successfully locked. */
|
||||
bool isLocked() const throw() { return lockWasSuccessful; }
|
||||
|
||||
private:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue