Browse Source

Lots of refactoring of the Expression and relative coordinate classes. This has changed some of the semantics that were in place, so any early adopters who had been playing with RelativeRectangles may need to check their expressions.

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
f01340e4aa
39 changed files with 1935 additions and 1632 deletions
  1. +10
    -10
      extras/Jucer (experimental)/Source/Project/jucer_ProjectInformationComponent.cpp
  2. +1
    -0
      extras/Jucer (experimental)/Source/Utility/jucer_PresetIDs.h
  3. +787
    -660
      juce_amalgamated.cpp
  4. +167
    -150
      juce_amalgamated.h
  5. +2
    -5
      src/audio/audio_file_formats/juce_WavAudioFormat.cpp
  6. +0
    -4
      src/audio/processors/juce_AudioProcessorGraph.cpp
  7. +0
    -5
      src/audio/processors/juce_AudioProcessorGraph.h
  8. +1
    -1
      src/core/juce_StandardHeader.h
  9. +5
    -1
      src/gui/components/controls/juce_ListBox.cpp
  10. +17
    -17
      src/gui/components/juce_Component.h
  11. +8
    -1
      src/gui/components/juce_ModalComponentManager.cpp
  12. +8
    -33
      src/gui/components/positioning/juce_MarkerList.cpp
  13. +29
    -35
      src/gui/components/positioning/juce_RelativeCoordinate.cpp
  14. +22
    -13
      src/gui/components/positioning/juce_RelativeCoordinate.h
  15. +152
    -152
      src/gui/components/positioning/juce_RelativeCoordinatePositioner.cpp
  16. +25
    -12
      src/gui/components/positioning/juce_RelativeCoordinatePositioner.h
  17. +14
    -14
      src/gui/components/positioning/juce_RelativeParallelogram.cpp
  18. +5
    -5
      src/gui/components/positioning/juce_RelativeParallelogram.h
  19. +6
    -12
      src/gui/components/positioning/juce_RelativePoint.cpp
  20. +3
    -8
      src/gui/components/positioning/juce_RelativePoint.h
  21. +14
    -14
      src/gui/components/positioning/juce_RelativePointPath.cpp
  22. +7
    -7
      src/gui/components/positioning/juce_RelativePointPath.h
  23. +75
    -54
      src/gui/components/positioning/juce_RelativeRectangle.cpp
  24. +5
    -5
      src/gui/components/positioning/juce_RelativeRectangle.h
  25. +5
    -1
      src/gui/graphics/drawables/juce_Drawable.h
  26. +3
    -3
      src/gui/graphics/drawables/juce_DrawableComposite.cpp
  27. +1
    -1
      src/gui/graphics/drawables/juce_DrawableComposite.h
  28. +2
    -2
      src/gui/graphics/drawables/juce_DrawableImage.cpp
  29. +1
    -1
      src/gui/graphics/drawables/juce_DrawableImage.h
  30. +24
    -22
      src/gui/graphics/drawables/juce_DrawablePath.cpp
  31. +5
    -5
      src/gui/graphics/drawables/juce_DrawablePath.h
  32. +4
    -4
      src/gui/graphics/drawables/juce_DrawableRectangle.cpp
  33. +1
    -1
      src/gui/graphics/drawables/juce_DrawableRectangle.h
  34. +7
    -6
      src/gui/graphics/drawables/juce_DrawableShape.cpp
  35. +1
    -1
      src/gui/graphics/drawables/juce_DrawableShape.h
  36. +3
    -3
      src/gui/graphics/drawables/juce_DrawableText.cpp
  37. +1
    -1
      src/gui/graphics/drawables/juce_DrawableText.h
  38. +446
    -295
      src/maths/juce_Expression.cpp
  39. +68
    -68
      src/maths/juce_Expression.h

+ 10
- 10
extras/Jucer (experimental)/Source/Project/jucer_ProjectInformationComponent.cpp View File

