1
0
Fork 0
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:
Julian Storer 2010-04-14 10:46:23 +01:00
parent 9d5954c08d
commit 5673b7ed5d
16 changed files with 750 additions and 183 deletions

View file

@ -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.");
}

View file

@ -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.");
}

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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();
}

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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).

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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&);

View file

@ -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: