diff --git a/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.cpp b/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.cpp index f7d32f00e0..6965f26862 100644 --- a/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.cpp +++ b/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.cpp @@ -333,11 +333,8 @@ void RelativeRectangleLayoutManager::applyLayout() } } -const Expression RelativeRectangleLayoutManager::getSymbolValue (const String& symbol) const +const Expression RelativeRectangleLayoutManager::getSymbolValue (const String& objectName, const String& edge) const { - const String objectName (symbol.upToFirstOccurrenceOf (".", false, false).trim()); - const String edge (symbol.fromFirstOccurrenceOf (".", false, false).trim()); - if (objectName == RelativeCoordinate::Strings::parent) { if (edge == RelativeCoordinate::Strings::right) return Expression ((double) parent->getWidth()); diff --git a/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h b/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h index cd06f82402..da97b43b1b 100644 --- a/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h +++ b/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h @@ -169,7 +169,7 @@ public: //============================================================================== /** @internal */ - const Expression getSymbolValue (const String& symbol) const; + const Expression getSymbolValue (const String& symbol, const String& member) const; /** @internal */ void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); /** @internal */ diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 67a42c312d..3d1215c604 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -4632,7 +4632,15 @@ public: class Symbol : public Term { public: - Symbol (const String& symbol_) : symbol (symbol_) {} + explicit Symbol (const String& symbol_) + : mainSymbol (symbol_.upToFirstOccurrenceOf (".", false, false).trim()), + member (symbol_.fromFirstOccurrenceOf (".", false, false).trim()) + {} + + Symbol (const String& symbol_, const String& member_) + : mainSymbol (symbol_), + member (member_) + {} double evaluate (const EvaluationContext& c, int recursionDepth) const { @@ -4641,7 +4649,7 @@ public: try { - return c.getSymbolValue (symbol).term->evaluate (c, recursionDepth); + return c.getSymbolValue (mainSymbol, member).term->evaluate (c, recursionDepth); } catch (...) {} @@ -4649,23 +4657,35 @@ public: return 0; } - Term* clone() const { return new Symbol (symbol); } + Term* clone() const { return new Symbol (mainSymbol, member); } int getNumInputs() const { return 0; } Term* getInput (int) const { return 0; } - const String toString() const { return symbol; } + + const String toString() const + { + return member.isEmpty() ? mainSymbol + : mainSymbol + "." + member; + } bool referencesSymbol (const String& s, const EvaluationContext& c, int recursionDepth) const { - if (s == symbol) + if (s == mainSymbol) return true; if (++recursionDepth > 256) throw EvaluationError ("Recursive symbol references"); - return c.getSymbolValue (symbol).term->referencesSymbol (s, c, recursionDepth); + try + { + return c.getSymbolValue (mainSymbol, member).term->referencesSymbol (s, c, recursionDepth); + } + catch (EvaluationError&) + { + return false; + } } - String symbol; + String mainSymbol, member; }; class Function : public Term @@ -4937,6 +4957,9 @@ public: if (c != 0 && (c->isResolutionTarget || ! mustBeFlagged)) return c; + if (dynamic_cast (term) != 0) + return 0; + int i; const int numIns = term->getNumInputs(); for (i = 0; i < numIns; ++i) @@ -4970,20 +4993,12 @@ public: static bool renameSymbol (Term* const t, const String& oldName, const String& newName) { - Symbol* sym = dynamic_cast (t); + Symbol* const sym = dynamic_cast (t); - if (sym != 0) + if (sym != 0 && sym->mainSymbol == oldName) { - if (sym->symbol == oldName) - { - sym->symbol = newName; - return true; - } - else if (sym->symbol.startsWith (oldName + ".")) - { - sym->symbol = newName + "." + sym->symbol.substring (0, oldName.length() + 1); - return true; - } + sym->mainSymbol = newName; + return true; } bool anyChanged = false; @@ -5109,6 +5124,12 @@ public: textIndex = i; } + if (text[i] == '-') + { + ++i; + skipWhitespace (i); + } + int numDigits = 0; while (isDecimalDigit (text[i])) @@ -5154,9 +5175,9 @@ public: return 0; } - Constant* t = new Constant (String (text + textIndex, i - textIndex).getDoubleValue(), isResolutionTarget); + const int start = textIndex; textIndex = i; - return t; + return new Constant (String (text + start, i - start).getDoubleValue(), isResolutionTarget); } const TermPtr readMultiplyOrDivideExpression() @@ -5386,7 +5407,7 @@ const Expression Expression::adjustedToGiveNewResult (const double targetValue, const Helpers::TermPtr reverseTerm (parent->createTermToEvaluateInput (context, termToAdjust, targetValue, newTerm)); if (reverseTerm == 0) - return Expression(); + return Expression (targetValue); termToAdjust->value = reverseTerm->evaluate (context, 0); } @@ -5396,7 +5417,7 @@ const Expression Expression::adjustedToGiveNewResult (const double targetValue, const Expression Expression::withRenamedSymbol (const String& oldSymbol, const String& newSymbol) const { - jassert (newSymbol.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_.")); + jassert (newSymbol.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_")); Expression newExpression (term->clone()); Helpers::renameSymbol (newExpression.term, oldSymbol, newSymbol); @@ -5454,9 +5475,9 @@ Expression::EvaluationError::EvaluationError (const String& message) Expression::EvaluationContext::EvaluationContext() {} Expression::EvaluationContext::~EvaluationContext() {} -const Expression Expression::EvaluationContext::getSymbolValue (const String& symbol) const +const Expression Expression::EvaluationContext::getSymbolValue (const String& symbol, const String& member) const { - throw EvaluationError ("Unknown symbol: \"" + symbol + "\""); + throw EvaluationError ("Unknown symbol: \"" + symbol + (member.isEmpty() ? "\"" : ("." + member + "\""))); } double Expression::EvaluationContext::evaluateFunction (const String& functionName, const double* parameters, int numParams) const @@ -19550,8 +19571,6 @@ FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool w if (fc.browseForFileToSave (warnAboutOverwritingExistingFiles)) { - setLastDocumentOpened (fc.getResult()); - File chosen (fc.getResult()); if (chosen.getFileExtension().isEmpty()) { @@ -19572,6 +19591,7 @@ FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool w } } + setLastDocumentOpened (chosen); return saveAs (chosen, false, false, true); } @@ -57322,6 +57342,17 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) const int indent = getIndentX(); const int itemW = itemWidth < 0 ? width - indent : itemWidth; + { + g.saveState(); + g.setOrigin (indent, 0); + + if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, + drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) + paintItem (g, itemW, itemHeight); + + g.restoreState(); + } + g.setColour (ownerView->findColour (TreeView::linesColourId)); const float halfH = itemHeight * 0.5f; @@ -57383,17 +57414,6 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) } } - { - g.saveState(); - g.setOrigin (indent, 0); - - if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, - drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) - paintItem (g, itemW, itemHeight); - - g.restoreState(); - } - if (isOpen()) { const Rectangle clip (g.getClipBounds()); @@ -79785,7 +79805,7 @@ const String RelativeCoordinate::toString() const void RelativeCoordinate::renameSymbolIfUsed (const String& oldName, const String& newName, const Expression::EvaluationContext* context) { - jassert (newName.isNotEmpty() && newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_.")); + jassert (newName.isNotEmpty() && newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_")); if (term.referencesSymbol (oldName, *context)) { @@ -86144,9 +86164,9 @@ void DrawableComposite::render (const Drawable::RenderingContext& context) const } } -const Expression DrawableComposite::getSymbolValue (const String& symbol) const +const Expression DrawableComposite::getSymbolValue (const String& symbol, const String& member) const { - jassert (! symbol.containsChar ('.')) // the only symbols available in a Drawable are markers. + jassert (member.isEmpty()) // the only symbols available in a Drawable are markers. int i; for (i = 0; i < markersX.size(); ++i) @@ -86163,7 +86183,7 @@ const Expression DrawableComposite::getSymbolValue (const String& symbol) const return m->position.getExpression(); } - return Expression::EvaluationContext::getSymbolValue (symbol); + return Expression::EvaluationContext::getSymbolValue (symbol, member); } const Rectangle DrawableComposite::getUntransformedBounds (const bool includeMarkers) const diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 3698b5e15b..5fd3de12a1 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 53 +#define JUCE_BUILDNUMBER 54 /** Current Juce version number. @@ -6630,9 +6630,11 @@ public: /** Returns the value of a symbol. If the symbol is unknown, this can throw an Expression::EvaluationError exception. + The member value is set to the part of the symbol that followed the dot, if there is + one, e.g. for "foo.bar", symbol = "foo" and member = "bar". @throws Expression::EvaluationError */ - virtual const Expression getSymbolValue (const String& symbol) const; + virtual const Expression getSymbolValue (const String& symbol, const String& member) const; /** Executes a named function. If the function name is unknown, this can throw an Expression::EvaluationError exception. @@ -59306,7 +59308,7 @@ public: /** @internal */ const Identifier getValueTreeType() const { return valueTreeType; } /** @internal */ - const Expression getSymbolValue (const String& symbol) const; + const Expression getSymbolValue (const String& symbol, const String& member) const; /** Internally-used class for wrapping a DrawableComposite's state into a ValueTree. */ class ValueTreeWrapper : public ValueTreeWrapperBase diff --git a/src/containers/juce_Expression.cpp b/src/containers/juce_Expression.cpp index 03940dac22..3910e73e2a 100644 --- a/src/containers/juce_Expression.cpp +++ b/src/containers/juce_Expression.cpp @@ -70,7 +70,15 @@ public: class Symbol : public Term { public: - Symbol (const String& symbol_) : symbol (symbol_) {} + explicit Symbol (const String& symbol_) + : mainSymbol (symbol_.upToFirstOccurrenceOf (".", false, false).trim()), + member (symbol_.fromFirstOccurrenceOf (".", false, false).trim()) + {} + + Symbol (const String& symbol_, const String& member_) + : mainSymbol (symbol_), + member (member_) + {} double evaluate (const EvaluationContext& c, int recursionDepth) const { @@ -79,7 +87,7 @@ public: try { - return c.getSymbolValue (symbol).term->evaluate (c, recursionDepth); + return c.getSymbolValue (mainSymbol, member).term->evaluate (c, recursionDepth); } catch (...) {} @@ -87,23 +95,35 @@ public: return 0; } - Term* clone() const { return new Symbol (symbol); } + Term* clone() const { return new Symbol (mainSymbol, member); } int getNumInputs() const { return 0; } Term* getInput (int) const { return 0; } - const String toString() const { return symbol; } + + const String toString() const + { + return member.isEmpty() ? mainSymbol + : mainSymbol + "." + member; + } bool referencesSymbol (const String& s, const EvaluationContext& c, int recursionDepth) const { - if (s == symbol) + if (s == mainSymbol) return true; if (++recursionDepth > 256) throw EvaluationError ("Recursive symbol references"); - return c.getSymbolValue (symbol).term->referencesSymbol (s, c, recursionDepth); + try + { + return c.getSymbolValue (mainSymbol, member).term->referencesSymbol (s, c, recursionDepth); + } + catch (EvaluationError&) + { + return false; + } } - String symbol; + String mainSymbol, member; }; //============================================================================== @@ -383,6 +403,9 @@ public: if (c != 0 && (c->isResolutionTarget || ! mustBeFlagged)) return c; + if (dynamic_cast (term) != 0) + return 0; + int i; const int numIns = term->getNumInputs(); for (i = 0; i < numIns; ++i) @@ -416,20 +439,12 @@ public: static bool renameSymbol (Term* const t, const String& oldName, const String& newName) { - Symbol* sym = dynamic_cast (t); + Symbol* const sym = dynamic_cast (t); - if (sym != 0) + if (sym != 0 && sym->mainSymbol == oldName) { - if (sym->symbol == oldName) - { - sym->symbol = newName; - return true; - } - else if (sym->symbol.startsWith (oldName + ".")) - { - sym->symbol = newName + "." + sym->symbol.substring (0, oldName.length() + 1); - return true; - } + sym->mainSymbol = newName; + return true; } bool anyChanged = false; @@ -557,6 +572,12 @@ public: textIndex = i; } + if (text[i] == '-') + { + ++i; + skipWhitespace (i); + } + int numDigits = 0; while (isDecimalDigit (text[i])) @@ -602,9 +623,9 @@ public: return 0; } - Constant* t = new Constant (String (text + textIndex, i - textIndex).getDoubleValue(), isResolutionTarget); + const int start = textIndex; textIndex = i; - return t; + return new Constant (String (text + start, i - start).getDoubleValue(), isResolutionTarget); } const TermPtr readMultiplyOrDivideExpression() @@ -835,7 +856,7 @@ const Expression Expression::adjustedToGiveNewResult (const double targetValue, const Helpers::TermPtr reverseTerm (parent->createTermToEvaluateInput (context, termToAdjust, targetValue, newTerm)); if (reverseTerm == 0) - return Expression(); + return Expression (targetValue); termToAdjust->value = reverseTerm->evaluate (context, 0); } @@ -845,7 +866,7 @@ const Expression Expression::adjustedToGiveNewResult (const double targetValue, const Expression Expression::withRenamedSymbol (const String& oldSymbol, const String& newSymbol) const { - jassert (newSymbol.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_.")); + jassert (newSymbol.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_")); Expression newExpression (term->clone()); Helpers::renameSymbol (newExpression.term, oldSymbol, newSymbol); @@ -906,9 +927,9 @@ Expression::EvaluationError::EvaluationError (const String& message) Expression::EvaluationContext::EvaluationContext() {} Expression::EvaluationContext::~EvaluationContext() {} -const Expression Expression::EvaluationContext::getSymbolValue (const String& symbol) const +const Expression Expression::EvaluationContext::getSymbolValue (const String& symbol, const String& member) const { - throw EvaluationError ("Unknown symbol: \"" + symbol + "\""); + throw EvaluationError ("Unknown symbol: \"" + symbol + (member.isEmpty() ? "\"" : ("." + member + "\""))); } double Expression::EvaluationContext::evaluateFunction (const String& functionName, const double* parameters, int numParams) const diff --git a/src/containers/juce_Expression.h b/src/containers/juce_Expression.h index 0833eb1ed5..d10e894244 100644 --- a/src/containers/juce_Expression.h +++ b/src/containers/juce_Expression.h @@ -113,9 +113,11 @@ public: /** Returns the value of a symbol. If the symbol is unknown, this can throw an Expression::EvaluationError exception. + The member value is set to the part of the symbol that followed the dot, if there is + one, e.g. for "foo.bar", symbol = "foo" and member = "bar". @throws Expression::EvaluationError */ - virtual const Expression getSymbolValue (const String& symbol) const; + virtual const Expression getSymbolValue (const String& symbol, const String& member) const; /** Executes a named function. If the function name is unknown, this can throw an Expression::EvaluationError exception. diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 2f15238317..97a09052a5 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 53 +#define JUCE_BUILDNUMBER 54 /** Current Juce version number. diff --git a/src/gui/components/controls/juce_TreeView.cpp b/src/gui/components/controls/juce_TreeView.cpp index 5287001bb3..86dcf31a28 100644 --- a/src/gui/components/controls/juce_TreeView.cpp +++ b/src/gui/components/controls/juce_TreeView.cpp @@ -1427,6 +1427,17 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) const int indent = getIndentX(); const int itemW = itemWidth < 0 ? width - indent : itemWidth; + { + g.saveState(); + g.setOrigin (indent, 0); + + if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, + drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) + paintItem (g, itemW, itemHeight); + + g.restoreState(); + } + g.setColour (ownerView->findColour (TreeView::linesColourId)); const float halfH = itemHeight * 0.5f; @@ -1489,17 +1500,6 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) } } - { - g.saveState(); - g.setOrigin (indent, 0); - - if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, - drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) - paintItem (g, itemW, itemHeight); - - g.restoreState(); - } - if (isOpen()) { const Rectangle clip (g.getClipBounds()); diff --git a/src/gui/graphics/drawables/juce_DrawableComposite.cpp b/src/gui/graphics/drawables/juce_DrawableComposite.cpp index cf6597b05e..685dca052e 100644 --- a/src/gui/graphics/drawables/juce_DrawableComposite.cpp +++ b/src/gui/graphics/drawables/juce_DrawableComposite.cpp @@ -247,9 +247,9 @@ void DrawableComposite::render (const Drawable::RenderingContext& context) const } } -const Expression DrawableComposite::getSymbolValue (const String& symbol) const +const Expression DrawableComposite::getSymbolValue (const String& symbol, const String& member) const { - jassert (! symbol.containsChar ('.')) // the only symbols available in a Drawable are markers. + jassert (member.isEmpty()) // the only symbols available in a Drawable are markers. int i; for (i = 0; i < markersX.size(); ++i) @@ -266,7 +266,7 @@ const Expression DrawableComposite::getSymbolValue (const String& symbol) const return m->position.getExpression(); } - return Expression::EvaluationContext::getSymbolValue (symbol); + return Expression::EvaluationContext::getSymbolValue (symbol, member); } const Rectangle DrawableComposite::getUntransformedBounds (const bool includeMarkers) const diff --git a/src/gui/graphics/drawables/juce_DrawableComposite.h b/src/gui/graphics/drawables/juce_DrawableComposite.h index 05e7248bb4..d99ab5eacf 100644 --- a/src/gui/graphics/drawables/juce_DrawableComposite.h +++ b/src/gui/graphics/drawables/juce_DrawableComposite.h @@ -201,7 +201,7 @@ public: /** @internal */ const Identifier getValueTreeType() const { return valueTreeType; } /** @internal */ - const Expression getSymbolValue (const String& symbol) const; + const Expression getSymbolValue (const String& symbol, const String& member) const; //============================================================================== /** Internally-used class for wrapping a DrawableComposite's state into a ValueTree. */ diff --git a/src/gui/graphics/geometry/juce_RelativeCoordinate.cpp b/src/gui/graphics/geometry/juce_RelativeCoordinate.cpp index dd87d6c6fc..339e3d38fb 100644 --- a/src/gui/graphics/geometry/juce_RelativeCoordinate.cpp +++ b/src/gui/graphics/geometry/juce_RelativeCoordinate.cpp @@ -185,7 +185,7 @@ const String RelativeCoordinate::toString() const void RelativeCoordinate::renameSymbolIfUsed (const String& oldName, const String& newName, const Expression::EvaluationContext* context) { - jassert (newName.isNotEmpty() && newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_.")); + jassert (newName.isNotEmpty() && newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_")); if (term.referencesSymbol (oldName, *context)) { diff --git a/src/utilities/juce_FileBasedDocument.cpp b/src/utilities/juce_FileBasedDocument.cpp index 5dd172ce16..23b641d189 100644 --- a/src/utilities/juce_FileBasedDocument.cpp +++ b/src/utilities/juce_FileBasedDocument.cpp @@ -263,8 +263,6 @@ FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool w if (fc.browseForFileToSave (warnAboutOverwritingExistingFiles)) { - setLastDocumentOpened (fc.getResult()); - File chosen (fc.getResult()); if (chosen.getFileExtension().isEmpty()) { @@ -285,6 +283,7 @@ FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool w } } + setLastDocumentOpened (chosen); return saveAs (chosen, false, false, true); }