@@ -104,21 +104,21 @@ ProjectInformationComponent::ProjectInformationComponent (Project& project_)
configTabBox (TabbedButtonBar::TabsAtTop) configTabBox (TabbedButtonBar::TabsAtTop)
{ {
addAndMakeVisible (&configTabBox); addAndMakeVisible (&configTabBox);
configTabBox.setBounds (RelativeRectangle ("8, 0, this.left + parent.right - 16, this.top + parent.bottom - 36"));
configTabBox.setBounds (RelativeRectangle ("8, 0, this.left + parent.width - 16, this.top + parent.height - 36"));
addAndMakeVisible (&editConfigsButton); addAndMakeVisible (&editConfigsButton);
editConfigsButton.setBounds (RelativeRectangle ("8, parent.bottom - 30, this.left + 192, this.top + 22"));
editConfigsButton.setBounds (RelativeRectangle ("8, parent.height - 30, this.left + 192, this.top + 22"));
editConfigsButton.setButtonText ("Add/Remove Configurations..."); editConfigsButton.setButtonText ("Add/Remove Configurations...");
editConfigsButton.addListener (this); editConfigsButton.addListener (this);
addAndMakeVisible (&openProjectButton); addAndMakeVisible (&openProjectButton);
openProjectButton.setBounds (RelativeRectangle ("608, parent.bottom - 30, this.left + 208, this.top + 22"));
openProjectButton.setBounds (RelativeRectangle ("608, parent.height - 30, this.left + 208, this.top + 22"));
openProjectButton.setButtonText ("Open Project in "); openProjectButton.setButtonText ("Open Project in ");
openProjectButton.addListener (this); openProjectButton.addListener (this);
addAndMakeVisible (&editExportersButton); addAndMakeVisible (&editExportersButton);
editExportersButton.setBounds (RelativeRectangle ("208, parent.bottom - 30, this.left + 160, this.top + 22"));
editExportersButton.setBounds (RelativeRectangle ("208, parent.height - 30, this.left + 160, this.top + 22"));
editExportersButton.setButtonText ("Add/Remove Exporters..."); editExportersButton.setButtonText ("Add/Remove Exporters...");
editExportersButton.addListener (this); editExportersButton.addListener (this);
addAndMakeVisible (&saveAndOpenButton); addAndMakeVisible (&saveAndOpenButton);
saveAndOpenButton.setBounds (RelativeRectangle ("391, parent.bottom - 30, this.left + 208, this.top + 22"));
saveAndOpenButton.setBounds (RelativeRectangle ("391, parent.height - 30, this.left + 208, this.top + 22"));
saveAndOpenButton.setButtonText ("Save And Open in"); saveAndOpenButton.setButtonText ("Save And Open in");
saveAndOpenButton.addListener (this); saveAndOpenButton.addListener (this);
@@ -354,22 +354,22 @@ JUCER_COMPONENT_METADATA_START
constructorParams="Project& project_" memberInitialisers="project (project_)"> constructorParams="Project& project_" memberInitialisers="project (project_)">
<COMPONENTS> <COMPONENTS>
<TABBEDCOMPONENT id="962c1575c4142253" memberName="configTabBox" focusOrder="0" <TABBEDCOMPONENT id="962c1575c4142253" memberName="configTabBox" focusOrder="0"
position="8, 0, this.left + parent.right - 16, this.top + parent.bottom - 36"/>
position="8, 0, this.left + parent.width - 16, this.top + parent.height - 36"/>
<TEXTBUTTON id="b6625dfcdb1f4755" memberName="editConfigsButton" focusOrder="0" <TEXTBUTTON id="b6625dfcdb1f4755" memberName="editConfigsButton" focusOrder="0"
text="Add/Remove Configurations..." createCallback="1" radioGroup="0" text="Add/Remove Configurations..." createCallback="1" radioGroup="0"
connectedLeft="0" connectedRight="0" connectedTop="0" connectedBottom="0" connectedLeft="0" connectedRight="0" connectedTop="0" connectedBottom="0"
backgroundColour="" textColour="" backgroundColourOn="" textColourOn="" backgroundColour="" textColour="" backgroundColourOn="" textColourOn=""
position="8, parent.bottom - 30, this.left + 192, this.top + 22"/>
position="8, parent.height - 30, this.left + 192, this.top + 22"/>
<TEXTBUTTON id="a550a652e2666ee7" memberName="openProjectButton" focusOrder="0" <TEXTBUTTON id="a550a652e2666ee7" memberName="openProjectButton" focusOrder="0"
text="Open Project in " createCallback="1" radioGroup="0" connectedLeft="0" text="Open Project in " createCallback="1" radioGroup="0" connectedLeft="0"
connectedRight="0" connectedTop="0" connectedBottom="0" backgroundColour="" connectedRight="0" connectedTop="0" connectedBottom="0" backgroundColour=""
textColour="" backgroundColourOn="" textColourOn="" position="608, parent.bottom - 30, this.left + 208, this.top + 22"/>
textColour="" backgroundColourOn="" textColourOn="" position="608, parent.height - 30, this.left + 208, this.top + 22"/>
<TEXTBUTTON id="c1f6e5f9811b307e" memberName="editExportersButton" focusOrder="0" <TEXTBUTTON id="c1f6e5f9811b307e" memberName="editExportersButton" focusOrder="0"
text="Add/Remove Exporters..." createCallback="1" radioGroup="0" text="Add/Remove Exporters..." createCallback="1" radioGroup="0"
connectedLeft="0" connectedRight="0" connectedTop="0" connectedBottom="0" connectedLeft="0" connectedRight="0" connectedTop="0" connectedBottom="0"
backgroundColour="" textColour="" backgroundColourOn="" textColourOn="" backgroundColour="" textColour="" backgroundColourOn="" textColourOn=""
position="208, parent.bottom - 30, this.left + 160, this.top + 22"/>
<TEXTBUTTON id="dRGMyYx" name="" memberName="saveAndOpenButton" position="391, parent.bottom - 30, this.left + 208, this.top + 22"
position="208, parent.height - 30, this.left + 160, this.top + 22"/>
<TEXTBUTTON id="dRGMyYx" name="" memberName="saveAndOpenButton" position="391, parent.height - 30, this.left + 208, this.top + 22"
text="Save And Open in" createCallback="1" radioGroup="0" connectedLeft="0" text="Save And Open in" createCallback="1" radioGroup="0" connectedLeft="0"
connectedRight="0" connectedTop="0" connectedBottom="0"/> connectedRight="0" connectedTop="0" connectedBottom="0"/>
</COMPONENTS> </COMPONENTS>


+ 1
- 0
extras/Jucer (experimental)/Source/Utility/jucer_PresetIDs.h View File

@@ -112,6 +112,7 @@ namespace Ids
DECLARE_ID (tooltip); DECLARE_ID (tooltip);
DECLARE_ID (memberName); DECLARE_ID (memberName);
DECLARE_ID (focusOrder); DECLARE_ID (focusOrder);
DECLARE_ID (hidden);
const Identifier class_ ("class"); const Identifier class_ ("class");
const Identifier id_ ("id"); const Identifier id_ ("id");


+ 787
- 660
juce_amalgamated.cpp
File diff suppressed because it is too large
View File


+ 167
- 150
juce_amalgamated.h View File

@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
*/ */
#define JUCE_MAJOR_VERSION 1 #define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53 #define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 14
#define JUCE_BUILDNUMBER 15


/** Current Juce version number. /** Current Juce version number.


@@ -17817,7 +17817,7 @@ private:
evaluated. evaluated.


Expressions which use identifiers and functions require a subclass of Expressions which use identifiers and functions require a subclass of
Expression::EvaluationContext to be supplied when evaluating them, and this object
Expression::Scope to be supplied when evaluating them, and this object
is expected to be able to resolve the symbol names and perform the functions that is expected to be able to resolve the symbol names and perform the functions that
are used. are used.
*/ */
@@ -17879,11 +17879,14 @@ public:
/** When evaluating an Expression object, this class is used to resolve symbols and /** When evaluating an Expression object, this class is used to resolve symbols and
perform functions that the expression uses. perform functions that the expression uses.
*/ */
class JUCE_API EvaluationContext
class JUCE_API Scope
{ {
public: public:
EvaluationContext();
virtual ~EvaluationContext();
Scope();
virtual ~Scope();

/** Returns some kind of globally unique ID that identifies this scope. */
virtual const String getScopeUID() const;


/** Returns the value of a symbol. /** Returns the value of a symbol.
If the symbol is unknown, this can throw an Expression::EvaluationError exception. If the symbol is unknown, this can throw an Expression::EvaluationError exception.
@@ -17891,55 +17894,97 @@ public:
one, e.g. for "foo.bar", symbol = "foo" and member = "bar". one, e.g. for "foo.bar", symbol = "foo" and member = "bar".
@throws Expression::EvaluationError @throws Expression::EvaluationError
*/ */
virtual const Expression getSymbolValue (const String& symbol, const String& member) const;
virtual const Expression getSymbolValue (const String& symbol) const;


/** Executes a named function. /** Executes a named function.
If the function name is unknown, this can throw an Expression::EvaluationError exception. If the function name is unknown, this can throw an Expression::EvaluationError exception.
@throws Expression::EvaluationError @throws Expression::EvaluationError
*/ */
virtual double evaluateFunction (const String& functionName, const double* parameters, int numParams) const;
virtual double evaluateFunction (const String& functionName,
const double* parameters, int numParameters) const;

/** Used as a callback by the Scope::visitRelativeScope() method.
You should never create an instance of this class yourself, it's used by the
expression evaluation code.
*/
class Visitor
{
public:
virtual ~Visitor() {}
virtual void visit (const Scope&) = 0;
};

/** Creates a Scope object for a named scope, and then calls a visitor
to do some kind of processing with this new scope.

If the name is valid, this method must create a suitable (temporary) Scope
object to represent it, and must call the Visitor::visit() method with this
new scope.
*/
virtual void visitRelativeScope (const String& scopeName, Visitor& visitor) const;
}; };


/** Evaluates this expression, without using an EvaluationContext.
Without an EvaluationContext, no symbols can be used, and only basic functions such as sin, cos, tan,
/** Evaluates this expression, without using a Scope.
Without a Scope, no symbols can be used, and only basic functions such as sin, cos, tan,
min, max are available. min, max are available.
@throws Expression::EvaluationError
To find out about any errors during evaluation, use the other version of this method which
takes a String parameter.
*/ */
double evaluate() const; double evaluate() const;


/** Evaluates this expression, providing a context that should be able to evaluate any symbols
/** Evaluates this expression, providing a scope that should be able to evaluate any symbols
or functions that it uses.
To find out about any errors during evaluation, use the other version of this method which
takes a String parameter.
*/
double evaluate (const Scope& scope) const;

/** Evaluates this expression, providing a scope that should be able to evaluate any symbols
or functions that it uses. or functions that it uses.
@throws Expression::EvaluationError
*/ */
double evaluate (const EvaluationContext& context) const;
double evaluate (const Scope& scope, String& evaluationError) const;


/** Attempts to return an expression which is a copy of this one, but with a constant adjusted /** Attempts to return an expression which is a copy of this one, but with a constant adjusted
to make the expression resolve to a target value. to make the expression resolve to a target value.


E.g. if the expression is "x + 10" and x is 5, then asking for a target value of 8 will return E.g. if the expression is "x + 10" and x is 5, then asking for a target value of 8 will return
the expression "x + 3". Obviously some expressions can't be reversed in this way, in which the expression "x + 3". Obviously some expressions can't be reversed in this way, in which
case they might just be adjusted by adding a constant to them.
case they might just be adjusted by adding a constant to the original expression.


@throws Expression::EvaluationError @throws Expression::EvaluationError
*/ */
const Expression adjustedToGiveNewResult (double targetValue, const EvaluationContext& context) const;
const Expression adjustedToGiveNewResult (double targetValue, const Scope& scope) const;

/** Represents a symbol that is used in an Expression. */
struct Symbol
{
Symbol (const String& scopeUID, const String& symbolName);
bool operator== (const Symbol&) const throw();
bool operator!= (const Symbol&) const throw();

String scopeUID; /**< The unique ID of the Scope that contains this symbol. */
String symbolName; /**< The name of the symbol. */
};


/** Returns a copy of this expression in which all instances of a given symbol have been renamed. */ /** Returns a copy of this expression in which all instances of a given symbol have been renamed. */
const Expression withRenamedSymbol (const String& oldSymbol, const String& newSymbol) const;
const Expression withRenamedSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope) const;


/** Returns true if this expression makes use of the specified symbol. /** Returns true if this expression makes use of the specified symbol.
If a suitable context is supplied, the search will dereference and recursively check
If a suitable scope is supplied, the search will dereference and recursively check
all symbols, so that it can be determined whether this expression relies on the given all symbols, so that it can be determined whether this expression relies on the given
symbol at any level in its evaluation. If the context parameter is null, this just checks
symbol at any level in its evaluation. If the scope parameter is null, this just checks
whether the expression contains any direct references to the symbol. whether the expression contains any direct references to the symbol.


@throws Expression::EvaluationError @throws Expression::EvaluationError
*/ */
bool referencesSymbol (const String& symbol, const EvaluationContext* context) const;
bool referencesSymbol (const Symbol& symbol, const Scope& scope) const;


/** Returns true if this expression contains any symbols. */ /** Returns true if this expression contains any symbols. */
bool usesAnySymbols() const; bool usesAnySymbols() const;


/** Returns a list of all symbols that may be needed to resolve this expression in the given scope. */
void findReferencedSymbols (Array<Symbol>& results, const Scope& scope) const;

/** An exception that can be thrown by Expression::parse(). */ /** An exception that can be thrown by Expression::parse(). */
class ParseError : public std::exception class ParseError : public std::exception
{ {
@@ -17949,16 +17994,6 @@ public:
String description; String description;
}; };


/** An exception that can be thrown by Expression::evaluate(). */
class EvaluationError : public std::exception
{
public:
EvaluationError (const String& message);
EvaluationError (const String& symbolName, const String& memberName);

String description;
};

/** Expression type. /** Expression type.
@see Expression::getType() @see Expression::getType()
*/ */
@@ -17973,19 +18008,8 @@ public:
/** Returns the type of this expression. */ /** Returns the type of this expression. */
Type getType() const throw(); Type getType() const throw();


/** If this expression is a symbol, this returns its full name. */
const String getSymbol() const;

/** For a symbol that contains a dot, this returns the two */
void getSymbolParts (String& objectName, String& memberName) const;

/** If this expression is a function, this returns its name. */
const String getFunction() const;

/** If this expression is an operator, this returns its name.
E.g. "+", "-", "*", "/", etc.
*/
const String getOperator() const;
/** If this expression is a symbol, function or operator, this returns its identifier. */
const String getSymbolOrFunction() const;


/** Returns the number of inputs to this expression. /** Returns the number of inputs to this expression.
@see getInput @see getInput
@@ -17999,35 +18023,12 @@ public:


private: private:


class Term;
class Helpers; class Helpers;
friend class Term;
friend class Helpers; friend class Helpers;

class Term : public ReferenceCountedObject
{
public:
Term() {}
virtual ~Term() {}

virtual Term* clone() const = 0;
virtual double evaluate (const EvaluationContext&, int recursionDepth) const = 0;
virtual int getNumInputs() const = 0;
virtual Term* getInput (int index) const = 0;
virtual int getInputIndexFor (const Term* possibleInput) const;
virtual const String toString() const = 0;
virtual int getOperatorPrecedence() const;
virtual bool referencesSymbol (const String& symbol, const EvaluationContext*, int recursionDepth) const;
virtual const ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const EvaluationContext&, const Term* inputTerm,
double overallTarget, Term* topLevelTerm) const;
virtual const ReferenceCountedObjectPtr<Term> negated();
virtual Type getType() const throw() = 0;
virtual void getSymbolParts (String& objectName, String& memberName) const;
virtual const String getFunctionName() const;

private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Term);
};

friend class ScopedPointer<Term>; friend class ScopedPointer<Term>;
friend class ReferenceCountedObjectPtr<Term>;
ReferenceCountedObjectPtr<Term> term; ReferenceCountedObjectPtr<Term> term;


explicit Expression (Term* term); explicit Expression (Term* term);
@@ -27477,35 +27478,35 @@ public:
for more details. for more details.


When using relative expressions, the following symbols are available: When using relative expressions, the following symbols are available:
- "this.left", "this.right", "this.top", "this.bottom" refer to the position of those
edges in this component, so e.g. for a component whose width is always 100, you might
set the right edge to the "this.left + 100".
- "parent.left", "parent.right", "parent.top", "parent.bottom" refer to the parent component's
positions, in its own coordinate space, so "parent.left", "parent.right" are always 0, and
"parent.top", "parent.bottom" will actually be the width and height of the parent. So
for example to make your component's right-hand edge always 10 pixels away from its parent's
right-hand edge, you could set it to "parent.right - 10"
- "[id].left", "[id].right", "[id].top", "[id].bottom", where [id] is the identifier of one of
this component's siblings. A component's identifier is set with Component::setComponentID().
So for example if you want your component to always be 50 pixels to the right of the one
called "xyz", you could set your left edge to be "xyz.right + 50"
- The name of a marker that is defined in the parent component. For markers to be used, the parent
component must implement its Component::getMarkers() method, and return at least one
- "left", "right", "top", "bottom" refer to the position of those edges in this component, so
e.g. for a component whose width is always 100, you might set the right edge to the "left + 100".
- "[id].left", "[id].right", "[id].top", "[id].bottom", "[id].width", "[id].height", where [id] is
the identifier of one of this component's siblings. A component's identifier is set with
Component::setComponentID(). So for example if you want your component to always be 50 pixels to the
right of the one called "xyz", you could set your left edge to be "xyz.right + 50".
- Instead of an [id], you can use the name "parent" to refer to this component's parent. Like
any other component, these values are relative to their component's parent, so "parent.right" won't be
very useful for positioning a component because it refers to a position with the parent's parent.. but
"parent.width" can be used for setting positions relative to the parent's size. E.g. to make a 10x10
component which remains 1 pixel away from its parent's bottom-right, you could use
"right - 10, bottom - 10, parent.width - 1, parent.height - 1".
- The name of one of the parent component's markers can also be used as a symbol. For markers to be
used, the parent component must implement its Component::getMarkers() method, and return at least one
valid MarkerList. So if you want your component's top edge to be 10 pixels below the valid MarkerList. So if you want your component's top edge to be 10 pixels below the
marker called "foobar", you'd set it to "foobar + 10". marker called "foobar", you'd set it to "foobar + 10".


See the Expression class for details about the operators that are supported, but for example See the Expression class for details about the operators that are supported, but for example
if you wanted to make your component remain centred within its parent with a size of 100, 100, if you wanted to make your component remain centred within its parent with a size of 100, 100,
you could express it as: you could express it as:
@code myComp.setBounds (RelativeBounds ("parent.right / 2 - 50, parent.bottom / 2 - 50, this.left + 100, this.top + 100"));
@code myComp.setBounds (RelativeBounds ("parent.width / 2 - 50, parent.height / 2 - 50, left + 100, top + 100"));
@endcode @endcode
..or an alternative way to achieve the same thing: ..or an alternative way to achieve the same thing:
@code myComp.setBounds (RelativeBounds ("this.right - 100, this.bottom - 100, parent.right / 2 + 50, parent.bottom / 2 + 50"));
@code myComp.setBounds (RelativeBounds ("right - 100, bottom - 100, parent.width / 2 + 50, parent.height / 2 + 50"));
@endcode @endcode


Or if you wanted a 100x100 component whose top edge is lined up to a marker called "topMarker" and Or if you wanted a 100x100 component whose top edge is lined up to a marker called "topMarker" and
which is positioned 50 pixels to the right of another component called "otherComp", you could write: which is positioned 50 pixels to the right of another component called "otherComp", you could write:
@code myComp.setBounds (RelativeBounds ("otherComp.right + 50, topMarker, this.left + 100, this.top + 100"));
@code myComp.setBounds (RelativeBounds ("otherComp.right + 50, topMarker, left + 100, top + 100"));
@endcode @endcode


Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will
@@ -43481,7 +43482,6 @@ public:
AudioProcessorGraph(); AudioProcessorGraph();


/** Destructor. /** Destructor.

Any processor objects that have been added to the graph will also be deleted. Any processor objects that have been added to the graph will also be deleted.
*/ */
~AudioProcessorGraph(); ~AudioProcessorGraph();
@@ -43493,9 +43493,6 @@ public:
class JUCE_API Node : public ReferenceCountedObject class JUCE_API Node : public ReferenceCountedObject
{ {
public: public:
/** Destructor.
*/
~Node();


/** The ID number assigned to this node. /** The ID number assigned to this node.


@@ -45643,18 +45640,18 @@ public:


/** Calculates the absolute position of this coordinate. /** Calculates the absolute position of this coordinate.


You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
You'll need to provide a suitable Expression::Scope for looking up any coordinates that may
be needed to calculate the result. be needed to calculate the result.
*/ */
double resolve (const Expression::EvaluationContext* evaluationContext) const;
double resolve (const Expression::Scope* evaluationScope) const;


/** Returns true if this coordinate uses the specified coord name at any level in its evaluation. /** Returns true if this coordinate uses the specified coord name at any level in its evaluation.
This will recursively check any coordinates upon which this one depends. This will recursively check any coordinates upon which this one depends.
*/ */
bool references (const String& coordName, const Expression::EvaluationContext* evaluationContext) const;
bool references (const String& coordName, const Expression::Scope* evaluationScope) const;


/** Returns true if there's a recursive loop when trying to resolve this coordinate's position. */ /** Returns true if there's a recursive loop when trying to resolve this coordinate's position. */
bool isRecursive (const Expression::EvaluationContext* evaluationContext) const;
bool isRecursive (const Expression::Scope* evaluationScope) const;


/** Returns true if this coordinate depends on any other coordinates for its position. */ /** Returns true if this coordinate depends on any other coordinates for its position. */
bool isDynamic() const; bool isDynamic() const;
@@ -45665,10 +45662,7 @@ public:
or relative position to whatever value is necessary to make its resultant position or relative position to whatever value is necessary to make its resultant position
match the position that is provided. match the position that is provided.
*/ */
void moveToAbsolute (double absoluteTargetPosition, const Expression::EvaluationContext* evaluationContext);

/** Changes the name of a symbol if it is used as part of the coordinate's expression. */
void renameSymbolIfUsed (const String& oldName, const String& newName);
void moveToAbsolute (double absoluteTargetPosition, const Expression::Scope* evaluationScope);


/** Returns the expression that defines this coordinate. */ /** Returns the expression that defines this coordinate. */
const Expression& getExpression() const { return term; } const Expression& getExpression() const { return term; }
@@ -45688,15 +45682,27 @@ public:
struct Strings struct Strings
{ {
static const String parent; /**< "parent" */ static const String parent; /**< "parent" */
static const String this_; /**< "this" */
static const String left; /**< "left" */ static const String left; /**< "left" */
static const String right; /**< "right" */ static const String right; /**< "right" */
static const String top; /**< "top" */ static const String top; /**< "top" */
static const String bottom; /**< "bottom" */ static const String bottom; /**< "bottom" */
static const String parentLeft; /**< "parent.left" */
static const String parentTop; /**< "parent.top" */
static const String parentRight; /**< "parent.right" */
static const String parentBottom; /**< "parent.bottom" */
static const String x; /**< "x" */
static const String y; /**< "y" */
static const String width; /**< "width" */
static const String height; /**< "height" */
};

struct StandardStrings
{
enum Type
{
left, right, top, bottom,
x, y, width, height,
parent,
unknown
};

static Type getTypeOf (const String& s) throw();
}; };


private: private:
@@ -45749,10 +45755,10 @@ public:


/** Calculates the absolute position of this point. /** Calculates the absolute position of this point.


You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
You'll need to provide a suitable Expression::Scope for looking up any coordinates that may
be needed to calculate the result. be needed to calculate the result.
*/ */
const Point<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
const Point<float> resolve (const Expression::Scope* evaluationContext) const;


/** Changes the values of this point's coordinates to make it resolve to the specified position. /** Changes the values of this point's coordinates to make it resolve to the specified position.


@@ -45760,7 +45766,7 @@ public:
or relative positions to whatever values are necessary to make the resultant position or relative positions to whatever values are necessary to make the resultant position
match the position that is provided. match the position that is provided.
*/ */
void moveToAbsolute (const Point<float>& newPos, const Expression::EvaluationContext* evaluationContext);
void moveToAbsolute (const Point<float>& newPos, const Expression::Scope* evaluationContext);


/** Returns a string which represents this point. /** Returns a string which represents this point.
This returns a comma-separated pair of coordinates. For details of the string syntax used by the This returns a comma-separated pair of coordinates. For details of the string syntax used by the
@@ -45769,11 +45775,6 @@ public:
*/ */
const String toString() const; const String toString() const;


/** Renames a symbol if it is used by any of the coordinates.
This calls RelativeCoordinate::renameAnchorIfUsed() on its X and Y coordinates.
*/
void renameSymbolIfUsed (const String& oldName, const String& newName);

/** Returns true if this point depends on any other coordinates for its position. */ /** Returns true if this point depends on any other coordinates for its position. */
bool isDynamic() const; bool isDynamic() const;


@@ -45946,15 +45947,12 @@ private:
*/ */
class JUCE_API RelativeCoordinatePositionerBase : public Component::Positioner, class JUCE_API RelativeCoordinatePositionerBase : public Component::Positioner,
public ComponentListener, public ComponentListener,
public MarkerList::Listener,
public Expression::EvaluationContext
public MarkerList::Listener
{ {
public: public:
RelativeCoordinatePositionerBase (Component& component_); RelativeCoordinatePositionerBase (Component& component_);
~RelativeCoordinatePositionerBase(); ~RelativeCoordinatePositionerBase();


const Expression getSymbolValue (const String& objectName, const String& member) const;

void componentMovedOrResized (Component&, bool, bool); void componentMovedOrResized (Component&, bool, bool);
void componentParentHierarchyChanged (Component&); void componentParentHierarchyChanged (Component&);
void componentBeingDeleted (Component& component); void componentBeingDeleted (Component& component);
@@ -45966,25 +45964,40 @@ public:
bool addCoordinate (const RelativeCoordinate& coord); bool addCoordinate (const RelativeCoordinate& coord);
bool addPoint (const RelativePoint& point); bool addPoint (const RelativePoint& point);


/** Used for resolving a RelativeCoordinate expression in the context of a component. */
class ComponentScope : public Expression::Scope
{
public:
ComponentScope (Component& component_);

const Expression getSymbolValue (const String& symbol) const;
void visitRelativeScope (const String& scopeName, Visitor& visitor) const;
const String getScopeUID() const;

protected:
Component& component;

Component* findSiblingComponent (const String& componentID) const;
const MarkerList::Marker* findMarker (const String& name, MarkerList*& list) const;

private:
JUCE_DECLARE_NON_COPYABLE (ComponentScope);
};

protected: protected:
virtual bool registerCoordinates() = 0; virtual bool registerCoordinates() = 0;
virtual void applyToComponentBounds() = 0; virtual void applyToComponentBounds() = 0;


private: private:
class DependencyFinderScope;
friend class DependencyFinderScope;
Array <Component*> sourceComponents; Array <Component*> sourceComponents;
Array <MarkerList*> sourceMarkerLists; Array <MarkerList*> sourceMarkerLists;
bool registeredOk; bool registeredOk;


bool registerListeners (const Expression& e);
bool registerComponent (const String& componentID);
bool registerMarker (const String markerName);
void registerComponentListener (Component* const comp);
void registerComponentListener (Component& comp);
void registerMarkerListListener (MarkerList* const list); void registerMarkerListListener (MarkerList* const list);
void unregisterListeners(); void unregisterListeners();
Component* findComponent (const String& componentID) const;
Component* getSourceComponent (const String& objectName) const;
const Expression xToExpression (const Component* const source, const int x) const;
const Expression yToExpression (const Component* const source, const int y) const;


JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeCoordinatePositionerBase); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeCoordinatePositionerBase);
}; };
@@ -46395,7 +46408,11 @@ protected:
{} {}


bool registerCoordinates() { return owner.registerCoordinates (*this); } bool registerCoordinates() { return owner.registerCoordinates (*this); }
void applyToComponentBounds() { owner.recalculateCoordinates (this); }
void applyToComponentBounds()
{
ComponentScope scope (getComponent());
owner.recalculateCoordinates (&scope);
}


private: private:
DrawableType& owner; DrawableType& owner;
@@ -57857,11 +57874,11 @@ public:
RelativeParallelogram (const String& topLeft, const String& topRight, const String& bottomLeft); RelativeParallelogram (const String& topLeft, const String& topRight, const String& bottomLeft);
~RelativeParallelogram(); ~RelativeParallelogram();


void resolveThreePoints (Point<float>* points, Expression::EvaluationContext* coordFinder) const;
void resolveFourCorners (Point<float>* points, Expression::EvaluationContext* coordFinder) const;
const Rectangle<float> getBounds (Expression::EvaluationContext* coordFinder) const;
void getPath (Path& path, Expression::EvaluationContext* coordFinder) const;
const AffineTransform resetToPerpendicular (Expression::EvaluationContext* coordFinder);
void resolveThreePoints (Point<float>* points, Expression::Scope* scope) const;
void resolveFourCorners (Point<float>* points, Expression::Scope* scope) const;
const Rectangle<float> getBounds (Expression::Scope* scope) const;
void getPath (Path& path, Expression::Scope* scope) const;
const AffineTransform resetToPerpendicular (Expression::Scope* scope);
bool isDynamic() const; bool isDynamic() const;


bool operator== (const RelativeParallelogram& other) const throw(); bool operator== (const RelativeParallelogram& other) const throw();
@@ -57911,7 +57928,7 @@ public:
bool operator!= (const RelativePointPath& other) const throw(); bool operator!= (const RelativePointPath& other) const throw();


/** Resolves this points in this path and adds them to a normal Path object. */ /** Resolves this points in this path and adds them to a normal Path object. */
void createPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void createPath (Path& path, Expression::Scope* scope) const;


/** Returns true if the path contains any non-fixed points. */ /** Returns true if the path contains any non-fixed points. */
bool containsAnyDynamicPoints() const; bool containsAnyDynamicPoints() const;
@@ -57940,7 +57957,7 @@ public:
ElementBase (ElementType type); ElementBase (ElementType type);
virtual ~ElementBase() {} virtual ~ElementBase() {}
virtual const ValueTree createTree() const = 0; virtual const ValueTree createTree() const = 0;
virtual void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const = 0;
virtual void addToPath (Path& path, Expression::Scope*) const = 0;
virtual RelativePoint* getControlPoints (int& numPoints) = 0; virtual RelativePoint* getControlPoints (int& numPoints) = 0;
virtual ElementBase* clone() const = 0; virtual ElementBase* clone() const = 0;
bool isDynamic(); bool isDynamic();
@@ -57956,7 +57973,7 @@ public:
public: public:
StartSubPath (const RelativePoint& pos); StartSubPath (const RelativePoint& pos);
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;


@@ -57971,7 +57988,7 @@ public:
public: public:
CloseSubPath(); CloseSubPath();
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;


@@ -57984,7 +58001,7 @@ public:
public: public:
LineTo (const RelativePoint& endPoint); LineTo (const RelativePoint& endPoint);
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;


@@ -57999,7 +58016,7 @@ public:
public: public:
QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint); QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint);
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;


