| @@ -104,21 +104,21 @@ ProjectInformationComponent::ProjectInformationComponent (Project& project_) | |||
| configTabBox (TabbedButtonBar::TabsAtTop) | |||
| { | |||
| 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); | |||
| 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.addListener (this); | |||
| 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.addListener (this); | |||
| 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.addListener (this); | |||
| 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.addListener (this); | |||
| @@ -354,22 +354,22 @@ JUCER_COMPONENT_METADATA_START | |||
| constructorParams="Project& project_" memberInitialisers="project (project_)"> | |||
| <COMPONENTS> | |||
| <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" | |||
| text="Add/Remove Configurations..." createCallback="1" radioGroup="0" | |||
| connectedLeft="0" connectedRight="0" connectedTop="0" connectedBottom="0" | |||
| 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" | |||
| text="Open Project in " createCallback="1" radioGroup="0" connectedLeft="0" | |||
| 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" | |||
| text="Add/Remove Exporters..." createCallback="1" radioGroup="0" | |||
| connectedLeft="0" connectedRight="0" connectedTop="0" connectedBottom="0" | |||
| 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" | |||
| connectedRight="0" connectedTop="0" connectedBottom="0"/> | |||
| </COMPONENTS> | |||
| @@ -112,6 +112,7 @@ namespace Ids | |||
| DECLARE_ID (tooltip); | |||
| DECLARE_ID (memberName); | |||
| DECLARE_ID (focusOrder); | |||
| DECLARE_ID (hidden); | |||
| const Identifier class_ ("class"); | |||
| const Identifier id_ ("id"); | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 14 | |||
| #define JUCE_BUILDNUMBER 15 | |||
| /** Current Juce version number. | |||
| @@ -17817,7 +17817,7 @@ private: | |||
| evaluated. | |||
| 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 | |||
| are used. | |||
| */ | |||
| @@ -17879,11 +17879,14 @@ public: | |||
| /** When evaluating an Expression object, this class is used to resolve symbols and | |||
| perform functions that the expression uses. | |||
| */ | |||
| class JUCE_API EvaluationContext | |||
| class JUCE_API Scope | |||
| { | |||
| 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. | |||
| 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". | |||
| @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. | |||
| If the function name is unknown, this can throw an Expression::EvaluationError exception. | |||
| @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. | |||
| @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; | |||
| /** 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. | |||
| @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 | |||
| 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 | |||
| 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 | |||
| */ | |||
| 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. */ | |||
| 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. | |||
| 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 | |||
| 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. | |||
| @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. */ | |||
| 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(). */ | |||
| class ParseError : public std::exception | |||
| { | |||
| @@ -17949,16 +17994,6 @@ public: | |||
| 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. | |||
| @see Expression::getType() | |||
| */ | |||
| @@ -17973,19 +18008,8 @@ public: | |||
| /** Returns the type of this expression. */ | |||
| 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. | |||
| @see getInput | |||
| @@ -17999,35 +18023,12 @@ public: | |||
| private: | |||
| class Term; | |||
| class Helpers; | |||
| friend class Term; | |||
| 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 ReferenceCountedObjectPtr<Term>; | |||
| ReferenceCountedObjectPtr<Term> term; | |||
| explicit Expression (Term* term); | |||
| @@ -27477,35 +27478,35 @@ public: | |||
| for more details. | |||
| 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 | |||
| 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 | |||
| if you wanted to make your component remain centred within its parent with a size of 100, 100, | |||
| 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 | |||
| ..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 | |||
| 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: | |||
| @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 | |||
| Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will | |||
| @@ -43481,7 +43482,6 @@ public: | |||
| AudioProcessorGraph(); | |||
| /** Destructor. | |||
| Any processor objects that have been added to the graph will also be deleted. | |||
| */ | |||
| ~AudioProcessorGraph(); | |||
| @@ -43493,9 +43493,6 @@ public: | |||
| class JUCE_API Node : public ReferenceCountedObject | |||
| { | |||
| public: | |||
| /** Destructor. | |||
| */ | |||
| ~Node(); | |||
| /** The ID number assigned to this node. | |||
| @@ -45643,18 +45640,18 @@ public: | |||
| /** 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. | |||
| */ | |||
| 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. | |||
| 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. */ | |||
| 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. */ | |||
| bool isDynamic() const; | |||
| @@ -45665,10 +45662,7 @@ public: | |||
| or relative position to whatever value is necessary to make its resultant position | |||
| 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. */ | |||
| const Expression& getExpression() const { return term; } | |||
| @@ -45688,15 +45682,27 @@ public: | |||
| struct Strings | |||
| { | |||
| static const String parent; /**< "parent" */ | |||
| static const String this_; /**< "this" */ | |||
| static const String left; /**< "left" */ | |||
| static const String right; /**< "right" */ | |||
| static const String top; /**< "top" */ | |||
| 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: | |||
| @@ -45749,10 +45755,10 @@ public: | |||
| /** 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. | |||
| */ | |||
| 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. | |||
| @@ -45760,7 +45766,7 @@ public: | |||
| or relative positions to whatever values are necessary to make the resultant position | |||
| 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. | |||
| 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; | |||
| /** 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. */ | |||
| bool isDynamic() const; | |||
| @@ -45946,15 +45947,12 @@ private: | |||
| */ | |||
| class JUCE_API RelativeCoordinatePositionerBase : public Component::Positioner, | |||
| public ComponentListener, | |||
| public MarkerList::Listener, | |||
| public Expression::EvaluationContext | |||
| public MarkerList::Listener | |||
| { | |||
| public: | |||
| RelativeCoordinatePositionerBase (Component& component_); | |||
| ~RelativeCoordinatePositionerBase(); | |||
| const Expression getSymbolValue (const String& objectName, const String& member) const; | |||
| void componentMovedOrResized (Component&, bool, bool); | |||
| void componentParentHierarchyChanged (Component&); | |||
| void componentBeingDeleted (Component& component); | |||
| @@ -45966,25 +45964,40 @@ public: | |||
| bool addCoordinate (const RelativeCoordinate& coord); | |||
| 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: | |||
| virtual bool registerCoordinates() = 0; | |||
| virtual void applyToComponentBounds() = 0; | |||
| private: | |||
| class DependencyFinderScope; | |||
| friend class DependencyFinderScope; | |||
| Array <Component*> sourceComponents; | |||
| Array <MarkerList*> sourceMarkerLists; | |||
| 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 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); | |||
| }; | |||
| @@ -46395,7 +46408,11 @@ protected: | |||
| {} | |||
| bool registerCoordinates() { return owner.registerCoordinates (*this); } | |||
| void applyToComponentBounds() { owner.recalculateCoordinates (this); } | |||
| void applyToComponentBounds() | |||
| { | |||
| ComponentScope scope (getComponent()); | |||
| owner.recalculateCoordinates (&scope); | |||
| } | |||
| private: | |||
| DrawableType& owner; | |||
| @@ -57857,11 +57874,11 @@ public: | |||
| RelativeParallelogram (const String& topLeft, const String& topRight, const String& bottomLeft); | |||
| ~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 operator== (const RelativeParallelogram& other) const throw(); | |||
| @@ -57911,7 +57928,7 @@ public: | |||
| bool operator!= (const RelativePointPath& other) const throw(); | |||
| /** 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. */ | |||
| bool containsAnyDynamicPoints() const; | |||
| @@ -57940,7 +57957,7 @@ public: | |||
| ElementBase (ElementType type); | |||
| virtual ~ElementBase() {} | |||
| 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 ElementBase* clone() const = 0; | |||
| bool isDynamic(); | |||
| @@ -57956,7 +57973,7 @@ public: | |||
| public: | |||
| StartSubPath (const RelativePoint& pos); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -57971,7 +57988,7 @@ public: | |||
| public: | |||
| CloseSubPath(); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -57984,7 +58001,7 @@ public: | |||
| public: | |||
| LineTo (const RelativePoint& endPoint); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -57999,7 +58016,7 @@ public: | |||
| public: | |||
| QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -58014,7 +58031,7 @@ public: | |||
| public: | |||
| CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -58087,10 +58104,10 @@ public: | |||
| /** 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. | |||
| */ | |||
| 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. | |||
| @@ -58098,7 +58115,7 @@ public: | |||
| or relative positions to whatever values are necessary to make the resultant position | |||
| 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. | |||
| Coordinates that refer to symbols based on "this" are assumed not to be dynamic. | |||
| @@ -58113,9 +58130,9 @@ public: | |||
| const String toString() const; | |||
| /** 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 | |||
| keep it positioned with this rectangle. | |||
| @@ -61907,7 +61924,7 @@ private: | |||
| friend class Drawable::Positioner<DrawableComposite>; | |||
| bool registerCoordinates (RelativeCoordinatePositionerBase&); | |||
| void recalculateCoordinates (Expression::EvaluationContext*); | |||
| void recalculateCoordinates (Expression::Scope*); | |||
| void updateBoundsToFitChildren(); | |||
| @@ -62024,7 +62041,7 @@ private: | |||
| friend class Drawable::Positioner<DrawableImage>; | |||
| bool registerCoordinates (RelativeCoordinatePositionerBase&); | |||
| void recalculateCoordinates (Expression::EvaluationContext*); | |||
| void recalculateCoordinates (Expression::Scope*); | |||
| DrawableImage& operator= (const DrawableImage&); | |||
| JUCE_LEAK_DETECTOR (DrawableImage); | |||
| @@ -62077,7 +62094,7 @@ public: | |||
| bool operator!= (const RelativeFillType&) const; | |||
| bool isDynamic() const; | |||
| bool recalculateCoords (Expression::EvaluationContext* context); | |||
| bool recalculateCoords (Expression::Scope* scope); | |||
| void writeTo (ValueTree& v, ComponentBuilder::ImageProvider*, UndoManager*) const; | |||
| bool readFrom (const ValueTree& v, ComponentBuilder::ImageProvider*); | |||
| @@ -62260,7 +62277,7 @@ public: | |||
| const RelativePoint getStartPoint() const; | |||
| const RelativePoint getEndPoint() const; | |||
| void setControlPoint (int index, const RelativePoint& point, UndoManager*); | |||
| float getLength (Expression::EvaluationContext*) const; | |||
| float getLength (Expression::Scope*) const; | |||
| ValueTreeWrapper getParent() const; | |||
| Element getPreviousElement() const; | |||
| @@ -62269,11 +62286,11 @@ public: | |||
| void setModeOfEndPoint (const String& newMode, UndoManager*); | |||
| void convertToLine (UndoManager*); | |||
| void convertToCubic (Expression::EvaluationContext*, UndoManager*); | |||
| void convertToCubic (Expression::Scope*, 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); | |||
| float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext*) const; | |||
| float findProportionAlongLine (const Point<float>& targetPoint, Expression::Scope*) const; | |||
| static const Identifier mode, startSubPathElement, closeSubPathElement, | |||
| lineToElement, quadraticToElement, cubicToElement; | |||
| @@ -62298,7 +62315,7 @@ private: | |||
| class RelativePositioner; | |||
| friend class RelativePositioner; | |||
| void applyRelativePath (const RelativePointPath&, Expression::EvaluationContext*); | |||
| void applyRelativePath (const RelativePointPath&, Expression::Scope*); | |||
| DrawablePath& operator= (const DrawablePath&); | |||
| JUCE_LEAK_DETECTOR (DrawablePath); | |||
| @@ -62377,7 +62394,7 @@ private: | |||
| void rebuildPath(); | |||
| bool registerCoordinates (RelativeCoordinatePositionerBase&); | |||
| void recalculateCoordinates (Expression::EvaluationContext*); | |||
| void recalculateCoordinates (Expression::Scope*); | |||
| DrawableRectangle& operator= (const DrawableRectangle&); | |||
| JUCE_LEAK_DETECTOR (DrawableRectangle); | |||
| @@ -62503,7 +62520,7 @@ private: | |||
| friend class Drawable::Positioner<DrawableText>; | |||
| bool registerCoordinates (RelativeCoordinatePositionerBase&); | |||
| void recalculateCoordinates (Expression::EvaluationContext*); | |||
| void recalculateCoordinates (Expression::Scope*); | |||
| void refreshBounds(); | |||
| const AffineTransform getArrangementAndTransform (GlyphArrangement& glyphs) const; | |||
| @@ -370,10 +370,6 @@ public: | |||
| } | |||
| } | |||
| ~WavAudioFormatReader() | |||
| { | |||
| } | |||
| //============================================================================== | |||
| bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, | |||
| int64 startSampleInFile, int numSamples) | |||
| @@ -532,7 +528,8 @@ private: | |||
| const int bytesPerFrame = numChannels * bitsPerSample / 8; | |||
| output->writeInt (chunkName ("RIFF")); | |||
| 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 ("fmt ")); | |||
| @@ -42,10 +42,6 @@ AudioProcessorGraph::Node::Node (const uint32 id_, AudioProcessor* const process | |||
| jassert (processor_ != 0); | |||
| } | |||
| AudioProcessorGraph::Node::~Node() | |||
| { | |||
| } | |||
| void AudioProcessorGraph::Node::prepare (const double sampleRate, const int blockSize, | |||
| AudioProcessorGraph* const graph) | |||
| { | |||
| @@ -57,7 +57,6 @@ public: | |||
| AudioProcessorGraph(); | |||
| /** Destructor. | |||
| Any processor objects that have been added to the graph will also be deleted. | |||
| */ | |||
| ~AudioProcessorGraph(); | |||
| @@ -70,10 +69,6 @@ public: | |||
| class JUCE_API Node : public ReferenceCountedObject | |||
| { | |||
| public: | |||
| /** Destructor. | |||
| */ | |||
| ~Node(); | |||
| //============================================================================== | |||
| /** The ID number assigned to this node. | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 14 | |||
| #define JUCE_BUILDNUMBER 15 | |||
| /** Current Juce version number. | |||
| @@ -888,8 +888,13 @@ const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) | |||
| Graphics g (snapshot); | |||
| g.setOrigin (pos.getX() - imageX, pos.getY() - imageY); | |||
| if (g.reduceClipRegion (rowComp->getLocalBounds())) | |||
| { | |||
| g.beginTransparencyLayer (0.6f); | |||
| rowComp->paintEntireComponent (g, false); | |||
| g.endTransparencyLayer(); | |||
| } | |||
| } | |||
| } | |||
| @@ -905,7 +910,6 @@ void ListBox::startDragAndDrop (const MouseEvent& e, const String& dragDescripti | |||
| { | |||
| int x, y; | |||
| Image dragImage (createSnapshotOfSelectedRows (x, y)); | |||
| dragImage.multiplyAllAlphas (0.6f); | |||
| MouseEvent e2 (e.getEventRelativeTo (this)); | |||
| const Point<int> p (x - e2.x, y - e2.y); | |||
| @@ -488,35 +488,35 @@ public: | |||
| for more details. | |||
| 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 | |||
| 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 | |||
| if you wanted to make your component remain centred within its parent with a size of 100, 100, | |||
| 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 | |||
| ..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 | |||
| 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: | |||
| @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 | |||
| Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will | |||
| @@ -65,6 +65,8 @@ public: | |||
| void componentBeingDeleted (Component& comp) | |||
| { | |||
| ComponentMovementWatcher::componentBeingDeleted (comp); | |||
| if (component == &comp || comp.isParentOf (component)) | |||
| cancel(); | |||
| } | |||
| @@ -201,9 +203,14 @@ void ModalComponentManager::handleAsyncUpdate() | |||
| if (! item->isActive) | |||
| { | |||
| for (int j = item->callbacks.size(); --j >= 0;) | |||
| { | |||
| item->callbacks.getUnchecked(j)->modalStateFinished (item->returnValue); | |||
| stack.remove (i); | |||
| if (! stack.contains (item)) | |||
| break; | |||
| } | |||
| stack.removeObject (item); | |||
| } | |||
| } | |||
| } | |||
| @@ -28,8 +28,10 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_MarkerList.h" | |||
| #include "juce_RelativeCoordinatePositioner.h" | |||
| #include "../juce_Component.h" | |||
| //============================================================================== | |||
| MarkerList::MarkerList() | |||
| { | |||
| @@ -246,44 +248,17 @@ void MarkerList::ValueTreeWrapper::removeMarker (const ValueTree& marker, UndoMa | |||
| 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); | |||
| } | |||
| //============================================================================== | |||
| @@ -32,15 +32,28 @@ BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| const String RelativeCoordinate::Strings::parent ("parent"); | |||
| const String RelativeCoordinate::Strings::this_ ("this"); | |||
| const String RelativeCoordinate::Strings::left ("left"); | |||
| const String RelativeCoordinate::Strings::right ("right"); | |||
| const String RelativeCoordinate::Strings::top ("top"); | |||
| 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() | |||
| @@ -92,12 +105,12 @@ bool RelativeCoordinate::operator!= (const RelativeCoordinate& other) const thro | |||
| return ! operator== (other); | |||
| } | |||
| double RelativeCoordinate::resolve (const Expression::EvaluationContext* context) const | |||
| double RelativeCoordinate::resolve (const Expression::Scope* scope) const | |||
| { | |||
| try | |||
| { | |||
| if (context != 0) | |||
| return term.evaluate (*context); | |||
| if (scope != 0) | |||
| return term.evaluate (*scope); | |||
| else | |||
| return term.evaluate(); | |||
| } | |||
| @@ -107,12 +120,12 @@ double RelativeCoordinate::resolve (const Expression::EvaluationContext* context | |||
| return 0.0; | |||
| } | |||
| bool RelativeCoordinate::isRecursive (const Expression::EvaluationContext* context) const | |||
| bool RelativeCoordinate::isRecursive (const Expression::Scope* scope) const | |||
| { | |||
| try | |||
| { | |||
| if (context != 0) | |||
| term.evaluate (*context); | |||
| if (scope != 0) | |||
| term.evaluate (*scope); | |||
| else | |||
| term.evaluate(); | |||
| } | |||
| @@ -124,36 +137,24 @@ bool RelativeCoordinate::isRecursive (const Expression::EvaluationContext* conte | |||
| return false; | |||
| } | |||
| void RelativeCoordinate::moveToAbsolute (double newPos, const Expression::EvaluationContext* context) | |||
| void RelativeCoordinate::moveToAbsolute (double newPos, const Expression::Scope* scope) | |||
| { | |||
| try | |||
| { | |||
| if (context != 0) | |||
| if (scope != 0) | |||
| { | |||
| term = term.adjustedToGiveNewResult (newPos, *context); | |||
| term = term.adjustedToGiveNewResult (newPos, *scope); | |||
| } | |||
| else | |||
| { | |||
| Expression::EvaluationContext defaultContext; | |||
| term = term.adjustedToGiveNewResult (newPos, defaultContext); | |||
| Expression::Scope defaultScope; | |||
| term = term.adjustedToGiveNewResult (newPos, defaultScope); | |||
| } | |||
| } | |||
| 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 | |||
| { | |||
| return term.usesAnySymbols(); | |||
| @@ -164,13 +165,6 @@ const String RelativeCoordinate::toString() const | |||
| 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 | |||
| @@ -69,18 +69,18 @@ public: | |||
| //============================================================================== | |||
| /** 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. | |||
| */ | |||
| 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. | |||
| 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. */ | |||
| 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. */ | |||
| bool isDynamic() const; | |||
| @@ -92,10 +92,7 @@ public: | |||
| or relative position to whatever value is necessary to make its resultant position | |||
| 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. */ | |||
| const Expression& getExpression() const { return term; } | |||
| @@ -118,15 +115,27 @@ public: | |||
| struct Strings | |||
| { | |||
| static const String parent; /**< "parent" */ | |||
| static const String this_; /**< "this" */ | |||
| static const String left; /**< "left" */ | |||
| static const String right; /**< "right" */ | |||
| static const String top; /**< "top" */ | |||
| 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: | |||
| @@ -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*/) | |||
| @@ -118,7 +238,10 @@ void RelativeCoordinatePositionerBase::apply() | |||
| 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) | |||
| @@ -127,95 +250,12 @@ bool RelativeCoordinatePositionerBase::addPoint (const RelativePoint& point) | |||
| 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(); | |||
| } | |||
| 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 | |||
| @@ -37,15 +37,12 @@ | |||
| */ | |||
| class JUCE_API RelativeCoordinatePositionerBase : public Component::Positioner, | |||
| public ComponentListener, | |||
| public MarkerList::Listener, | |||
| public Expression::EvaluationContext | |||
| public MarkerList::Listener | |||
| { | |||
| public: | |||
| RelativeCoordinatePositionerBase (Component& component_); | |||
| ~RelativeCoordinatePositionerBase(); | |||
| const Expression getSymbolValue (const String& objectName, const String& member) const; | |||
| void componentMovedOrResized (Component&, bool, bool); | |||
| void componentParentHierarchyChanged (Component&); | |||
| void componentBeingDeleted (Component& component); | |||
| @@ -57,25 +54,41 @@ public: | |||
| bool addCoordinate (const RelativeCoordinate& coord); | |||
| 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: | |||
| virtual bool registerCoordinates() = 0; | |||
| virtual void applyToComponentBounds() = 0; | |||
| private: | |||
| class DependencyFinderScope; | |||
| friend class DependencyFinderScope; | |||
| Array <Component*> sourceComponents; | |||
| Array <MarkerList*> sourceMarkerLists; | |||
| 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 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); | |||
| }; | |||
| @@ -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]); | |||
| } | |||
| const Rectangle<float> RelativeParallelogram::getBounds (Expression::EvaluationContext* const coordFinder) const | |||
| const Rectangle<float> RelativeParallelogram::getBounds (Expression::Scope* const scope) const | |||
| { | |||
| Point<float> points[4]; | |||
| resolveFourCorners (points, coordFinder); | |||
| resolveFourCorners (points, scope); | |||
| 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]; | |||
| resolveFourCorners (points, coordFinder); | |||
| resolveFourCorners (points, scope); | |||
| path.startNewSubPath (points[0]); | |||
| path.lineTo (points[1]); | |||
| @@ -85,18 +85,18 @@ void RelativeParallelogram::getPath (Path& path, Expression::EvaluationContext* | |||
| path.closeSubPath(); | |||
| } | |||
| const AffineTransform RelativeParallelogram::resetToPerpendicular (Expression::EvaluationContext* const coordFinder) | |||
| const AffineTransform RelativeParallelogram::resetToPerpendicular (Expression::Scope* const scope) | |||
| { | |||
| Point<float> corners[3]; | |||
| resolveThreePoints (corners, coordFinder); | |||
| resolveThreePoints (corners, scope); | |||
| const Line<float> top (corners[0], corners[1]); | |||
| const Line<float> left (corners[0], corners[2]); | |||
| const Point<float> newTopRight (corners[0] + Point<float> (top.getLength(), 0.0f)); | |||
| 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(), | |||
| corners[1].getX(), corners[1].getY(), newTopRight.getX(), newTopRight.getY(), | |||
| @@ -46,11 +46,11 @@ public: | |||
| ~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 operator== (const RelativeParallelogram& other) const throw(); | |||
| @@ -79,16 +79,16 @@ bool RelativePoint::operator!= (const RelativePoint& other) const throw() | |||
| 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 | |||
| @@ -96,12 +96,6 @@ const String RelativePoint::toString() const | |||
| 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 | |||
| { | |||
| return x.isDynamic() || y.isDynamic(); | |||
| @@ -62,10 +62,10 @@ public: | |||
| /** 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. | |||
| */ | |||
| 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. | |||
| @@ -73,7 +73,7 @@ public: | |||
| or relative positions to whatever values are necessary to make the resultant position | |||
| 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. | |||
| 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; | |||
| /** 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. */ | |||
| bool isDynamic() const; | |||
| @@ -109,10 +109,10 @@ void RelativePointPath::swapWith (RelativePointPath& other) throw() | |||
| 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) | |||
| elements.getUnchecked(i)->addToPath (path, coordFinder); | |||
| elements.getUnchecked(i)->addToPath (path, scope); | |||
| } | |||
| bool RelativePointPath::containsAnyDynamicPoints() const | |||
| @@ -159,9 +159,9 @@ const ValueTree RelativePointPath::StartSubPath::createTree() const | |||
| 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) | |||
| @@ -186,7 +186,7 @@ const ValueTree RelativePointPath::CloseSubPath::createTree() const | |||
| 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(); | |||
| } | |||
| @@ -215,9 +215,9 @@ const ValueTree RelativePointPath::LineTo::createTree() const | |||
| 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) | |||
| @@ -247,10 +247,10 @@ const ValueTree RelativePointPath::QuadraticTo::createTree() const | |||
| 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) | |||
| @@ -283,11 +283,11 @@ const ValueTree RelativePointPath::CubicTo::createTree() const | |||
| 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) | |||
| @@ -54,7 +54,7 @@ public: | |||
| //============================================================================== | |||
| /** 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. */ | |||
| bool containsAnyDynamicPoints() const; | |||
| @@ -85,7 +85,7 @@ public: | |||
| ElementBase (ElementType type); | |||
| virtual ~ElementBase() {} | |||
| 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 ElementBase* clone() const = 0; | |||
| bool isDynamic(); | |||
| @@ -102,7 +102,7 @@ public: | |||
| public: | |||
| StartSubPath (const RelativePoint& pos); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -118,7 +118,7 @@ public: | |||
| public: | |||
| CloseSubPath(); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -132,7 +132,7 @@ public: | |||
| public: | |||
| LineTo (const RelativePoint& endPoint); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -148,7 +148,7 @@ public: | |||
| public: | |||
| QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -164,7 +164,7 @@ public: | |||
| public: | |||
| CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint); | |||
| const ValueTree createTree() const; | |||
| void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const; | |||
| void addToPath (Path& path, Expression::Scope*) const; | |||
| RelativePoint* getControlPoints (int& numPoints); | |||
| ElementBase* clone() const; | |||
| @@ -30,6 +30,8 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_RelativeRectangle.h" | |||
| #include "juce_RelativeCoordinatePositioner.h" | |||
| //============================================================================== | |||
| namespace RelativeRectangleHelpers | |||
| { | |||
| inline void skipComma (const juce_wchar* const s, int& i) | |||
| @@ -43,13 +45,23 @@ namespace RelativeRectangleHelpers | |||
| bool dependsOnSymbolsOtherThanThis (const Expression& e) | |||
| { | |||
| if (e.getType() == Expression::operatorType && e.getSymbolOrFunction() == ".") | |||
| return true; | |||
| 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 | |||
| { | |||
| @@ -75,11 +87,9 @@ RelativeRectangle::RelativeRectangle (const RelativeCoordinate& left_, const Rel | |||
| RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect) | |||
| : 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()), | |||
| 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); | |||
| } | |||
| 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 | |||
| @@ -138,12 +185,12 @@ const String RelativeRectangle::toString() const | |||
| 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;) | |||
| { | |||
| const Rectangle<int> newBounds (rectangle.resolve (this).getSmallestIntegerContainer()); | |||
| ComponentScope scope (getComponent()); | |||
| const Rectangle<int> newBounds (rectangle.resolve (&scope).getSmallestIntegerContainer()); | |||
| if (newBounds == getComponent().getBounds()) | |||
| return; | |||
| @@ -191,31 +239,6 @@ private: | |||
| 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 | |||
| { | |||
| if (isDynamic()) | |||
| @@ -233,9 +256,7 @@ void RelativeRectangle::applyToComponent (Component& component) const | |||
| else | |||
| { | |||
| component.setPositioner (0); | |||
| TemporaryRectangleContext context (*this); | |||
| component.setBounds (resolve (&context).getSmallestIntegerContainer()); | |||
| component.setBounds (resolve (0).getSmallestIntegerContainer()); | |||
| } | |||
| } | |||
| @@ -65,10 +65,10 @@ public: | |||
| //============================================================================== | |||
| /** 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. | |||
| */ | |||
| 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. | |||
| @@ -76,7 +76,7 @@ public: | |||
| or relative positions to whatever values are necessary to make the resultant position | |||
| 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. | |||
| Coordinates that refer to symbols based on "this" are assumed not to be dynamic. | |||
| @@ -91,9 +91,9 @@ public: | |||
| const String toString() const; | |||
| /** 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 | |||
| keep it positioned with this rectangle. | |||
| @@ -228,7 +228,11 @@ protected: | |||
| {} | |||
| bool registerCoordinates() { return owner.registerCoordinates (*this); } | |||
| void applyToComponentBounds() { owner.recalculateCoordinates (this); } | |||
| void applyToComponentBounds() | |||
| { | |||
| ComponentScope scope (getComponent()); | |||
| owner.recalculateCoordinates (&scope); | |||
| } | |||
| private: | |||
| DrawableType& owner; | |||
| @@ -153,12 +153,12 @@ bool DrawableComposite::registerCoordinates (RelativeCoordinatePositionerBase& p | |||
| return positioner.addPoint (bounds.bottomLeft) && ok; | |||
| } | |||
| void DrawableComposite::recalculateCoordinates (Expression::EvaluationContext* context) | |||
| void DrawableComposite::recalculateCoordinates (Expression::Scope* scope) | |||
| { | |||
| 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(), | |||
| content.getRight(), content.getY(), resolved[1].getX(), resolved[1].getY(), | |||
| @@ -150,7 +150,7 @@ private: | |||
| friend class Drawable::Positioner<DrawableComposite>; | |||
| bool registerCoordinates (RelativeCoordinatePositionerBase&); | |||
| void recalculateCoordinates (Expression::EvaluationContext*); | |||
| void recalculateCoordinates (Expression::Scope*); | |||
| void updateBoundsToFitChildren(); | |||
| @@ -106,12 +106,12 @@ bool DrawableImage::registerCoordinates (RelativeCoordinatePositionerBase& posit | |||
| return positioner.addPoint (bounds.bottomLeft) && ok; | |||
| } | |||
| void DrawableImage::recalculateCoordinates (Expression::EvaluationContext* context) | |||
| void DrawableImage::recalculateCoordinates (Expression::Scope* scope) | |||
| { | |||
| if (image.isValid()) | |||
| { | |||
| 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> bl (resolved[0] + (resolved[2] - resolved[0]) / (float) image.getHeight()); | |||
| @@ -133,7 +133,7 @@ private: | |||
| friend class Drawable::Positioner<DrawableImage>; | |||
| bool registerCoordinates (RelativeCoordinatePositionerBase&); | |||
| void recalculateCoordinates (Expression::EvaluationContext*); | |||
| void recalculateCoordinates (Expression::Scope*); | |||
| DrawableImage& operator= (const DrawableImage&); | |||
| JUCE_LEAK_DETECTOR (DrawableImage); | |||
| @@ -72,10 +72,10 @@ const Path& DrawablePath::getStrokePath() const | |||
| return strokePath; | |||
| } | |||
| void DrawablePath::applyRelativePath (const RelativePointPath& newRelativePath, Expression::EvaluationContext* context) | |||
| void DrawablePath::applyRelativePath (const RelativePointPath& newRelativePath, Expression::Scope* scope) | |||
| { | |||
| Path newPath; | |||
| newRelativePath.createPath (newPath, context); | |||
| newRelativePath.createPath (newPath, scope); | |||
| if (path != newPath) | |||
| { | |||
| @@ -118,7 +118,9 @@ public: | |||
| void applyToComponentBounds() | |||
| { | |||
| jassert (owner.relativePath != 0); | |||
| owner.applyRelativePath (*owner.relativePath, this); | |||
| ComponentScope scope (getComponent()); | |||
| owner.applyRelativePath (*owner.relativePath, &scope); | |||
| } | |||
| private: | |||
| @@ -299,26 +301,26 @@ const RelativePoint DrawablePath::ValueTreeWrapper::Element::getEndPoint() const | |||
| 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()); | |||
| if (i == lineToElement || i == closeSubPathElement) | |||
| return getEndPoint().resolve (context).getDistanceFrom (getStartPoint().resolve (context)); | |||
| return getEndPoint().resolve (scope).getDistanceFrom (getStartPoint().resolve (scope)); | |||
| if (i == cubicToElement) | |||
| { | |||
| 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(); | |||
| } | |||
| if (i == quadraticToElement) | |||
| { | |||
| 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(); | |||
| } | |||
| @@ -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()); | |||
| @@ -361,8 +363,8 @@ void DrawablePath::ValueTreeWrapper::Element::convertToCubic (Expression::Evalua | |||
| const RelativePoint start (getStartPoint()); | |||
| 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 (1, startResolved + (endResolved - startResolved) * 0.7f, 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; | |||
| 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()); | |||
| 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(); | |||
| @@ -437,7 +439,7 @@ float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Po | |||
| else if (type == quadraticToElement) | |||
| { | |||
| 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(); | |||
| @@ -457,24 +459,24 @@ float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Po | |||
| else if (type == lineToElement) | |||
| { | |||
| 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); | |||
| } | |||
| 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; | |||
| const Identifier type (state.getType()); | |||
| if (type == cubicToElement) | |||
| { | |||
| float bestProp = findProportionAlongLine (targetPoint, context); | |||
| float bestProp = findProportionAlongLine (targetPoint, scope); | |||
| 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), | |||
| mid2 (points[1] + (points[2] - points[1]) * bestProp), | |||
| @@ -499,10 +501,10 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa | |||
| } | |||
| else if (type == quadraticToElement) | |||
| { | |||
| float bestProp = findProportionAlongLine (targetPoint, context); | |||
| float bestProp = findProportionAlongLine (targetPoint, scope); | |||
| 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), | |||
| mid2 (points[1] + (points[2] - points[1]) * bestProp); | |||
| @@ -522,7 +524,7 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa | |||
| else if (type == lineToElement) | |||
| { | |||
| 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)); | |||
| setControlPoint (0, newPoint, undoManager); | |||
| @@ -101,7 +101,7 @@ public: | |||
| const RelativePoint getStartPoint() const; | |||
| const RelativePoint getEndPoint() const; | |||
| void setControlPoint (int index, const RelativePoint& point, UndoManager*); | |||
| float getLength (Expression::EvaluationContext*) const; | |||
| float getLength (Expression::Scope*) const; | |||
| ValueTreeWrapper getParent() const; | |||
| Element getPreviousElement() const; | |||
| @@ -110,11 +110,11 @@ public: | |||
| void setModeOfEndPoint (const String& newMode, UndoManager*); | |||
| void convertToLine (UndoManager*); | |||
| void convertToCubic (Expression::EvaluationContext*, UndoManager*); | |||
| void convertToCubic (Expression::Scope*, 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); | |||
| float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext*) const; | |||
| float findProportionAlongLine (const Point<float>& targetPoint, Expression::Scope*) const; | |||
| static const Identifier mode, startSubPathElement, closeSubPathElement, | |||
| lineToElement, quadraticToElement, cubicToElement; | |||
| @@ -139,7 +139,7 @@ private: | |||
| class RelativePositioner; | |||
| friend class RelativePositioner; | |||
| void applyRelativePath (const RelativePointPath&, Expression::EvaluationContext*); | |||
| void applyRelativePath (const RelativePointPath&, Expression::Scope*); | |||
| DrawablePath& operator= (const DrawablePath&); | |||
| JUCE_LEAK_DETECTOR (DrawablePath); | |||
| @@ -95,13 +95,13 @@ bool DrawableRectangle::registerCoordinates (RelativeCoordinatePositionerBase& p | |||
| return positioner.addPoint (cornerSize) && ok; | |||
| } | |||
| void DrawableRectangle::recalculateCoordinates (Expression::EvaluationContext* context) | |||
| void DrawableRectangle::recalculateCoordinates (Expression::Scope* scope) | |||
| { | |||
| 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 h = Line<float> (points[0], points[2]).getLength(); | |||
| @@ -97,7 +97,7 @@ private: | |||
| void rebuildPath(); | |||
| bool registerCoordinates (RelativeCoordinatePositionerBase&); | |||
| void recalculateCoordinates (Expression::EvaluationContext*); | |||
| void recalculateCoordinates (Expression::Scope*); | |||
| DrawableRectangle& operator= (const DrawableRectangle&); | |||
| JUCE_LEAK_DETECTOR (DrawableRectangle); | |||
| @@ -71,8 +71,9 @@ public: | |||
| 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(); | |||
| } | |||
| @@ -256,19 +257,19 @@ bool DrawableShape::RelativeFillType::operator!= (const RelativeFillType& other) | |||
| return ! operator== (other); | |||
| } | |||
| bool DrawableShape::RelativeFillType::recalculateCoords (Expression::EvaluationContext* context) | |||
| bool DrawableShape::RelativeFillType::recalculateCoords (Expression::Scope* scope) | |||
| { | |||
| 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; | |||
| ColourGradient& g = *fill.gradient; | |||
| 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(), | |||
| g1.getY() + g1.getX() - g2.getX()); | |||
| @@ -65,7 +65,7 @@ public: | |||
| bool operator!= (const RelativeFillType&) const; | |||
| bool isDynamic() const; | |||
| bool recalculateCoords (Expression::EvaluationContext* context); | |||
| bool recalculateCoords (Expression::Scope* scope); | |||
| void writeTo (ValueTree& v, ComponentBuilder::ImageProvider*, UndoManager*) const; | |||
| bool readFrom (const ValueTree& v, ComponentBuilder::ImageProvider*); | |||
| @@ -138,14 +138,14 @@ bool DrawableText::registerCoordinates (RelativeCoordinatePositionerBase& positi | |||
| 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 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 fontWidth = jlimit (0.01f, jmax (0.01f, w), fontCoords.getX()); | |||
| @@ -142,7 +142,7 @@ private: | |||
| friend class Drawable::Positioner<DrawableText>; | |||
| bool registerCoordinates (RelativeCoordinatePositionerBase&); | |||
| void recalculateCoordinates (Expression::EvaluationContext*); | |||
| void recalculateCoordinates (Expression::Scope*); | |||
| void refreshBounds(); | |||
| const AffineTransform getArrangementAndTransform (GlyphArrangement& glyphs) const; | |||
| @@ -42,7 +42,7 @@ | |||
| evaluated. | |||
| 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 | |||
| are used. | |||
| */ | |||
| @@ -105,11 +105,14 @@ public: | |||
| /** When evaluating an Expression object, this class is used to resolve symbols and | |||
| perform functions that the expression uses. | |||
| */ | |||
| class JUCE_API EvaluationContext | |||
| class JUCE_API Scope | |||
| { | |||
| 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. | |||
| 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". | |||
| @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. | |||
| If the function name is unknown, this can throw an Expression::EvaluationError exception. | |||
| @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. | |||
| @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; | |||
| /** 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. | |||
| @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 | |||
| 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 | |||
| 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 | |||
| */ | |||
| 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. */ | |||
| 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. | |||
| 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 | |||
| 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. | |||
| @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. */ | |||
| 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(). */ | |||
| class ParseError : public std::exception | |||
| @@ -176,17 +221,6 @@ public: | |||
| 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. | |||
| @see Expression::getType() | |||
| @@ -202,19 +236,8 @@ public: | |||
| /** Returns the type of this expression. */ | |||
| 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. | |||
| @see getInput | |||
| @@ -228,35 +251,12 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| class Term; | |||
| class Helpers; | |||
| friend class Term; | |||
| 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 ReferenceCountedObjectPtr<Term>; | |||
| ReferenceCountedObjectPtr<Term> term; | |||
| explicit Expression (Term* term); | |||