@@ -58014,7 +58031,7 @@ public:
public: public:
CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint); CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint);
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;


@@ -58087,10 +58104,10 @@ public:


/** Calculates the absolute position of this rectangle. /** Calculates the absolute position of this rectangle.


You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
You'll need to provide a suitable Expression::Scope for looking up any coordinates that may
be needed to calculate the result. be needed to calculate the result.
*/ */
const Rectangle<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
const Rectangle<float> resolve (const Expression::Scope* scope) const;


/** Changes the values of this rectangle's coordinates to make it resolve to the specified position. /** Changes the values of this rectangle's coordinates to make it resolve to the specified position.


@@ -58098,7 +58115,7 @@ public:
or relative positions to whatever values are necessary to make the resultant position or relative positions to whatever values are necessary to make the resultant position
match the position that is provided. match the position that is provided.
*/ */
void moveToAbsolute (const Rectangle<float>& newPos, const Expression::EvaluationContext* evaluationContext);
void moveToAbsolute (const Rectangle<float>& newPos, const Expression::Scope* scope);


/** Returns true if this rectangle depends on any external symbols for its position. /** Returns true if this rectangle depends on any external symbols for its position.
Coordinates that refer to symbols based on "this" are assumed not to be dynamic. Coordinates that refer to symbols based on "this" are assumed not to be dynamic.
@@ -58113,9 +58130,9 @@ public:
const String toString() const; const String toString() const;


/** Renames a symbol if it is used by any of the coordinates. /** Renames a symbol if it is used by any of the coordinates.
This calls RelativeCoordinate::renameSymbolIfUsed() on the rectangle's coordinates.
This calls Expression::withRenamedSymbol() on the rectangle's coordinates.
*/ */
void renameSymbolIfUsed (const String& oldName, const String& newName);
void renameSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Expression::Scope& scope);


/** Creates and sets an appropriate Component::Positioner object for the given component, which will /** Creates and sets an appropriate Component::Positioner object for the given component, which will
keep it positioned with this rectangle. keep it positioned with this rectangle.
@@ -61907,7 +61924,7 @@ private:


friend class Drawable::Positioner<DrawableComposite>; friend class Drawable::Positioner<DrawableComposite>;
bool registerCoordinates (RelativeCoordinatePositionerBase&); bool registerCoordinates (RelativeCoordinatePositionerBase&);
void recalculateCoordinates (Expression::EvaluationContext*);
void recalculateCoordinates (Expression::Scope*);


void updateBoundsToFitChildren(); void updateBoundsToFitChildren();


@@ -62024,7 +62041,7 @@ private:


friend class Drawable::Positioner<DrawableImage>; friend class Drawable::Positioner<DrawableImage>;
bool registerCoordinates (RelativeCoordinatePositionerBase&); bool registerCoordinates (RelativeCoordinatePositionerBase&);
void recalculateCoordinates (Expression::EvaluationContext*);
void recalculateCoordinates (Expression::Scope*);


DrawableImage& operator= (const DrawableImage&); DrawableImage& operator= (const DrawableImage&);
JUCE_LEAK_DETECTOR (DrawableImage); JUCE_LEAK_DETECTOR (DrawableImage);
@@ -62077,7 +62094,7 @@ public:
bool operator!= (const RelativeFillType&) const; bool operator!= (const RelativeFillType&) const;


bool isDynamic() const; bool isDynamic() const;
bool recalculateCoords (Expression::EvaluationContext* context);
bool recalculateCoords (Expression::Scope* scope);


void writeTo (ValueTree& v, ComponentBuilder::ImageProvider*, UndoManager*) const; void writeTo (ValueTree& v, ComponentBuilder::ImageProvider*, UndoManager*) const;
bool readFrom (const ValueTree& v, ComponentBuilder::ImageProvider*); bool readFrom (const ValueTree& v, ComponentBuilder::ImageProvider*);
@@ -62260,7 +62277,7 @@ public:
const RelativePoint getStartPoint() const; const RelativePoint getStartPoint() const;
const RelativePoint getEndPoint() const; const RelativePoint getEndPoint() const;
void setControlPoint (int index, const RelativePoint& point, UndoManager*); void setControlPoint (int index, const RelativePoint& point, UndoManager*);
float getLength (Expression::EvaluationContext*) const;
float getLength (Expression::Scope*) const;


ValueTreeWrapper getParent() const; ValueTreeWrapper getParent() const;
Element getPreviousElement() const; Element getPreviousElement() const;
@@ -62269,11 +62286,11 @@ public:
void setModeOfEndPoint (const String& newMode, UndoManager*); void setModeOfEndPoint (const String& newMode, UndoManager*);


void convertToLine (UndoManager*); void convertToLine (UndoManager*);
void convertToCubic (Expression::EvaluationContext*, UndoManager*);
void convertToCubic (Expression::Scope*, UndoManager*);
void convertToPathBreak (UndoManager* undoManager); void convertToPathBreak (UndoManager* undoManager);
ValueTree insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext*, UndoManager*);
ValueTree insertPoint (const Point<float>& targetPoint, Expression::Scope*, UndoManager*);
void removePoint (UndoManager* undoManager); void removePoint (UndoManager* undoManager);
float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext*) const;
float findProportionAlongLine (const Point<float>& targetPoint, Expression::Scope*) const;


static const Identifier mode, startSubPathElement, closeSubPathElement, static const Identifier mode, startSubPathElement, closeSubPathElement,
lineToElement, quadraticToElement, cubicToElement; lineToElement, quadraticToElement, cubicToElement;
@@ -62298,7 +62315,7 @@ private:


class RelativePositioner; class RelativePositioner;
friend class RelativePositioner; friend class RelativePositioner;
void applyRelativePath (const RelativePointPath&, Expression::EvaluationContext*);
void applyRelativePath (const RelativePointPath&, Expression::Scope*);


DrawablePath& operator= (const DrawablePath&); DrawablePath& operator= (const DrawablePath&);
JUCE_LEAK_DETECTOR (DrawablePath); JUCE_LEAK_DETECTOR (DrawablePath);
@@ -62377,7 +62394,7 @@ private:


void rebuildPath(); void rebuildPath();
bool registerCoordinates (RelativeCoordinatePositionerBase&); bool registerCoordinates (RelativeCoordinatePositionerBase&);
void recalculateCoordinates (Expression::EvaluationContext*);
void recalculateCoordinates (Expression::Scope*);


DrawableRectangle& operator= (const DrawableRectangle&); DrawableRectangle& operator= (const DrawableRectangle&);
JUCE_LEAK_DETECTOR (DrawableRectangle); JUCE_LEAK_DETECTOR (DrawableRectangle);
@@ -62503,7 +62520,7 @@ private:


friend class Drawable::Positioner<DrawableText>; friend class Drawable::Positioner<DrawableText>;
bool registerCoordinates (RelativeCoordinatePositionerBase&); bool registerCoordinates (RelativeCoordinatePositionerBase&);
void recalculateCoordinates (Expression::EvaluationContext*);
void recalculateCoordinates (Expression::Scope*);
void refreshBounds(); void refreshBounds();
const AffineTransform getArrangementAndTransform (GlyphArrangement& glyphs) const; const AffineTransform getArrangementAndTransform (GlyphArrangement& glyphs) const;




+ 2
- 5
src/audio/audio_file_formats/juce_WavAudioFormat.cpp View File

@@ -370,10 +370,6 @@ public:
} }
} }
~WavAudioFormatReader()
{
}
//============================================================================== //==============================================================================
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
int64 startSampleInFile, int numSamples) int64 startSampleInFile, int numSamples)
@@ -532,7 +528,8 @@ private:
const int bytesPerFrame = numChannels * bitsPerSample / 8; const int bytesPerFrame = numChannels * bitsPerSample / 8;
output->writeInt (chunkName ("RIFF")); output->writeInt (chunkName ("RIFF"));
output->writeInt ((int) (lengthInSamples * bytesPerFrame output->writeInt ((int) (lengthInSamples * bytesPerFrame
+ ((bwavChunk.getSize() > 0) ? (44 + bwavChunk.getSize()) : 36)));
+ ((bwavChunk.getSize() > 0) ? (44 + bwavChunk.getSize()) : 36)
+ (smplChunk.getSize() > 0 ? smplChunk.getSize() + 8 : 0)));
output->writeInt (chunkName ("WAVE")); output->writeInt (chunkName ("WAVE"));
output->writeInt (chunkName ("fmt ")); output->writeInt (chunkName ("fmt "));


+ 0
- 4
src/audio/processors/juce_AudioProcessorGraph.cpp View File

@@ -42,10 +42,6 @@ AudioProcessorGraph::Node::Node (const uint32 id_, AudioProcessor* const process
jassert (processor_ != 0); jassert (processor_ != 0);
} }
AudioProcessorGraph::Node::~Node()
{
}
void AudioProcessorGraph::Node::prepare (const double sampleRate, const int blockSize, void AudioProcessorGraph::Node::prepare (const double sampleRate, const int blockSize,
AudioProcessorGraph* const graph) AudioProcessorGraph* const graph)
{ {


+ 0
- 5
src/audio/processors/juce_AudioProcessorGraph.h View File

@@ -57,7 +57,6 @@ public:
AudioProcessorGraph(); AudioProcessorGraph();
/** Destructor. /** Destructor.
Any processor objects that have been added to the graph will also be deleted. Any processor objects that have been added to the graph will also be deleted.
*/ */
~AudioProcessorGraph(); ~AudioProcessorGraph();
@@ -70,10 +69,6 @@ public:
class JUCE_API Node : public ReferenceCountedObject class JUCE_API Node : public ReferenceCountedObject
{ {
public: public:
/** Destructor.
*/
~Node();
//============================================================================== //==============================================================================
/** The ID number assigned to this node. /** The ID number assigned to this node.


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/ */
#define JUCE_MAJOR_VERSION 1 #define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53 #define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 14
#define JUCE_BUILDNUMBER 15
/** Current Juce version number. /** Current Juce version number.


+ 5
- 1
src/gui/components/controls/juce_ListBox.cpp View File

@@ -888,8 +888,13 @@ const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY)
Graphics g (snapshot); Graphics g (snapshot);
g.setOrigin (pos.getX() - imageX, pos.getY() - imageY); g.setOrigin (pos.getX() - imageX, pos.getY() - imageY);
if (g.reduceClipRegion (rowComp->getLocalBounds())) if (g.reduceClipRegion (rowComp->getLocalBounds()))
{
g.beginTransparencyLayer (0.6f);
rowComp->paintEntireComponent (g, false); rowComp->paintEntireComponent (g, false);
g.endTransparencyLayer();
}
} }
} }
@@ -905,7 +910,6 @@ void ListBox::startDragAndDrop (const MouseEvent& e, const String& dragDescripti
{ {
int x, y; int x, y;
Image dragImage (createSnapshotOfSelectedRows (x, y)); Image dragImage (createSnapshotOfSelectedRows (x, y));
dragImage.multiplyAllAlphas (0.6f);
MouseEvent e2 (e.getEventRelativeTo (this)); MouseEvent e2 (e.getEventRelativeTo (this));
const Point<int> p (x - e2.x, y - e2.y); const Point<int> p (x - e2.x, y - e2.y);


+ 17
- 17
src/gui/components/juce_Component.h View File

@@ -488,35 +488,35 @@ public:
for more details. for more details.
When using relative expressions, the following symbols are available: When using relative expressions, the following symbols are available:
- "this.left", "this.right", "this.top", "this.bottom" refer to the position of those
edges in this component, so e.g. for a component whose width is always 100, you might
set the right edge to the "this.left + 100".
- "parent.left", "parent.right", "parent.top", "parent.bottom" refer to the parent component's
positions, in its own coordinate space, so "parent.left", "parent.right" are always 0, and
"parent.top", "parent.bottom" will actually be the width and height of the parent. So
for example to make your component's right-hand edge always 10 pixels away from its parent's
right-hand edge, you could set it to "parent.right - 10"
- "[id].left", "[id].right", "[id].top", "[id].bottom", where [id] is the identifier of one of
this component's siblings. A component's identifier is set with Component::setComponentID().
So for example if you want your component to always be 50 pixels to the right of the one
called "xyz", you could set your left edge to be "xyz.right + 50"
- The name of a marker that is defined in the parent component. For markers to be used, the parent
component must implement its Component::getMarkers() method, and return at least one
- "left", "right", "top", "bottom" refer to the position of those edges in this component, so
e.g. for a component whose width is always 100, you might set the right edge to the "left + 100".
- "[id].left", "[id].right", "[id].top", "[id].bottom", "[id].width", "[id].height", where [id] is
the identifier of one of this component's siblings. A component's identifier is set with
Component::setComponentID(). So for example if you want your component to always be 50 pixels to the
right of the one called "xyz", you could set your left edge to be "xyz.right + 50".
- Instead of an [id], you can use the name "parent" to refer to this component's parent. Like
any other component, these values are relative to their component's parent, so "parent.right" won't be
very useful for positioning a component because it refers to a position with the parent's parent.. but
"parent.width" can be used for setting positions relative to the parent's size. E.g. to make a 10x10
component which remains 1 pixel away from its parent's bottom-right, you could use
"right - 10, bottom - 10, parent.width - 1, parent.height - 1".
- The name of one of the parent component's markers can also be used as a symbol. For markers to be
used, the parent component must implement its Component::getMarkers() method, and return at least one
valid MarkerList. So if you want your component's top edge to be 10 pixels below the valid MarkerList. So if you want your component's top edge to be 10 pixels below the
marker called "foobar", you'd set it to "foobar + 10". marker called "foobar", you'd set it to "foobar + 10".
See the Expression class for details about the operators that are supported, but for example See the Expression class for details about the operators that are supported, but for example
if you wanted to make your component remain centred within its parent with a size of 100, 100, if you wanted to make your component remain centred within its parent with a size of 100, 100,
you could express it as: you could express it as:
@code myComp.setBounds (RelativeBounds ("parent.right / 2 - 50, parent.bottom / 2 - 50, this.left + 100, this.top + 100"));
@code myComp.setBounds (RelativeBounds ("parent.width / 2 - 50, parent.height / 2 - 50, left + 100, top + 100"));
@endcode @endcode
..or an alternative way to achieve the same thing: ..or an alternative way to achieve the same thing:
@code myComp.setBounds (RelativeBounds ("this.right - 100, this.bottom - 100, parent.right / 2 + 50, parent.bottom / 2 + 50"));
@code myComp.setBounds (RelativeBounds ("right - 100, bottom - 100, parent.width / 2 + 50, parent.height / 2 + 50"));
@endcode @endcode
Or if you wanted a 100x100 component whose top edge is lined up to a marker called "topMarker" and Or if you wanted a 100x100 component whose top edge is lined up to a marker called "topMarker" and
which is positioned 50 pixels to the right of another component called "otherComp", you could write: which is positioned 50 pixels to the right of another component called "otherComp", you could write:
@code myComp.setBounds (RelativeBounds ("otherComp.right + 50, topMarker, this.left + 100, this.top + 100"));
@code myComp.setBounds (RelativeBounds ("otherComp.right + 50, topMarker, left + 100, top + 100"));
@endcode @endcode
Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will


+ 8
- 1
src/gui/components/juce_ModalComponentManager.cpp View File

@@ -65,6 +65,8 @@ public:
void componentBeingDeleted (Component& comp) void componentBeingDeleted (Component& comp)
{ {
ComponentMovementWatcher::componentBeingDeleted (comp);
if (component == &comp || comp.isParentOf (component)) if (component == &comp || comp.isParentOf (component))
cancel(); cancel();
} }
@@ -201,9 +203,14 @@ void ModalComponentManager::handleAsyncUpdate()
if (! item->isActive) if (! item->isActive)
{ {
for (int j = item->callbacks.size(); --j >= 0;) for (int j = item->callbacks.size(); --j >= 0;)
{
item->callbacks.getUnchecked(j)->modalStateFinished (item->returnValue); item->callbacks.getUnchecked(j)->modalStateFinished (item->returnValue);
stack.remove (i);
if (! stack.contains (item))
break;
}
stack.removeObject (item);
} }
} }
} }


+ 8
- 33
src/gui/components/positioning/juce_MarkerList.cpp View File

@@ -28,8 +28,10 @@
BEGIN_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE
#include "juce_MarkerList.h" #include "juce_MarkerList.h"
#include "juce_RelativeCoordinatePositioner.h"
#include "../juce_Component.h" #include "../juce_Component.h"
//============================================================================== //==============================================================================
MarkerList::MarkerList() MarkerList::MarkerList()
{ {
@@ -246,44 +248,17 @@ void MarkerList::ValueTreeWrapper::removeMarker (const ValueTree& marker, UndoMa
state.removeChild (marker, undoManager); state.removeChild (marker, undoManager);
} }
//==============================================================================
class MarkerListEvaluator : public Expression::EvaluationContext
double MarkerList::getMarkerPosition (const Marker& marker, Component* parentComponent) const
{ {
public:
MarkerListEvaluator (const MarkerList& markerList_, Component* const parentComponent_)
: markerList (markerList_), parentComponent (parentComponent_)
if (parentComponent != 0)
{ {
RelativeCoordinatePositionerBase::ComponentScope scope (*parentComponent);
return marker.position.resolve (&scope);
} }
const Expression getSymbolValue (const String& objectName, const String& member) const
else
{ {
if (member.isEmpty())
{
const MarkerList::Marker* const marker = markerList.getMarker (objectName);
if (marker != 0)
return Expression (marker->position.resolve (this));
}
else if (parentComponent != 0 && objectName == RelativeCoordinate::Strings::parent)
{
if (member == RelativeCoordinate::Strings::right) return Expression ((double) parentComponent->getWidth());
if (member == RelativeCoordinate::Strings::bottom) return Expression ((double) parentComponent->getHeight());
}
return Expression::EvaluationContext::getSymbolValue (objectName, member);
return marker.position.resolve (0);
} }
private:
const MarkerList& markerList;
Component* parentComponent;
JUCE_DECLARE_NON_COPYABLE (MarkerListEvaluator);
};
double MarkerList::getMarkerPosition (const Marker& marker, Component* const parentComponent) const
{
MarkerListEvaluator context (*this, parentComponent);
return marker.position.resolve (&context);
} }
//============================================================================== //==============================================================================


+ 29
- 35
src/gui/components/positioning/juce_RelativeCoordinate.cpp View File

@@ -32,15 +32,28 @@ BEGIN_JUCE_NAMESPACE
//============================================================================== //==============================================================================
const String RelativeCoordinate::Strings::parent ("parent"); const String RelativeCoordinate::Strings::parent ("parent");
const String RelativeCoordinate::Strings::this_ ("this");
const String RelativeCoordinate::Strings::left ("left"); const String RelativeCoordinate::Strings::left ("left");
const String RelativeCoordinate::Strings::right ("right"); const String RelativeCoordinate::Strings::right ("right");
const String RelativeCoordinate::Strings::top ("top"); const String RelativeCoordinate::Strings::top ("top");
const String RelativeCoordinate::Strings::bottom ("bottom"); const String RelativeCoordinate::Strings::bottom ("bottom");
const String RelativeCoordinate::Strings::parentLeft ("parent.left");
const String RelativeCoordinate::Strings::parentTop ("parent.top");
const String RelativeCoordinate::Strings::parentRight ("parent.right");
const String RelativeCoordinate::Strings::parentBottom ("parent.bottom");
const String RelativeCoordinate::Strings::x ("x");
const String RelativeCoordinate::Strings::y ("y");
const String RelativeCoordinate::Strings::width ("width");
const String RelativeCoordinate::Strings::height ("height");
RelativeCoordinate::StandardStrings::Type RelativeCoordinate::StandardStrings::getTypeOf (const String& s) throw()
{
if (s == Strings::left) return left;
if (s == Strings::right) return right;
if (s == Strings::top) return top;
if (s == Strings::bottom) return bottom;
if (s == Strings::x) return x;
if (s == Strings::y) return y;
if (s == Strings::width) return width;
if (s == Strings::height) return height;
if (s == Strings::parent) return parent;
return unknown;
}
//============================================================================== //==============================================================================
RelativeCoordinate::RelativeCoordinate() RelativeCoordinate::RelativeCoordinate()
@@ -92,12 +105,12 @@ bool RelativeCoordinate::operator!= (const RelativeCoordinate& other) const thro
return ! operator== (other); return ! operator== (other);
} }
double RelativeCoordinate::resolve (const Expression::EvaluationContext* context) const
double RelativeCoordinate::resolve (const Expression::Scope* scope) const
{ {
try try
{ {
if (context != 0)
return term.evaluate (*context);
if (scope != 0)
return term.evaluate (*scope);
else else
return term.evaluate(); return term.evaluate();
} }
@@ -107,12 +120,12 @@ double RelativeCoordinate::resolve (const Expression::EvaluationContext* context
return 0.0; return 0.0;
} }
bool RelativeCoordinate::isRecursive (const Expression::EvaluationContext* context) const
bool RelativeCoordinate::isRecursive (const Expression::Scope* scope) const
{ {
try try
{ {
if (context != 0)
term.evaluate (*context);
if (scope != 0)
term.evaluate (*scope);
else else
term.evaluate(); term.evaluate();
} }
@@ -124,36 +137,24 @@ bool RelativeCoordinate::isRecursive (const Expression::EvaluationContext* conte
return false; return false;
} }
void RelativeCoordinate::moveToAbsolute (double newPos, const Expression::EvaluationContext* context)
void RelativeCoordinate::moveToAbsolute (double newPos, const Expression::Scope* scope)
{ {
try try
{ {
if (context != 0)
if (scope != 0)
{ {
term = term.adjustedToGiveNewResult (newPos, *context);
term = term.adjustedToGiveNewResult (newPos, *scope);
} }
else else
{ {
Expression::EvaluationContext defaultContext;
term = term.adjustedToGiveNewResult (newPos, defaultContext);
Expression::Scope defaultScope;
term = term.adjustedToGiveNewResult (newPos, defaultScope);
} }
} }
catch (...) catch (...)
{} {}
} }
bool RelativeCoordinate::references (const String& coordName, const Expression::EvaluationContext* context) const
{
try
{
return term.referencesSymbol (coordName, context);
}
catch (...)
{}
return false;
}
bool RelativeCoordinate::isDynamic() const bool RelativeCoordinate::isDynamic() const
{ {
return term.usesAnySymbols(); return term.usesAnySymbols();
@@ -164,13 +165,6 @@ const String RelativeCoordinate::toString() const
return term.toString(); return term.toString();
} }
void RelativeCoordinate::renameSymbolIfUsed (const String& oldName, const String& newName)
{
jassert (newName.isNotEmpty() && newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_"));
if (term.referencesSymbol (oldName, 0))
term = term.withRenamedSymbol (oldName, newName);
}
END_JUCE_NAMESPACE END_JUCE_NAMESPACE

+ 22
- 13
src/gui/components/positioning/juce_RelativeCoordinate.h View File

@@ -69,18 +69,18 @@ public:
//============================================================================== //==============================================================================
/** Calculates the absolute position of this coordinate. /** Calculates the absolute position of this coordinate.
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
You'll need to provide a suitable Expression::Scope for looking up any coordinates that may
be needed to calculate the result. be needed to calculate the result.
*/ */
double resolve (const Expression::EvaluationContext* evaluationContext) const;
double resolve (const Expression::Scope* evaluationScope) const;
/** Returns true if this coordinate uses the specified coord name at any level in its evaluation. /** Returns true if this coordinate uses the specified coord name at any level in its evaluation.
This will recursively check any coordinates upon which this one depends. This will recursively check any coordinates upon which this one depends.
*/ */
bool references (const String& coordName, const Expression::EvaluationContext* evaluationContext) const;
bool references (const String& coordName, const Expression::Scope* evaluationScope) const;
/** Returns true if there's a recursive loop when trying to resolve this coordinate's position. */ /** Returns true if there's a recursive loop when trying to resolve this coordinate's position. */
bool isRecursive (const Expression::EvaluationContext* evaluationContext) const;
bool isRecursive (const Expression::Scope* evaluationScope) const;
/** Returns true if this coordinate depends on any other coordinates for its position. */ /** Returns true if this coordinate depends on any other coordinates for its position. */
bool isDynamic() const; bool isDynamic() const;
@@ -92,10 +92,7 @@ public:
or relative position to whatever value is necessary to make its resultant position or relative position to whatever value is necessary to make its resultant position
match the position that is provided. match the position that is provided.
*/ */
void moveToAbsolute (double absoluteTargetPosition, const Expression::EvaluationContext* evaluationContext);
/** Changes the name of a symbol if it is used as part of the coordinate's expression. */
void renameSymbolIfUsed (const String& oldName, const String& newName);
void moveToAbsolute (double absoluteTargetPosition, const Expression::Scope* evaluationScope);
/** Returns the expression that defines this coordinate. */ /** Returns the expression that defines this coordinate. */
const Expression& getExpression() const { return term; } const Expression& getExpression() const { return term; }
@@ -118,15 +115,27 @@ public:
struct Strings struct Strings
{ {
static const String parent; /**< "parent" */ static const String parent; /**< "parent" */
static const String this_; /**< "this" */
static const String left; /**< "left" */ static const String left; /**< "left" */
static const String right; /**< "right" */ static const String right; /**< "right" */
static const String top; /**< "top" */ static const String top; /**< "top" */
static const String bottom; /**< "bottom" */ static const String bottom; /**< "bottom" */
static const String parentLeft; /**< "parent.left" */
static const String parentTop; /**< "parent.top" */
static const String parentRight; /**< "parent.right" */
static const String parentBottom; /**< "parent.bottom" */
static const String x; /**< "x" */
static const String y; /**< "y" */
static const String width; /**< "width" */
static const String height; /**< "height" */
};
struct StandardStrings
{
enum Type
{
left, right, top, bottom,
x, y, width, height,
parent,
unknown
};
static Type getTypeOf (const String& s) throw();
}; };
private: private:


+ 152
- 152
src/gui/components/positioning/juce_RelativeCoordinatePositioner.cpp View File

@@ -31,51 +31,171 @@ BEGIN_JUCE_NAMESPACE
//============================================================================== //==============================================================================
RelativeCoordinatePositionerBase::RelativeCoordinatePositionerBase (Component& component_)
: Component::Positioner (component_), registeredOk (false)
RelativeCoordinatePositionerBase::ComponentScope::ComponentScope (Component& component_)
: component (component_)
{ {
} }
RelativeCoordinatePositionerBase::~RelativeCoordinatePositionerBase()
const Expression RelativeCoordinatePositionerBase::ComponentScope::getSymbolValue (const String& symbol) const
{ {
unregisterListeners();
switch (RelativeCoordinate::StandardStrings::getTypeOf (symbol))
{
case RelativeCoordinate::StandardStrings::x:
case RelativeCoordinate::StandardStrings::left: return Expression ((double) component.getX());
case RelativeCoordinate::StandardStrings::y:
case RelativeCoordinate::StandardStrings::top: return Expression ((double) component.getY());
case RelativeCoordinate::StandardStrings::width: return Expression ((double) component.getWidth());
case RelativeCoordinate::StandardStrings::height: return Expression ((double) component.getHeight());
case RelativeCoordinate::StandardStrings::right: return Expression ((double) component.getRight());
case RelativeCoordinate::StandardStrings::bottom: return Expression ((double) component.getBottom());
default: break;
}
MarkerList* list;
const MarkerList::Marker* const marker = findMarker (symbol, list);
if (marker != 0)
return marker->position.getExpression();
return Expression::Scope::getSymbolValue (symbol);
} }
const Expression RelativeCoordinatePositionerBase::getSymbolValue (const String& objectName, const String& member) const
void RelativeCoordinatePositionerBase::ComponentScope::visitRelativeScope (const String& scopeName, Visitor& visitor) const
{ {
jassert (objectName.isNotEmpty());
Component* targetComp = 0;
if (member.isNotEmpty())
if (scopeName == RelativeCoordinate::Strings::parent)
targetComp = component.getParentComponent();
else
targetComp = findSiblingComponent (scopeName);
if (targetComp != 0)
visitor.visit (ComponentScope (*targetComp));
}
const String RelativeCoordinatePositionerBase::ComponentScope::getScopeUID() const
{
return String::toHexString ((pointer_sized_int) (void*) &component);
}
Component* RelativeCoordinatePositionerBase::ComponentScope::findSiblingComponent (const String& componentID) const
{
Component* const parent = component.getParentComponent();
if (parent != 0)
{ {
const Component* comp = getSourceComponent (objectName);
for (int i = parent->getNumChildComponents(); --i >= 0;)
{
Component* const c = parent->getChildComponent(i);
if (c->getComponentID() == componentID)
return c;
}
}
return 0;
}
const MarkerList::Marker* RelativeCoordinatePositionerBase::ComponentScope::findMarker (const String& name, MarkerList*& list) const
{
const MarkerList::Marker* marker = 0;
Component* const parent = component.getParentComponent();
if (comp == 0)
if (parent != 0)
{
list = parent->getMarkers (true);
if (list != 0)
marker = list->getMarker (name);
if (marker == 0)
{ {
if (objectName == RelativeCoordinate::Strings::parent)
comp = getComponent().getParentComponent();
else if (objectName == RelativeCoordinate::Strings::this_ || objectName == getComponent().getComponentID())
comp = &getComponent();
list = parent->getMarkers (false);
if (list != 0)
marker = list->getMarker (name);
} }
}
return marker;
}
//==============================================================================
class RelativeCoordinatePositionerBase::DependencyFinderScope : public ComponentScope
{
public:
DependencyFinderScope (Component& component_, RelativeCoordinatePositionerBase& positioner_, bool& ok_)
: ComponentScope (component_), positioner (positioner_), ok (ok_)
{
}
if (comp != 0)
const Expression getSymbolValue (const String& symbol) const
{
if (symbol == RelativeCoordinate::Strings::left || symbol == RelativeCoordinate::Strings::x
|| symbol == RelativeCoordinate::Strings::width || symbol == RelativeCoordinate::Strings::right
|| symbol == RelativeCoordinate::Strings::top || symbol == RelativeCoordinate::Strings::y
|| symbol == RelativeCoordinate::Strings::height || symbol == RelativeCoordinate::Strings::bottom)
{ {
if (member == RelativeCoordinate::Strings::left) return xToExpression (comp, 0);
if (member == RelativeCoordinate::Strings::right) return xToExpression (comp, comp->getWidth());
if (member == RelativeCoordinate::Strings::top) return yToExpression (comp, 0);
if (member == RelativeCoordinate::Strings::bottom) return yToExpression (comp, comp->getHeight());
positioner.registerComponentListener (component);
} }
else
{
MarkerList* list;
const MarkerList::Marker* const marker = findMarker (symbol, list);
if (marker != 0)
{
positioner.registerMarkerListListener (list);
}
else
{
// The marker we want doesn't exist, so watch all lists in case they change and the marker appears later..
positioner.registerMarkerListListener (component.getMarkers (true));
positioner.registerMarkerListListener (component.getMarkers (false));
ok = false;
}
}
return ComponentScope::getSymbolValue (symbol);
} }
for (int i = sourceMarkerLists.size(); --i >= 0;)
void visitRelativeScope (const String& scopeName, Visitor& visitor) const
{ {
MarkerList* const markerList = sourceMarkerLists.getUnchecked(i);
const MarkerList::Marker* const marker = markerList->getMarker (objectName);
Component* targetComp = 0;
if (marker != 0)
return Expression (markerList->getMarkerPosition (*marker, getComponent().getParentComponent()));
if (scopeName == RelativeCoordinate::Strings::parent)
targetComp = component.getParentComponent();
else
targetComp = findSiblingComponent (scopeName);
if (targetComp != 0)
{
visitor.visit (DependencyFinderScope (*targetComp, positioner, ok));
}
else
{
// The named component doesn't exist, so we'll watch the parent for changes in case it appears later..
positioner.registerComponentListener (component);
ok = false;
}
} }
return Expression::EvaluationContext::getSymbolValue (objectName, member);
private:
RelativeCoordinatePositionerBase& positioner;
bool& ok;
JUCE_DECLARE_NON_COPYABLE (DependencyFinderScope);
};
//==============================================================================
RelativeCoordinatePositionerBase::RelativeCoordinatePositionerBase (Component& component_)
: Component::Positioner (component_), registeredOk (false)
{
}
RelativeCoordinatePositionerBase::~RelativeCoordinatePositionerBase()
{
unregisterListeners();
} }
void RelativeCoordinatePositionerBase::componentMovedOrResized (Component&, bool /*wasMoved*/, bool /*wasResized*/) void RelativeCoordinatePositionerBase::componentMovedOrResized (Component&, bool /*wasMoved*/, bool /*wasResized*/)
@@ -118,7 +238,10 @@ void RelativeCoordinatePositionerBase::apply()
bool RelativeCoordinatePositionerBase::addCoordinate (const RelativeCoordinate& coord) bool RelativeCoordinatePositionerBase::addCoordinate (const RelativeCoordinate& coord)
{ {
return registerListeners (coord.getExpression());
bool ok = true;
DependencyFinderScope finderScope (getComponent(), *this, ok);
coord.getExpression().evaluate (finderScope);
return ok;
} }
bool RelativeCoordinatePositionerBase::addPoint (const RelativePoint& point) bool RelativeCoordinatePositionerBase::addPoint (const RelativePoint& point)
@@ -127,95 +250,12 @@ bool RelativeCoordinatePositionerBase::addPoint (const RelativePoint& point)
return addCoordinate (point.y) && ok; return addCoordinate (point.y) && ok;
} }
bool RelativeCoordinatePositionerBase::registerListeners (const Expression& e)
{
bool ok = true;
if (e.getType() == Expression::symbolType)
{
String objectName, memberName;
e.getSymbolParts (objectName, memberName);
if (memberName.isNotEmpty())
ok = registerComponent (objectName) && ok;
else
ok = registerMarker (objectName) && ok;
}
else
{
for (int i = e.getNumInputs(); --i >= 0;)
ok = registerListeners (e.getInput (i)) && ok;
}
return ok;
}
bool RelativeCoordinatePositionerBase::registerComponent (const String& componentID)
void RelativeCoordinatePositionerBase::registerComponentListener (Component& comp)
{ {
Component* comp = findComponent (componentID);
if (comp == 0)
if (! sourceComponents.contains (&comp))
{ {
if (componentID == RelativeCoordinate::Strings::parent)
comp = getComponent().getParentComponent();
else if (componentID == RelativeCoordinate::Strings::this_ || componentID == getComponent().getComponentID())
comp = &getComponent();
}
if (comp != 0)
{
if (comp != &getComponent())
registerComponentListener (comp);
return true;
}
else
{
// The component we want doesn't exist, so watch the parent in case the hierarchy changes and it appears later..
Component* const parent = getComponent().getParentComponent();
if (parent != 0)
registerComponentListener (parent);
else
registerComponentListener (&getComponent());
return false;
}
}
bool RelativeCoordinatePositionerBase::registerMarker (const String markerName)
{
Component* const parent = getComponent().getParentComponent();
if (parent != 0)
{
MarkerList* list = parent->getMarkers (true);
if (list == 0 || list->getMarker (markerName) == 0)
list = parent->getMarkers (false);
if (list != 0 && list->getMarker (markerName) != 0)
{
registerMarkerListListener (list);
return true;
}
else
{
// The marker we want doesn't exist, so watch all lists in case they change and the marker appears later..
registerMarkerListListener (parent->getMarkers (true));
registerMarkerListListener (parent->getMarkers (false));
}
}
return false;
}
void RelativeCoordinatePositionerBase::registerComponentListener (Component* const comp)
{
if (comp != 0 && ! sourceComponents.contains (comp))
{
comp->addComponentListener (this);
sourceComponents.add (comp);
comp.addComponentListener (this);
sourceComponents.add (&comp);
} }
} }
@@ -241,45 +281,5 @@ void RelativeCoordinatePositionerBase::unregisterListeners()
sourceMarkerLists.clear(); sourceMarkerLists.clear();
} }
Component* RelativeCoordinatePositionerBase::findComponent (const String& componentID) const
{
Component* const parent = getComponent().getParentComponent();
if (parent != 0)
{
for (int i = parent->getNumChildComponents(); --i >= 0;)
{
Component* const c = parent->getChildComponent(i);
if (c->getComponentID() == componentID)
return c;
}
}
return 0;
}
Component* RelativeCoordinatePositionerBase::getSourceComponent (const String& objectName) const
{
for (int i = sourceComponents.size(); --i >= 0;)
{
Component* const comp = sourceComponents.getUnchecked(i);
if (comp->getComponentID() == objectName)
return comp;
}
return 0;
}
const Expression RelativeCoordinatePositionerBase::xToExpression (const Component* const source, const int x) const
{
return Expression ((double) (getComponent().getLocalPoint (source, Point<int> (x, 0)).getX() + getComponent().getX()));
}
const Expression RelativeCoordinatePositionerBase::yToExpression (const Component* const source, const int y) const
{
return Expression ((double) (getComponent().getLocalPoint (source, Point<int> (0, y)).getY() + getComponent().getY()));
}
END_JUCE_NAMESPACE END_JUCE_NAMESPACE

+ 25
- 12
src/gui/components/positioning/juce_RelativeCoordinatePositioner.h View File

@@ -37,15 +37,12 @@
*/ */
class JUCE_API RelativeCoordinatePositionerBase : public Component::Positioner, class JUCE_API RelativeCoordinatePositionerBase : public Component::Positioner,
public ComponentListener, public ComponentListener,
public MarkerList::Listener,
public Expression::EvaluationContext
public MarkerList::Listener
{ {
public: public:
RelativeCoordinatePositionerBase (Component& component_); RelativeCoordinatePositionerBase (Component& component_);
~RelativeCoordinatePositionerBase(); ~RelativeCoordinatePositionerBase();
const Expression getSymbolValue (const String& objectName, const String& member) const;
void componentMovedOrResized (Component&, bool, bool); void componentMovedOrResized (Component&, bool, bool);
void componentParentHierarchyChanged (Component&); void componentParentHierarchyChanged (Component&);
void componentBeingDeleted (Component& component); void componentBeingDeleted (Component& component);
@@ -57,25 +54,41 @@ public:
bool addCoordinate (const RelativeCoordinate& coord); bool addCoordinate (const RelativeCoordinate& coord);
bool addPoint (const RelativePoint& point); bool addPoint (const RelativePoint& point);
//==============================================================================
/** Used for resolving a RelativeCoordinate expression in the context of a component. */
class ComponentScope : public Expression::Scope
{
public:
ComponentScope (Component& component_);
const Expression getSymbolValue (const String& symbol) const;
void visitRelativeScope (const String& scopeName, Visitor& visitor) const;
const String getScopeUID() const;
protected:
Component& component;
Component* findSiblingComponent (const String& componentID) const;
const MarkerList::Marker* findMarker (const String& name, MarkerList*& list) const;
private:
JUCE_DECLARE_NON_COPYABLE (ComponentScope);
};
protected: protected:
virtual bool registerCoordinates() = 0; virtual bool registerCoordinates() = 0;
virtual void applyToComponentBounds() = 0; virtual void applyToComponentBounds() = 0;
private: private:
class DependencyFinderScope;
friend class DependencyFinderScope;
Array <Component*> sourceComponents; Array <Component*> sourceComponents;
Array <MarkerList*> sourceMarkerLists; Array <MarkerList*> sourceMarkerLists;
bool registeredOk; bool registeredOk;
bool registerListeners (const Expression& e);
bool registerComponent (const String& componentID);
bool registerMarker (const String markerName);
void registerComponentListener (Component* const comp);
void registerComponentListener (Component& comp);
void registerMarkerListListener (MarkerList* const list); void registerMarkerListListener (MarkerList* const list);
void unregisterListeners(); void unregisterListeners();
Component* findComponent (const String& componentID) const;
Component* getSourceComponent (const String& objectName) const;
const Expression xToExpression (const Component* const source, const int x) const;
const Expression yToExpression (const Component* const source, const int y) const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeCoordinatePositionerBase); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeCoordinatePositionerBase);
}; };


+ 14
- 14
src/gui/components/positioning/juce_RelativeParallelogram.cpp View File

@@ -53,30 +53,30 @@ RelativeParallelogram::~RelativeParallelogram()
{ {
} }
void RelativeParallelogram::resolveThreePoints (Point<float>* points, Expression::EvaluationContext* const coordFinder) const
void RelativeParallelogram::resolveThreePoints (Point<float>* points, Expression::Scope* const scope) const
{ {
points[0] = topLeft.resolve (coordFinder);
points[1] = topRight.resolve (coordFinder);
points[2] = bottomLeft.resolve (coordFinder);
points[0] = topLeft.resolve (scope);
points[1] = topRight.resolve (scope);
points[2] = bottomLeft.resolve (scope);
} }
void RelativeParallelogram::resolveFourCorners (Point<float>* points, Expression::EvaluationContext* const coordFinder) const
void RelativeParallelogram::resolveFourCorners (Point<float>* points, Expression::Scope* const scope) const
{ {
resolveThreePoints (points, coordFinder);
resolveThreePoints (points, scope);
points[3] = points[1] + (points[2] - points[0]); points[3] = points[1] + (points[2] - points[0]);
} }
const Rectangle<float> RelativeParallelogram::getBounds (Expression::EvaluationContext* const coordFinder) const
const Rectangle<float> RelativeParallelogram::getBounds (Expression::Scope* const scope) const
{ {
Point<float> points[4]; Point<float> points[4];
resolveFourCorners (points, coordFinder);
resolveFourCorners (points, scope);
return Rectangle<float>::findAreaContainingPoints (points, 4); return Rectangle<float>::findAreaContainingPoints (points, 4);
} }
void RelativeParallelogram::getPath (Path& path, Expression::EvaluationContext* const coordFinder) const
void RelativeParallelogram::getPath (Path& path, Expression::Scope* const scope) const
{ {
Point<float> points[4]; Point<float> points[4];
resolveFourCorners (points, coordFinder);
resolveFourCorners (points, scope);
path.startNewSubPath (points[0]); path.startNewSubPath (points[0]);
path.lineTo (points[1]); path.lineTo (points[1]);
@@ -85,18 +85,18 @@ void RelativeParallelogram::getPath (Path& path, Expression::EvaluationContext*
path.closeSubPath(); path.closeSubPath();
} }
const AffineTransform RelativeParallelogram::resetToPerpendicular (Expression::EvaluationContext* const coordFinder)
const AffineTransform RelativeParallelogram::resetToPerpendicular (Expression::Scope* const scope)
{ {
Point<float> corners[3]; Point<float> corners[3];
resolveThreePoints (corners, coordFinder);
resolveThreePoints (corners, scope);
const Line<float> top (corners[0], corners[1]); const Line<float> top (corners[0], corners[1]);
const Line<float> left (corners[0], corners[2]); const Line<float> left (corners[0], corners[2]);
const Point<float> newTopRight (corners[0] + Point<float> (top.getLength(), 0.0f)); const Point<float> newTopRight (corners[0] + Point<float> (top.getLength(), 0.0f));
const Point<float> newBottomLeft (corners[0] + Point<float> (0.0f, left.getLength())); const Point<float> newBottomLeft (corners[0] + Point<float> (0.0f, left.getLength()));
topRight.moveToAbsolute (newTopRight, coordFinder);
bottomLeft.moveToAbsolute (newBottomLeft, coordFinder);
topRight.moveToAbsolute (newTopRight, scope);
bottomLeft.moveToAbsolute (newBottomLeft, scope);
return AffineTransform::fromTargetPoints (corners[0].getX(), corners[0].getY(), corners[0].getX(), corners[0].getY(), return AffineTransform::fromTargetPoints (corners[0].getX(), corners[0].getY(), corners[0].getX(), corners[0].getY(),
corners[1].getX(), corners[1].getY(), newTopRight.getX(), newTopRight.getY(), corners[1].getX(), corners[1].getY(), newTopRight.getX(), newTopRight.getY(),


+ 5
- 5
src/gui/components/positioning/juce_RelativeParallelogram.h View File

@@ -46,11 +46,11 @@ public:
~RelativeParallelogram(); ~RelativeParallelogram();
//============================================================================== //==============================================================================
void resolveThreePoints (Point<float>* points, Expression::EvaluationContext* coordFinder) const;
void resolveFourCorners (Point<float>* points, Expression::EvaluationContext* coordFinder) const;
const Rectangle<float> getBounds (Expression::EvaluationContext* coordFinder) const;
void getPath (Path& path, Expression::EvaluationContext* coordFinder) const;
const AffineTransform resetToPerpendicular (Expression::EvaluationContext* coordFinder);
void resolveThreePoints (Point<float>* points, Expression::Scope* scope) const;
void resolveFourCorners (Point<float>* points, Expression::Scope* scope) const;
const Rectangle<float> getBounds (Expression::Scope* scope) const;
void getPath (Path& path, Expression::Scope* scope) const;
const AffineTransform resetToPerpendicular (Expression::Scope* scope);
bool isDynamic() const; bool isDynamic() const;
bool operator== (const RelativeParallelogram& other) const throw(); bool operator== (const RelativeParallelogram& other) const throw();


+ 6
- 12
src/gui/components/positioning/juce_RelativePoint.cpp View File

@@ -79,16 +79,16 @@ bool RelativePoint::operator!= (const RelativePoint& other) const throw()
return ! operator== (other); return ! operator== (other);
} }
const Point<float> RelativePoint::resolve (const Expression::EvaluationContext* context) const
const Point<float> RelativePoint::resolve (const Expression::Scope* scope) const
{ {
return Point<float> ((float) x.resolve (context),
(float) y.resolve (context));
return Point<float> ((float) x.resolve (scope),
(float) y.resolve (scope));
} }
void RelativePoint::moveToAbsolute (const Point<float>& newPos, const Expression::EvaluationContext* context)
void RelativePoint::moveToAbsolute (const Point<float>& newPos, const Expression::Scope* scope)
{ {
x.moveToAbsolute (newPos.getX(), context);
y.moveToAbsolute (newPos.getY(), context);
x.moveToAbsolute (newPos.getX(), scope);
y.moveToAbsolute (newPos.getY(), scope);
} }
const String RelativePoint::toString() const const String RelativePoint::toString() const
@@ -96,12 +96,6 @@ const String RelativePoint::toString() const
return x.toString() + ", " + y.toString(); return x.toString() + ", " + y.toString();
} }
void RelativePoint::renameSymbolIfUsed (const String& oldName, const String& newName)
{
x.renameSymbolIfUsed (oldName, newName);
y.renameSymbolIfUsed (oldName, newName);
}
bool RelativePoint::isDynamic() const bool RelativePoint::isDynamic() const
{ {
return x.isDynamic() || y.isDynamic(); return x.isDynamic() || y.isDynamic();


+ 3
- 8
src/gui/components/positioning/juce_RelativePoint.h View File

@@ -62,10 +62,10 @@ public:
/** Calculates the absolute position of this point. /** Calculates the absolute position of this point.
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
You'll need to provide a suitable Expression::Scope for looking up any coordinates that may
be needed to calculate the result. be needed to calculate the result.
*/ */
const Point<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
const Point<float> resolve (const Expression::Scope* evaluationContext) const;
/** Changes the values of this point's coordinates to make it resolve to the specified position. /** Changes the values of this point's coordinates to make it resolve to the specified position.
@@ -73,7 +73,7 @@ public:
or relative positions to whatever values are necessary to make the resultant position or relative positions to whatever values are necessary to make the resultant position
match the position that is provided. match the position that is provided.
*/ */
void moveToAbsolute (const Point<float>& newPos, const Expression::EvaluationContext* evaluationContext);
void moveToAbsolute (const Point<float>& newPos, const Expression::Scope* evaluationContext);
/** Returns a string which represents this point. /** Returns a string which represents this point.
This returns a comma-separated pair of coordinates. For details of the string syntax used by the This returns a comma-separated pair of coordinates. For details of the string syntax used by the
@@ -82,11 +82,6 @@ public:
*/ */
const String toString() const; const String toString() const;
/** Renames a symbol if it is used by any of the coordinates.
This calls RelativeCoordinate::renameAnchorIfUsed() on its X and Y coordinates.
*/
void renameSymbolIfUsed (const String& oldName, const String& newName);
/** Returns true if this point depends on any other coordinates for its position. */ /** Returns true if this point depends on any other coordinates for its position. */
bool isDynamic() const; bool isDynamic() const;


+ 14
- 14
src/gui/components/positioning/juce_RelativePointPath.cpp View File

@@ -109,10 +109,10 @@ void RelativePointPath::swapWith (RelativePointPath& other) throw()
swapVariables (containsDynamicPoints, other.containsDynamicPoints); swapVariables (containsDynamicPoints, other.containsDynamicPoints);
} }
void RelativePointPath::createPath (Path& path, Expression::EvaluationContext* coordFinder) const
void RelativePointPath::createPath (Path& path, Expression::Scope* scope) const
{ {
for (int i = 0; i < elements.size(); ++i) for (int i = 0; i < elements.size(); ++i)
elements.getUnchecked(i)->addToPath (path, coordFinder);
elements.getUnchecked(i)->addToPath (path, scope);
} }
bool RelativePointPath::containsAnyDynamicPoints() const bool RelativePointPath::containsAnyDynamicPoints() const
@@ -159,9 +159,9 @@ const ValueTree RelativePointPath::StartSubPath::createTree() const
return v; return v;
} }
void RelativePointPath::StartSubPath::addToPath (Path& path, Expression::EvaluationContext* coordFinder) const
void RelativePointPath::StartSubPath::addToPath (Path& path, Expression::Scope* scope) const
{ {
path.startNewSubPath (startPos.resolve (coordFinder));
path.startNewSubPath (startPos.resolve (scope));
} }
RelativePoint* RelativePointPath::StartSubPath::getControlPoints (int& numPoints) RelativePoint* RelativePointPath::StartSubPath::getControlPoints (int& numPoints)
@@ -186,7 +186,7 @@ const ValueTree RelativePointPath::CloseSubPath::createTree() const
return ValueTree (DrawablePath::ValueTreeWrapper::Element::closeSubPathElement); return ValueTree (DrawablePath::ValueTreeWrapper::Element::closeSubPathElement);
} }
void RelativePointPath::CloseSubPath::addToPath (Path& path, Expression::EvaluationContext*) const
void RelativePointPath::CloseSubPath::addToPath (Path& path, Expression::Scope*) const
{ {
path.closeSubPath(); path.closeSubPath();
} }
@@ -215,9 +215,9 @@ const ValueTree RelativePointPath::LineTo::createTree() const
return v; return v;
} }
void RelativePointPath::LineTo::addToPath (Path& path, Expression::EvaluationContext* coordFinder) const
void RelativePointPath::LineTo::addToPath (Path& path, Expression::Scope* scope) const
{ {
path.lineTo (endPoint.resolve (coordFinder));
path.lineTo (endPoint.resolve (scope));
} }
RelativePoint* RelativePointPath::LineTo::getControlPoints (int& numPoints) RelativePoint* RelativePointPath::LineTo::getControlPoints (int& numPoints)
@@ -247,10 +247,10 @@ const ValueTree RelativePointPath::QuadraticTo::createTree() const
return v; return v;
} }
void RelativePointPath::QuadraticTo::addToPath (Path& path, Expression::EvaluationContext* coordFinder) const
void RelativePointPath::QuadraticTo::addToPath (Path& path, Expression::Scope* scope) const
{ {
path.quadraticTo (controlPoints[0].resolve (coordFinder),
controlPoints[1].resolve (coordFinder));
path.quadraticTo (controlPoints[0].resolve (scope),
controlPoints[1].resolve (scope));
} }
RelativePoint* RelativePointPath::QuadraticTo::getControlPoints (int& numPoints) RelativePoint* RelativePointPath::QuadraticTo::getControlPoints (int& numPoints)
@@ -283,11 +283,11 @@ const ValueTree RelativePointPath::CubicTo::createTree() const
return v; return v;
} }
void RelativePointPath::CubicTo::addToPath (Path& path, Expression::EvaluationContext* coordFinder) const
void RelativePointPath::CubicTo::addToPath (Path& path, Expression::Scope* scope) const
{ {
path.cubicTo (controlPoints[0].resolve (coordFinder),
controlPoints[1].resolve (coordFinder),
controlPoints[2].resolve (coordFinder));
path.cubicTo (controlPoints[0].resolve (scope),
controlPoints[1].resolve (scope),
controlPoints[2].resolve (scope));
} }
RelativePoint* RelativePointPath::CubicTo::getControlPoints (int& numPoints) RelativePoint* RelativePointPath::CubicTo::getControlPoints (int& numPoints)


+ 7
- 7
src/gui/components/positioning/juce_RelativePointPath.h View File

@@ -54,7 +54,7 @@ public:
//============================================================================== //==============================================================================
/** Resolves this points in this path and adds them to a normal Path object. */ /** Resolves this points in this path and adds them to a normal Path object. */
void createPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void createPath (Path& path, Expression::Scope* scope) const;
/** Returns true if the path contains any non-fixed points. */ /** Returns true if the path contains any non-fixed points. */
bool containsAnyDynamicPoints() const; bool containsAnyDynamicPoints() const;
@@ -85,7 +85,7 @@ public:
ElementBase (ElementType type); ElementBase (ElementType type);
virtual ~ElementBase() {} virtual ~ElementBase() {}
virtual const ValueTree createTree() const = 0; virtual const ValueTree createTree() const = 0;
virtual void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const = 0;
virtual void addToPath (Path& path, Expression::Scope*) const = 0;
virtual RelativePoint* getControlPoints (int& numPoints) = 0; virtual RelativePoint* getControlPoints (int& numPoints) = 0;
virtual ElementBase* clone() const = 0; virtual ElementBase* clone() const = 0;
bool isDynamic(); bool isDynamic();
@@ -102,7 +102,7 @@ public:
public: public:
StartSubPath (const RelativePoint& pos); StartSubPath (const RelativePoint& pos);
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;
@@ -118,7 +118,7 @@ public:
public: public:
CloseSubPath(); CloseSubPath();
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;
@@ -132,7 +132,7 @@ public:
public: public:
LineTo (const RelativePoint& endPoint); LineTo (const RelativePoint& endPoint);
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;
@@ -148,7 +148,7 @@ public:
public: public:
QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint); QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint);
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;
@@ -164,7 +164,7 @@ public:
public: public:
CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint); CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint);
const ValueTree createTree() const; const ValueTree createTree() const;
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
void addToPath (Path& path, Expression::Scope*) const;
RelativePoint* getControlPoints (int& numPoints); RelativePoint* getControlPoints (int& numPoints);
ElementBase* clone() const; ElementBase* clone() const;


+ 75
- 54
src/gui/components/positioning/juce_RelativeRectangle.cpp View File

@@ -30,6 +30,8 @@ BEGIN_JUCE_NAMESPACE
#include "juce_RelativeRectangle.h" #include "juce_RelativeRectangle.h"
#include "juce_RelativeCoordinatePositioner.h" #include "juce_RelativeCoordinatePositioner.h"
//==============================================================================
namespace RelativeRectangleHelpers namespace RelativeRectangleHelpers
{ {
inline void skipComma (const juce_wchar* const s, int& i) inline void skipComma (const juce_wchar* const s, int& i)
@@ -43,13 +45,23 @@ namespace RelativeRectangleHelpers
bool dependsOnSymbolsOtherThanThis (const Expression& e) bool dependsOnSymbolsOtherThanThis (const Expression& e)
{ {
if (e.getType() == Expression::operatorType && e.getSymbolOrFunction() == ".")
return true;
if (e.getType() == Expression::symbolType) if (e.getType() == Expression::symbolType)
{ {
String objectName, memberName;
e.getSymbolParts (objectName, memberName);
if (objectName != RelativeCoordinate::Strings::this_)
return true;
switch (RelativeCoordinate::StandardStrings::getTypeOf (e.getSymbolOrFunction()))
{
case RelativeCoordinate::StandardStrings::x:
case RelativeCoordinate::StandardStrings::y:
case RelativeCoordinate::StandardStrings::left:
case RelativeCoordinate::StandardStrings::right:
case RelativeCoordinate::StandardStrings::top:
case RelativeCoordinate::StandardStrings::bottom: return false;
default: break;
}
return true;
} }
else else
{ {
@@ -75,11 +87,9 @@ RelativeRectangle::RelativeRectangle (const RelativeCoordinate& left_, const Rel
RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect) RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect)
: left (rect.getX()), : left (rect.getX()),
right (Expression::symbol (RelativeCoordinate::Strings::this_ + "." + RelativeCoordinate::Strings::left)
+ Expression ((double) rect.getWidth())),
right (Expression::symbol (RelativeCoordinate::Strings::left) + Expression ((double) rect.getWidth())),
top (rect.getY()), top (rect.getY()),
bottom (Expression::symbol (RelativeCoordinate::Strings::this_ + "." + RelativeCoordinate::Strings::top)
+ Expression ((double) rect.getHeight()))
bottom (Expression::symbol (RelativeCoordinate::Strings::top) + Expression ((double) rect.getHeight()))
{ {
} }
@@ -105,22 +115,59 @@ bool RelativeRectangle::operator!= (const RelativeRectangle& other) const throw(
return ! operator== (other); return ! operator== (other);
} }
const Rectangle<float> RelativeRectangle::resolve (const Expression::EvaluationContext* context) const
//==============================================================================
// An expression context that can evaluate expressions using "this"
class RelativeRectangleLocalScope : public Expression::Scope
{ {
const double l = left.resolve (context);
const double r = right.resolve (context);
const double t = top.resolve (context);
const double b = bottom.resolve (context);
public:
RelativeRectangleLocalScope (const RelativeRectangle& rect_) : rect (rect_) {}
const Expression getSymbolValue (const String& symbol) const
{
switch (RelativeCoordinate::StandardStrings::getTypeOf (symbol))
{
case RelativeCoordinate::StandardStrings::x:
case RelativeCoordinate::StandardStrings::left: return rect.left.getExpression();
case RelativeCoordinate::StandardStrings::y:
case RelativeCoordinate::StandardStrings::top: return rect.top.getExpression();
case RelativeCoordinate::StandardStrings::right: return rect.right.getExpression();
case RelativeCoordinate::StandardStrings::bottom: return rect.bottom.getExpression();
default: break;
}
return Rectangle<float> ((float) l, (float) t, (float) jmax (0.0, r - l), (float) jmax (0.0, b - t));
return Expression::Scope::getSymbolValue (symbol);
}
private:
const RelativeRectangle& rect;
JUCE_DECLARE_NON_COPYABLE (RelativeRectangleLocalScope);
};
const Rectangle<float> RelativeRectangle::resolve (const Expression::Scope* scope) const
{
if (scope == 0)
{
RelativeRectangleLocalScope scope (*this);
return resolve (&scope);
}
else
{
const double l = left.resolve (scope);
const double r = right.resolve (scope);
const double t = top.resolve (scope);
const double b = bottom.resolve (scope);
return Rectangle<float> ((float) l, (float) t, (float) jmax (0.0, r - l), (float) jmax (0.0, b - t));
}
} }
void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const Expression::EvaluationContext* context)
void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const Expression::Scope* scope)
{ {
left.moveToAbsolute (newPos.getX(), context);
right.moveToAbsolute (newPos.getRight(), context);
top.moveToAbsolute (newPos.getY(), context);
bottom.moveToAbsolute (newPos.getBottom(), context);
left.moveToAbsolute (newPos.getX(), scope);
right.moveToAbsolute (newPos.getRight(), scope);
top.moveToAbsolute (newPos.getY(), scope);
bottom.moveToAbsolute (newPos.getBottom(), scope);
} }
bool RelativeRectangle::isDynamic() const bool RelativeRectangle::isDynamic() const
@@ -138,12 +185,12 @@ const String RelativeRectangle::toString() const
return left.toString() + ", " + top.toString() + ", " + right.toString() + ", " + bottom.toString(); return left.toString() + ", " + top.toString() + ", " + right.toString() + ", " + bottom.toString();
} }
void RelativeRectangle::renameSymbolIfUsed (const String& oldName, const String& newName)
void RelativeRectangle::renameSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Expression::Scope& scope)
{ {
left.renameSymbolIfUsed (oldName, newName);
right.renameSymbolIfUsed (oldName, newName);
top.renameSymbolIfUsed (oldName, newName);
bottom.renameSymbolIfUsed (oldName, newName);
left = left.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
right = right.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
top = top.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
bottom = bottom.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
} }
//============================================================================== //==============================================================================
@@ -174,7 +221,8 @@ public:
{ {
for (int i = 4; --i >= 0;) for (int i = 4; --i >= 0;)
{ {
const Rectangle<int> newBounds (rectangle.resolve (this).getSmallestIntegerContainer());
ComponentScope scope (getComponent());
const Rectangle<int> newBounds (rectangle.resolve (&scope).getSmallestIntegerContainer());
if (newBounds == getComponent().getBounds()) if (newBounds == getComponent().getBounds())
return; return;
@@ -191,31 +239,6 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeRectangleComponentPositioner); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeRectangleComponentPositioner);
}; };
// An expression context that can evaluate expressions using "this"
class TemporaryRectangleContext : public Expression::EvaluationContext
{
public:
TemporaryRectangleContext (const RelativeRectangle& rect_) : rect (rect_) {}
const Expression getSymbolValue (const String& objectName, const String& edge) const
{
if (objectName == RelativeCoordinate::Strings::this_)
{
if (edge == RelativeCoordinate::Strings::left) return rect.left.getExpression();
if (edge == RelativeCoordinate::Strings::right) return rect.right.getExpression();
if (edge == RelativeCoordinate::Strings::top) return rect.top.getExpression();
if (edge == RelativeCoordinate::Strings::bottom) return rect.bottom.getExpression();
}
return Expression::EvaluationContext::getSymbolValue (objectName, edge);
}
private:
const RelativeRectangle& rect;
JUCE_DECLARE_NON_COPYABLE (TemporaryRectangleContext);
};
void RelativeRectangle::applyToComponent (Component& component) const void RelativeRectangle::applyToComponent (Component& component) const
{ {
if (isDynamic()) if (isDynamic())
@@ -233,9 +256,7 @@ void RelativeRectangle::applyToComponent (Component& component) const
else else
{ {
component.setPositioner (0); component.setPositioner (0);
TemporaryRectangleContext context (*this);
component.setBounds (resolve (&context).getSmallestIntegerContainer());
component.setBounds (resolve (0).getSmallestIntegerContainer());
} }
} }


+ 5
- 5
src/gui/components/positioning/juce_RelativeRectangle.h View File

@@ -65,10 +65,10 @@ public:
//============================================================================== //==============================================================================
/** Calculates the absolute position of this rectangle. /** Calculates the absolute position of this rectangle.
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
You'll need to provide a suitable Expression::Scope for looking up any coordinates that may
be needed to calculate the result. be needed to calculate the result.
*/ */
const Rectangle<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
const Rectangle<float> resolve (const Expression::Scope* scope) const;
/** Changes the values of this rectangle's coordinates to make it resolve to the specified position. /** Changes the values of this rectangle's coordinates to make it resolve to the specified position.
@@ -76,7 +76,7 @@ public:
or relative positions to whatever values are necessary to make the resultant position or relative positions to whatever values are necessary to make the resultant position
match the position that is provided. match the position that is provided.
*/ */
void moveToAbsolute (const Rectangle<float>& newPos, const Expression::EvaluationContext* evaluationContext);
void moveToAbsolute (const Rectangle<float>& newPos, const Expression::Scope* scope);
/** Returns true if this rectangle depends on any external symbols for its position. /** Returns true if this rectangle depends on any external symbols for its position.
Coordinates that refer to symbols based on "this" are assumed not to be dynamic. Coordinates that refer to symbols based on "this" are assumed not to be dynamic.
@@ -91,9 +91,9 @@ public:
const String toString() const; const String toString() const;
/** Renames a symbol if it is used by any of the coordinates. /** Renames a symbol if it is used by any of the coordinates.
This calls RelativeCoordinate::renameSymbolIfUsed() on the rectangle's coordinates.
This calls Expression::withRenamedSymbol() on the rectangle's coordinates.
*/ */
void renameSymbolIfUsed (const String& oldName, const String& newName);
void renameSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Expression::Scope& scope);
/** Creates and sets an appropriate Component::Positioner object for the given component, which will /** Creates and sets an appropriate Component::Positioner object for the given component, which will
keep it positioned with this rectangle. keep it positioned with this rectangle.


+ 5
- 1
src/gui/graphics/drawables/juce_Drawable.h View File

@@ -228,7 +228,11 @@ protected:
{} {}
bool registerCoordinates() { return owner.registerCoordinates (*this); } bool registerCoordinates() { return owner.registerCoordinates (*this); }
void applyToComponentBounds() { owner.recalculateCoordinates (this); }
void applyToComponentBounds()
{
ComponentScope scope (getComponent());
owner.recalculateCoordinates (&scope);
}
private: private:
DrawableType& owner; DrawableType& owner;


+ 3
- 3
src/gui/graphics/drawables/juce_DrawableComposite.cpp View File

@@ -153,12 +153,12 @@ bool DrawableComposite::registerCoordinates (RelativeCoordinatePositionerBase& p
return positioner.addPoint (bounds.bottomLeft) && ok; return positioner.addPoint (bounds.bottomLeft) && ok;
} }
void DrawableComposite::recalculateCoordinates (Expression::EvaluationContext* context)
void DrawableComposite::recalculateCoordinates (Expression::Scope* scope)
{ {
Point<float> resolved[3]; Point<float> resolved[3];
bounds.resolveThreePoints (resolved, context);
bounds.resolveThreePoints (resolved, scope);
const Rectangle<float> content (getContentArea().resolve (context));
const Rectangle<float> content (getContentArea().resolve (scope));
AffineTransform t (AffineTransform::fromTargetPoints (content.getX(), content.getY(), resolved[0].getX(), resolved[0].getY(), AffineTransform t (AffineTransform::fromTargetPoints (content.getX(), content.getY(), resolved[0].getX(), resolved[0].getY(),
content.getRight(), content.getY(), resolved[1].getX(), resolved[1].getY(), content.getRight(), content.getY(), resolved[1].getX(), resolved[1].getY(),


+ 1
- 1
src/gui/graphics/drawables/juce_DrawableComposite.h View File

@@ -150,7 +150,7 @@ private:
friend class Drawable::Positioner<DrawableComposite>; friend class Drawable::Positioner<DrawableComposite>;
bool registerCoordinates (RelativeCoordinatePositionerBase&); bool registerCoordinates (RelativeCoordinatePositionerBase&);
void recalculateCoordinates (Expression::EvaluationContext*);
void recalculateCoordinates (Expression::Scope*);
void updateBoundsToFitChildren(); void updateBoundsToFitChildren();


+ 2
- 2
src/gui/graphics/drawables/juce_DrawableImage.cpp View File

@@ -106,12 +106,12 @@ bool DrawableImage::registerCoordinates (RelativeCoordinatePositionerBase& posit
return positioner.addPoint (bounds.bottomLeft) && ok; return positioner.addPoint (bounds.bottomLeft) && ok;
} }
void DrawableImage::recalculateCoordinates (Expression::EvaluationContext* context)
void DrawableImage::recalculateCoordinates (Expression::Scope* scope)
{ {
if (image.isValid()) if (image.isValid())
{ {
Point<float> resolved[3]; Point<float> resolved[3];
bounds.resolveThreePoints (resolved, context);
bounds.resolveThreePoints (resolved, scope);
const Point<float> tr (resolved[0] + (resolved[1] - resolved[0]) / (float) image.getWidth()); const Point<float> tr (resolved[0] + (resolved[1] - resolved[0]) / (float) image.getWidth());
const Point<float> bl (resolved[0] + (resolved[2] - resolved[0]) / (float) image.getHeight()); const Point<float> bl (resolved[0] + (resolved[2] - resolved[0]) / (float) image.getHeight());


+ 1
- 1
src/gui/graphics/drawables/juce_DrawableImage.h View File

@@ -133,7 +133,7 @@ private:
friend class Drawable::Positioner<DrawableImage>; friend class Drawable::Positioner<DrawableImage>;
bool registerCoordinates (RelativeCoordinatePositionerBase&); bool registerCoordinates (RelativeCoordinatePositionerBase&);
void recalculateCoordinates (Expression::EvaluationContext*);
void recalculateCoordinates (Expression::Scope*);
DrawableImage& operator= (const DrawableImage&); DrawableImage& operator= (const DrawableImage&);
JUCE_LEAK_DETECTOR (DrawableImage); JUCE_LEAK_DETECTOR (DrawableImage);


+ 24
- 22
src/gui/graphics/drawables/juce_DrawablePath.cpp View File

@@ -72,10 +72,10 @@ const Path& DrawablePath::getStrokePath() const
return strokePath; return strokePath;
} }
void DrawablePath::applyRelativePath (const RelativePointPath& newRelativePath, Expression::EvaluationContext* context)
void DrawablePath::applyRelativePath (const RelativePointPath& newRelativePath, Expression::Scope* scope)
{ {
Path newPath; Path newPath;
newRelativePath.createPath (newPath, context);
newRelativePath.createPath (newPath, scope);
if (path != newPath) if (path != newPath)
{ {
@@ -118,7 +118,9 @@ public:
void applyToComponentBounds() void applyToComponentBounds()
{ {
jassert (owner.relativePath != 0); jassert (owner.relativePath != 0);
owner.applyRelativePath (*owner.relativePath, this);
ComponentScope scope (getComponent());
owner.applyRelativePath (*owner.relativePath, &scope);
} }
private: private:
@@ -299,26 +301,26 @@ const RelativePoint DrawablePath::ValueTreeWrapper::Element::getEndPoint() const
return RelativePoint(); return RelativePoint();
} }
float DrawablePath::ValueTreeWrapper::Element::getLength (Expression::EvaluationContext* context) const
float DrawablePath::ValueTreeWrapper::Element::getLength (Expression::Scope* scope) const
{ {
const Identifier i (state.getType()); const Identifier i (state.getType());
if (i == lineToElement || i == closeSubPathElement) if (i == lineToElement || i == closeSubPathElement)
return getEndPoint().resolve (context).getDistanceFrom (getStartPoint().resolve (context));
return getEndPoint().resolve (scope).getDistanceFrom (getStartPoint().resolve (scope));
if (i == cubicToElement) if (i == cubicToElement)
{ {
Path p; Path p;
p.startNewSubPath (getStartPoint().resolve (context));
p.cubicTo (getControlPoint (0).resolve (context), getControlPoint (1).resolve (context), getControlPoint (2).resolve (context));
p.startNewSubPath (getStartPoint().resolve (scope));
p.cubicTo (getControlPoint (0).resolve (scope), getControlPoint (1).resolve (scope), getControlPoint (2).resolve (scope));
return p.getLength(); return p.getLength();
} }
if (i == quadraticToElement) if (i == quadraticToElement)
{ {
Path p; Path p;
p.startNewSubPath (getStartPoint().resolve (context));
p.quadraticTo (getControlPoint (0).resolve (context), getControlPoint (1).resolve (context));
p.startNewSubPath (getStartPoint().resolve (scope));
p.quadraticTo (getControlPoint (0).resolve (scope), getControlPoint (1).resolve (scope));
return p.getLength(); return p.getLength();
} }
@@ -350,7 +352,7 @@ void DrawablePath::ValueTreeWrapper::Element::convertToLine (UndoManager* undoMa
} }
} }
void DrawablePath::ValueTreeWrapper::Element::convertToCubic (Expression::EvaluationContext* context, UndoManager* undoManager)
void DrawablePath::ValueTreeWrapper::Element::convertToCubic (Expression::Scope* scope, UndoManager* undoManager)
{ {
const Identifier i (state.getType()); const Identifier i (state.getType());
@@ -361,8 +363,8 @@ void DrawablePath::ValueTreeWrapper::Element::convertToCubic (Expression::Evalua
const RelativePoint start (getStartPoint()); const RelativePoint start (getStartPoint());
const RelativePoint end (getEndPoint()); const RelativePoint end (getEndPoint());
const Point<float> startResolved (start.resolve (context));
const Point<float> endResolved (end.resolve (context));
const Point<float> startResolved (start.resolve (scope));
const Point<float> endResolved (end.resolve (scope));
e.setControlPoint (0, startResolved + (endResolved - startResolved) * 0.3f, undoManager); e.setControlPoint (0, startResolved + (endResolved - startResolved) * 0.3f, undoManager);
e.setControlPoint (1, startResolved + (endResolved - startResolved) * 0.7f, undoManager); e.setControlPoint (1, startResolved + (endResolved - startResolved) * 0.7f, undoManager);
e.setControlPoint (2, end, undoManager); e.setControlPoint (2, end, undoManager);
@@ -407,7 +409,7 @@ namespace DrawablePathHelpers
} }
} }
float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext* context) const
float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, Expression::Scope* scope) const
{ {
using namespace DrawablePathHelpers; using namespace DrawablePathHelpers;
const Identifier type (state.getType()); const Identifier type (state.getType());
@@ -417,7 +419,7 @@ float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Po
{ {
RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getControlPoint (1)), rp4 (getEndPoint()); RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getControlPoint (1)), rp4 (getEndPoint());
const Point<float> points[] = { rp1.resolve (context), rp2.resolve (context), rp3.resolve (context), rp4.resolve (context) };
const Point<float> points[] = { rp1.resolve (scope), rp2.resolve (scope), rp3.resolve (scope), rp4.resolve (scope) };
float bestDistance = std::numeric_limits<float>::max(); float bestDistance = std::numeric_limits<float>::max();
@@ -437,7 +439,7 @@ float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Po
else if (type == quadraticToElement) else if (type == quadraticToElement)
{ {
RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getEndPoint()); RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getEndPoint());
const Point<float> points[] = { rp1.resolve (context), rp2.resolve (context), rp3.resolve (context) };
const Point<float> points[] = { rp1.resolve (scope), rp2.resolve (scope), rp3.resolve (scope) };
float bestDistance = std::numeric_limits<float>::max(); float bestDistance = std::numeric_limits<float>::max();
@@ -457,24 +459,24 @@ float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Po
else if (type == lineToElement) else if (type == lineToElement)
{ {
RelativePoint rp1 (getStartPoint()), rp2 (getEndPoint()); RelativePoint rp1 (getStartPoint()), rp2 (getEndPoint());
const Line<float> line (rp1.resolve (context), rp2.resolve (context));
const Line<float> line (rp1.resolve (scope), rp2.resolve (scope));
bestProp = line.findNearestProportionalPositionTo (targetPoint); bestProp = line.findNearestProportionalPositionTo (targetPoint);
} }
return bestProp; return bestProp;
} }
ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext* context, UndoManager* undoManager)
ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<float>& targetPoint, Expression::Scope* scope, UndoManager* undoManager)
{ {
ValueTree newTree; ValueTree newTree;
const Identifier type (state.getType()); const Identifier type (state.getType());
if (type == cubicToElement) if (type == cubicToElement)
{ {
float bestProp = findProportionAlongLine (targetPoint, context);
float bestProp = findProportionAlongLine (targetPoint, scope);
RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getControlPoint (1)), rp4 (getEndPoint()); RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getControlPoint (1)), rp4 (getEndPoint());
const Point<float> points[] = { rp1.resolve (context), rp2.resolve (context), rp3.resolve (context), rp4.resolve (context) };
const Point<float> points[] = { rp1.resolve (scope), rp2.resolve (scope), rp3.resolve (scope), rp4.resolve (scope) };
const Point<float> mid1 (points[0] + (points[1] - points[0]) * bestProp), const Point<float> mid1 (points[0] + (points[1] - points[0]) * bestProp),
mid2 (points[1] + (points[2] - points[1]) * bestProp), mid2 (points[1] + (points[2] - points[1]) * bestProp),
@@ -499,10 +501,10 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa
} }
else if (type == quadraticToElement) else if (type == quadraticToElement)
{ {
float bestProp = findProportionAlongLine (targetPoint, context);
float bestProp = findProportionAlongLine (targetPoint, scope);
RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getEndPoint()); RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getEndPoint());
const Point<float> points[] = { rp1.resolve (context), rp2.resolve (context), rp3.resolve (context) };
const Point<float> points[] = { rp1.resolve (scope), rp2.resolve (scope), rp3.resolve (scope) };
const Point<float> mid1 (points[0] + (points[1] - points[0]) * bestProp), const Point<float> mid1 (points[0] + (points[1] - points[0]) * bestProp),
mid2 (points[1] + (points[2] - points[1]) * bestProp); mid2 (points[1] + (points[2] - points[1]) * bestProp);
@@ -522,7 +524,7 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa
else if (type == lineToElement) else if (type == lineToElement)
{ {
RelativePoint rp1 (getStartPoint()), rp2 (getEndPoint()); RelativePoint rp1 (getStartPoint()), rp2 (getEndPoint());
const Line<float> line (rp1.resolve (context), rp2.resolve (context));
const Line<float> line (rp1.resolve (scope), rp2.resolve (scope));
const Point<float> newPoint (line.findNearestPointTo (targetPoint)); const Point<float> newPoint (line.findNearestPointTo (targetPoint));
setControlPoint (0, newPoint, undoManager); setControlPoint (0, newPoint, undoManager);


+ 5
- 5
src/gui/graphics/drawables/juce_DrawablePath.h View File

@@ -101,7 +101,7 @@ public:
const RelativePoint getStartPoint() const; const RelativePoint getStartPoint() const;
const RelativePoint getEndPoint() const; const RelativePoint getEndPoint() const;
void setControlPoint (int index, const RelativePoint& point, UndoManager*); void setControlPoint (int index, const RelativePoint& point, UndoManager*);
float getLength (Expression::EvaluationContext*) const;
float getLength (Expression::Scope*) const;
ValueTreeWrapper getParent() const; ValueTreeWrapper getParent() const;
Element getPreviousElement() const; Element getPreviousElement() const;
@@ -110,11 +110,11 @@ public:
void setModeOfEndPoint (const String& newMode, UndoManager*); void setModeOfEndPoint (const String& newMode, UndoManager*);
void convertToLine (UndoManager*); void convertToLine (UndoManager*);
void convertToCubic (Expression::EvaluationContext*, UndoManager*);
void convertToCubic (Expression::Scope*, UndoManager*);
void convertToPathBreak (UndoManager* undoManager); void convertToPathBreak (UndoManager* undoManager);
ValueTree insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext*, UndoManager*);
ValueTree insertPoint (const Point<float>& targetPoint, Expression::Scope*, UndoManager*);
void removePoint (UndoManager* undoManager); void removePoint (UndoManager* undoManager);
float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext*) const;
float findProportionAlongLine (const Point<float>& targetPoint, Expression::Scope*) const;
static const Identifier mode, startSubPathElement, closeSubPathElement, static const Identifier mode, startSubPathElement, closeSubPathElement,
lineToElement, quadraticToElement, cubicToElement; lineToElement, quadraticToElement, cubicToElement;
@@ -139,7 +139,7 @@ private:
class RelativePositioner; class RelativePositioner;
friend class RelativePositioner; friend class RelativePositioner;
void applyRelativePath (const RelativePointPath&, Expression::EvaluationContext*);
void applyRelativePath (const RelativePointPath&, Expression::Scope*);
DrawablePath& operator= (const DrawablePath&); DrawablePath& operator= (const DrawablePath&);
JUCE_LEAK_DETECTOR (DrawablePath); JUCE_LEAK_DETECTOR (DrawablePath);


+ 4
- 4
src/gui/graphics/drawables/juce_DrawableRectangle.cpp View File

@@ -95,13 +95,13 @@ bool DrawableRectangle::registerCoordinates (RelativeCoordinatePositionerBase& p
return positioner.addPoint (cornerSize) && ok; return positioner.addPoint (cornerSize) && ok;
} }
void DrawableRectangle::recalculateCoordinates (Expression::EvaluationContext* context)
void DrawableRectangle::recalculateCoordinates (Expression::Scope* scope)
{ {
Point<float> points[3]; Point<float> points[3];
bounds.resolveThreePoints (points, context);
bounds.resolveThreePoints (points, scope);
const float cornerSizeX = (float) cornerSize.x.resolve (context);
const float cornerSizeY = (float) cornerSize.y.resolve (context);
const float cornerSizeX = (float) cornerSize.x.resolve (scope);
const float cornerSizeY = (float) cornerSize.y.resolve (scope);
const float w = Line<float> (points[0], points[1]).getLength(); const float w = Line<float> (points[0], points[1]).getLength();
const float h = Line<float> (points[0], points[2]).getLength(); const float h = Line<float> (points[0], points[2]).getLength();


+ 1
- 1
src/gui/graphics/drawables/juce_DrawableRectangle.h View File

@@ -97,7 +97,7 @@ private:
void rebuildPath(); void rebuildPath();
bool registerCoordinates (RelativeCoordinatePositionerBase&); bool registerCoordinates (RelativeCoordinatePositionerBase&);
void recalculateCoordinates (Expression::EvaluationContext*);
void recalculateCoordinates (Expression::Scope*);
DrawableRectangle& operator= (const DrawableRectangle&); DrawableRectangle& operator= (const DrawableRectangle&);
JUCE_LEAK_DETECTOR (DrawableRectangle); JUCE_LEAK_DETECTOR (DrawableRectangle);


+ 7
- 6
src/gui/graphics/drawables/juce_DrawableShape.cpp View File

@@ -71,8 +71,9 @@ public:
void applyToComponentBounds() void applyToComponentBounds()
{ {
if (isMainFill ? owner.mainFill.recalculateCoords (this)
: owner.strokeFill.recalculateCoords (this))
ComponentScope scope (owner);
if (isMainFill ? owner.mainFill.recalculateCoords (&scope)
: owner.strokeFill.recalculateCoords (&scope))
owner.repaint(); owner.repaint();
} }
@@ -256,19 +257,19 @@ bool DrawableShape::RelativeFillType::operator!= (const RelativeFillType& other)
return ! operator== (other); return ! operator== (other);
} }
bool DrawableShape::RelativeFillType::recalculateCoords (Expression::EvaluationContext* context)
bool DrawableShape::RelativeFillType::recalculateCoords (Expression::Scope* scope)
{ {
if (fill.isGradient()) if (fill.isGradient())
{ {
const Point<float> g1 (gradientPoint1.resolve (context));
const Point<float> g2 (gradientPoint2.resolve (context));
const Point<float> g1 (gradientPoint1.resolve (scope));
const Point<float> g2 (gradientPoint2.resolve (scope));
AffineTransform t; AffineTransform t;
ColourGradient& g = *fill.gradient; ColourGradient& g = *fill.gradient;
if (g.isRadial) if (g.isRadial)
{ {
const Point<float> g3 (gradientPoint3.resolve (context));
const Point<float> g3 (gradientPoint3.resolve (scope));
const Point<float> g3Source (g1.getX() + g2.getY() - g1.getY(), const Point<float> g3Source (g1.getX() + g2.getY() - g1.getY(),
g1.getY() + g1.getX() - g2.getX()); g1.getY() + g1.getX() - g2.getX());


+ 1
- 1
src/gui/graphics/drawables/juce_DrawableShape.h View File

@@ -65,7 +65,7 @@ public:
bool operator!= (const RelativeFillType&) const; bool operator!= (const RelativeFillType&) const;
bool isDynamic() const; bool isDynamic() const;
bool recalculateCoords (Expression::EvaluationContext* context);
bool recalculateCoords (Expression::Scope* scope);
void writeTo (ValueTree& v, ComponentBuilder::ImageProvider*, UndoManager*) const; void writeTo (ValueTree& v, ComponentBuilder::ImageProvider*, UndoManager*) const;
bool readFrom (const ValueTree& v, ComponentBuilder::ImageProvider*); bool readFrom (const ValueTree& v, ComponentBuilder::ImageProvider*);


+ 3
- 3
src/gui/graphics/drawables/juce_DrawableText.cpp View File

@@ -138,14 +138,14 @@ bool DrawableText::registerCoordinates (RelativeCoordinatePositionerBase& positi
return positioner.addPoint (fontSizeControlPoint) && ok; return positioner.addPoint (fontSizeControlPoint) && ok;
} }
void DrawableText::recalculateCoordinates (Expression::EvaluationContext* context)
void DrawableText::recalculateCoordinates (Expression::Scope* scope)
{ {
bounds.resolveThreePoints (resolvedPoints, context);
bounds.resolveThreePoints (resolvedPoints, scope);
const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength(); const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength(); const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
const Point<float> fontCoords (RelativeParallelogram::getInternalCoordForPoint (resolvedPoints, fontSizeControlPoint.resolve (context)));
const Point<float> fontCoords (RelativeParallelogram::getInternalCoordForPoint (resolvedPoints, fontSizeControlPoint.resolve (scope)));
const float fontHeight = jlimit (0.01f, jmax (0.01f, h), fontCoords.getY()); const float fontHeight = jlimit (0.01f, jmax (0.01f, h), fontCoords.getY());
const float fontWidth = jlimit (0.01f, jmax (0.01f, w), fontCoords.getX()); const float fontWidth = jlimit (0.01f, jmax (0.01f, w), fontCoords.getX());


+ 1
- 1
src/gui/graphics/drawables/juce_DrawableText.h View File

@@ -142,7 +142,7 @@ private:
friend class Drawable::Positioner<DrawableText>; friend class Drawable::Positioner<DrawableText>;
bool registerCoordinates (RelativeCoordinatePositionerBase&); bool registerCoordinates (RelativeCoordinatePositionerBase&);
void recalculateCoordinates (Expression::EvaluationContext*);
void recalculateCoordinates (Expression::Scope*);
void refreshBounds(); void refreshBounds();
const AffineTransform getArrangementAndTransform (GlyphArrangement& glyphs) const; const AffineTransform getArrangementAndTransform (GlyphArrangement& glyphs) const;


+ 446
- 295
src/maths/juce_Expression.cpp
File diff suppressed because it is too large
View File


+ 68
- 68
src/maths/juce_Expression.h View File

@@ -42,7 +42,7 @@
evaluated. evaluated.
Expressions which use identifiers and functions require a subclass of Expressions which use identifiers and functions require a subclass of
Expression::EvaluationContext to be supplied when evaluating them, and this object
Expression::Scope to be supplied when evaluating them, and this object
is expected to be able to resolve the symbol names and perform the functions that is expected to be able to resolve the symbol names and perform the functions that
are used. are used.
*/ */
@@ -105,11 +105,14 @@ public:
/** When evaluating an Expression object, this class is used to resolve symbols and /** When evaluating an Expression object, this class is used to resolve symbols and
perform functions that the expression uses. perform functions that the expression uses.
*/ */
class JUCE_API EvaluationContext
class JUCE_API Scope
{ {
public: public:
EvaluationContext();
virtual ~EvaluationContext();
Scope();
virtual ~Scope();
/** Returns some kind of globally unique ID that identifies this scope. */
virtual const String getScopeUID() const;
/** Returns the value of a symbol. /** Returns the value of a symbol.
If the symbol is unknown, this can throw an Expression::EvaluationError exception. If the symbol is unknown, this can throw an Expression::EvaluationError exception.
@@ -117,55 +120,97 @@ public:
one, e.g. for "foo.bar", symbol = "foo" and member = "bar". one, e.g. for "foo.bar", symbol = "foo" and member = "bar".
@throws Expression::EvaluationError @throws Expression::EvaluationError
*/ */
virtual const Expression getSymbolValue (const String& symbol, const String& member) const;
virtual const Expression getSymbolValue (const String& symbol) const;
/** Executes a named function. /** Executes a named function.
If the function name is unknown, this can throw an Expression::EvaluationError exception. If the function name is unknown, this can throw an Expression::EvaluationError exception.
@throws Expression::EvaluationError @throws Expression::EvaluationError
*/ */
virtual double evaluateFunction (const String& functionName, const double* parameters, int numParams) const;
virtual double evaluateFunction (const String& functionName,
const double* parameters, int numParameters) const;
/** Used as a callback by the Scope::visitRelativeScope() method.
You should never create an instance of this class yourself, it's used by the
expression evaluation code.
*/
class Visitor
{
public:
virtual ~Visitor() {}
virtual void visit (const Scope&) = 0;
};
/** Creates a Scope object for a named scope, and then calls a visitor
to do some kind of processing with this new scope.
If the name is valid, this method must create a suitable (temporary) Scope
object to represent it, and must call the Visitor::visit() method with this
new scope.
*/
virtual void visitRelativeScope (const String& scopeName, Visitor& visitor) const;
}; };
/** Evaluates this expression, without using an EvaluationContext.
Without an EvaluationContext, no symbols can be used, and only basic functions such as sin, cos, tan,
/** Evaluates this expression, without using a Scope.
Without a Scope, no symbols can be used, and only basic functions such as sin, cos, tan,
min, max are available. min, max are available.
@throws Expression::EvaluationError
To find out about any errors during evaluation, use the other version of this method which
takes a String parameter.
*/ */
double evaluate() const; double evaluate() const;
/** Evaluates this expression, providing a context that should be able to evaluate any symbols
/** Evaluates this expression, providing a scope that should be able to evaluate any symbols
or functions that it uses. or functions that it uses.
@throws Expression::EvaluationError
To find out about any errors during evaluation, use the other version of this method which
takes a String parameter.
*/ */
double evaluate (const EvaluationContext& context) const;
double evaluate (const Scope& scope) const;
/** Evaluates this expression, providing a scope that should be able to evaluate any symbols
or functions that it uses.
*/
double evaluate (const Scope& scope, String& evaluationError) const;
/** Attempts to return an expression which is a copy of this one, but with a constant adjusted /** Attempts to return an expression which is a copy of this one, but with a constant adjusted
to make the expression resolve to a target value. to make the expression resolve to a target value.
E.g. if the expression is "x + 10" and x is 5, then asking for a target value of 8 will return E.g. if the expression is "x + 10" and x is 5, then asking for a target value of 8 will return
the expression "x + 3". Obviously some expressions can't be reversed in this way, in which the expression "x + 3". Obviously some expressions can't be reversed in this way, in which
case they might just be adjusted by adding a constant to them.
case they might just be adjusted by adding a constant to the original expression.
@throws Expression::EvaluationError @throws Expression::EvaluationError
*/ */
const Expression adjustedToGiveNewResult (double targetValue, const EvaluationContext& context) const;
const Expression adjustedToGiveNewResult (double targetValue, const Scope& scope) const;
/** Represents a symbol that is used in an Expression. */
struct Symbol
{
Symbol (const String& scopeUID, const String& symbolName);
bool operator== (const Symbol&) const throw();
bool operator!= (const Symbol&) const throw();
String scopeUID; /**< The unique ID of the Scope that contains this symbol. */
String symbolName; /**< The name of the symbol. */
};
/** Returns a copy of this expression in which all instances of a given symbol have been renamed. */ /** Returns a copy of this expression in which all instances of a given symbol have been renamed. */
const Expression withRenamedSymbol (const String& oldSymbol, const String& newSymbol) const;
const Expression withRenamedSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope) const;
/** Returns true if this expression makes use of the specified symbol. /** Returns true if this expression makes use of the specified symbol.
If a suitable context is supplied, the search will dereference and recursively check
If a suitable scope is supplied, the search will dereference and recursively check
all symbols, so that it can be determined whether this expression relies on the given all symbols, so that it can be determined whether this expression relies on the given
symbol at any level in its evaluation. If the context parameter is null, this just checks
symbol at any level in its evaluation. If the scope parameter is null, this just checks
whether the expression contains any direct references to the symbol. whether the expression contains any direct references to the symbol.
@throws Expression::EvaluationError @throws Expression::EvaluationError
*/ */
bool referencesSymbol (const String& symbol, const EvaluationContext* context) const;
bool referencesSymbol (const Symbol& symbol, const Scope& scope) const;
/** Returns true if this expression contains any symbols. */ /** Returns true if this expression contains any symbols. */
bool usesAnySymbols() const; bool usesAnySymbols() const;
/** Returns a list of all symbols that may be needed to resolve this expression in the given scope. */
void findReferencedSymbols (Array<Symbol>& results, const Scope& scope) const;
//============================================================================== //==============================================================================
/** An exception that can be thrown by Expression::parse(). */ /** An exception that can be thrown by Expression::parse(). */
class ParseError : public std::exception class ParseError : public std::exception
@@ -176,17 +221,6 @@ public:
String description; String description;
}; };
//==============================================================================
/** An exception that can be thrown by Expression::evaluate(). */
class EvaluationError : public std::exception
{
public:
EvaluationError (const String& message);
EvaluationError (const String& symbolName, const String& memberName);
String description;
};
//============================================================================== //==============================================================================
/** Expression type. /** Expression type.
@see Expression::getType() @see Expression::getType()
@@ -202,19 +236,8 @@ public:
/** Returns the type of this expression. */ /** Returns the type of this expression. */
Type getType() const throw(); Type getType() const throw();
/** If this expression is a symbol, this returns its full name. */
const String getSymbol() const;
/** For a symbol that contains a dot, this returns the two */
void getSymbolParts (String& objectName, String& memberName) const;
/** If this expression is a function, this returns its name. */
const String getFunction() const;
/** If this expression is an operator, this returns its name.
E.g. "+", "-", "*", "/", etc.
*/
const String getOperator() const;
/** If this expression is a symbol, function or operator, this returns its identifier. */
const String getSymbolOrFunction() const;
/** Returns the number of inputs to this expression. /** Returns the number of inputs to this expression.
@see getInput @see getInput
@@ -228,35 +251,12 @@ public:
private: private:
//============================================================================== //==============================================================================
class Term;
class Helpers; class Helpers;
friend class Term;
friend class Helpers; friend class Helpers;
class Term : public ReferenceCountedObject
{
public:
Term() {}
virtual ~Term() {}
virtual Term* clone() const = 0;
virtual double evaluate (const EvaluationContext&, int recursionDepth) const = 0;
virtual int getNumInputs() const = 0;
virtual Term* getInput (int index) const = 0;
virtual int getInputIndexFor (const Term* possibleInput) const;
virtual const String toString() const = 0;
virtual int getOperatorPrecedence() const;
virtual bool referencesSymbol (const String& symbol, const EvaluationContext*, int recursionDepth) const;
virtual const ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const EvaluationContext&, const Term* inputTerm,
double overallTarget, Term* topLevelTerm) const;
virtual const ReferenceCountedObjectPtr<Term> negated();
virtual Type getType() const throw() = 0;
virtual void getSymbolParts (String& objectName, String& memberName) const;
virtual const String getFunctionName() const;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Term);
};
friend class ScopedPointer<Term>; friend class ScopedPointer<Term>;
friend class ReferenceCountedObjectPtr<Term>;
ReferenceCountedObjectPtr<Term> term; ReferenceCountedObjectPtr<Term> term;
explicit Expression (Term* term); explicit Expression (Term* term);


Loading…
Cancel
Save