mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-30 02:50:05 +00:00
Documentation fixes. Mac OpenGL fix. PositionableAudioSource tweak. Added new class: Expression, and changed RelativeCoordinate to use an Expression to store its position.
This commit is contained in:
parent
244219bbe2
commit
3e30e09afa
38 changed files with 4301 additions and 2730 deletions
|
|
@ -94,6 +94,7 @@ OBJECTS := \
|
|||
$(OBJDIR)/juce_Synthesiser_2bffa1dd.o \
|
||||
$(OBJDIR)/juce_BigInteger_63589133.o \
|
||||
$(OBJDIR)/juce_DynamicObject_69d02ab3.o \
|
||||
$(OBJDIR)/juce_Expression_1e9a5aad.o \
|
||||
$(OBJDIR)/juce_Identifier_89fa043e.o \
|
||||
$(OBJDIR)/juce_MemoryBlock_edd65761.o \
|
||||
$(OBJDIR)/juce_NamedValueSet_6b0793df.o \
|
||||
|
|
@ -631,6 +632,11 @@ $(OBJDIR)/juce_DynamicObject_69d02ab3.o: ../../src/containers/juce_DynamicObject
|
|||
@echo "Compiling juce_DynamicObject.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/juce_Expression_1e9a5aad.o: ../../src/containers/juce_Expression.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo "Compiling juce_Expression.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/juce_Identifier_89fa043e.o: ../../src/containers/juce_Identifier.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo "Compiling juce_Identifier.cpp"
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
E8DFABC1603D55B97429A8E4 = { isa = PBXBuildFile; fileRef = 35668D8EEA19957C6C9AC83A; };
|
||||
BE25871C34D79FEFFD1B94B6 = { isa = PBXBuildFile; fileRef = 895D742F49DA9F100990879C; };
|
||||
4AB5E55BDF79028F82F83D8E = { isa = PBXBuildFile; fileRef = F77C9170829579FABA5679AD; };
|
||||
25018C91F79D918FEA084630 = { isa = PBXBuildFile; fileRef = 199DFD1C5A282FE13A585FEA; };
|
||||
95577AE91AA6CBA7FE9434F3 = { isa = PBXBuildFile; fileRef = 1CF7CC0EB057F995BBBEFC90; };
|
||||
21BA256CBCC9C15265928A23 = { isa = PBXBuildFile; fileRef = FF40DA899AE16A5E1D8AA54A; };
|
||||
9D2D1BA65C27BDA1F7C44769 = { isa = PBXBuildFile; fileRef = 70E5409425A76782B6188B31; };
|
||||
|
|
@ -481,6 +482,8 @@
|
|||
F77C9170829579FABA5679AD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DynamicObject.cpp; path = ../../src/containers/juce_DynamicObject.cpp; sourceTree = SOURCE_ROOT; };
|
||||
34C402EF9ADCAD34FB657D43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_DynamicObject.h; path = ../../src/containers/juce_DynamicObject.h; sourceTree = SOURCE_ROOT; };
|
||||
7DA9AC75A4D9227C8FC4B2F7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ElementComparator.h; path = ../../src/containers/juce_ElementComparator.h; sourceTree = SOURCE_ROOT; };
|
||||
199DFD1C5A282FE13A585FEA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Expression.cpp; path = ../../src/containers/juce_Expression.cpp; sourceTree = SOURCE_ROOT; };
|
||||
3C12A5E0EBBB0916C01CFC58 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Expression.h; path = ../../src/containers/juce_Expression.h; sourceTree = SOURCE_ROOT; };
|
||||
F364AA2637B7CB89D3657DFF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_HeapBlock.h; path = ../../src/containers/juce_HeapBlock.h; sourceTree = SOURCE_ROOT; };
|
||||
1CF7CC0EB057F995BBBEFC90 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Identifier.cpp; path = ../../src/containers/juce_Identifier.cpp; sourceTree = SOURCE_ROOT; };
|
||||
C16848F86DF014F1CBECE248 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Identifier.h; path = ../../src/containers/juce_Identifier.h; sourceTree = SOURCE_ROOT; };
|
||||
|
|
@ -1195,6 +1198,8 @@
|
|||
F77C9170829579FABA5679AD,
|
||||
34C402EF9ADCAD34FB657D43,
|
||||
7DA9AC75A4D9227C8FC4B2F7,
|
||||
199DFD1C5A282FE13A585FEA,
|
||||
3C12A5E0EBBB0916C01CFC58,
|
||||
F364AA2637B7CB89D3657DFF,
|
||||
1CF7CC0EB057F995BBBEFC90,
|
||||
C16848F86DF014F1CBECE248,
|
||||
|
|
@ -1952,6 +1957,7 @@
|
|||
E8DFABC1603D55B97429A8E4,
|
||||
BE25871C34D79FEFFD1B94B6,
|
||||
4AB5E55BDF79028F82F83D8E,
|
||||
25018C91F79D918FEA084630,
|
||||
95577AE91AA6CBA7FE9434F3,
|
||||
21BA256CBCC9C15265928A23,
|
||||
9D2D1BA65C27BDA1F7C44769,
|
||||
|
|
|
|||
|
|
@ -350,6 +350,8 @@
|
|||
<File RelativePath="..\..\src\containers\juce_DynamicObject.cpp"/>
|
||||
<File RelativePath="..\..\src\containers\juce_DynamicObject.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_ElementComparator.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Expression.cpp"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Expression.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_HeapBlock.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Identifier.cpp"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Identifier.h"/>
|
||||
|
|
|
|||
|
|
@ -350,6 +350,8 @@
|
|||
<File RelativePath="..\..\src\containers\juce_DynamicObject.cpp"/>
|
||||
<File RelativePath="..\..\src\containers\juce_DynamicObject.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_ElementComparator.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Expression.cpp"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Expression.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_HeapBlock.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Identifier.cpp"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Identifier.h"/>
|
||||
|
|
|
|||
|
|
@ -352,6 +352,8 @@
|
|||
<File RelativePath="..\..\src\containers\juce_DynamicObject.cpp"/>
|
||||
<File RelativePath="..\..\src\containers\juce_DynamicObject.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_ElementComparator.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Expression.cpp"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Expression.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_HeapBlock.h"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Identifier.cpp"/>
|
||||
<File RelativePath="..\..\src\containers\juce_Identifier.h"/>
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@
|
|||
<ClCompile Include="..\..\src\audio\synthesisers\juce_Synthesiser.cpp"/>
|
||||
<ClCompile Include="..\..\src\containers\juce_BigInteger.cpp"/>
|
||||
<ClCompile Include="..\..\src\containers\juce_DynamicObject.cpp"/>
|
||||
<ClCompile Include="..\..\src\containers\juce_Expression.cpp"/>
|
||||
<ClCompile Include="..\..\src\containers\juce_Identifier.cpp"/>
|
||||
<ClCompile Include="..\..\src\containers\juce_MemoryBlock.cpp"/>
|
||||
<ClCompile Include="..\..\src\containers\juce_NamedValueSet.cpp"/>
|
||||
|
|
@ -502,6 +503,7 @@
|
|||
<ClInclude Include="..\..\src\containers\juce_BigInteger.h"/>
|
||||
<ClInclude Include="..\..\src\containers\juce_DynamicObject.h"/>
|
||||
<ClInclude Include="..\..\src\containers\juce_ElementComparator.h"/>
|
||||
<ClInclude Include="..\..\src\containers\juce_Expression.h"/>
|
||||
<ClInclude Include="..\..\src\containers\juce_HeapBlock.h"/>
|
||||
<ClInclude Include="..\..\src\containers\juce_Identifier.h"/>
|
||||
<ClInclude Include="..\..\src\containers\juce_MemoryBlock.h"/>
|
||||
|
|
|
|||
|
|
@ -379,6 +379,9 @@
|
|||
<ClCompile Include="..\..\src\containers\juce_DynamicObject.cpp">
|
||||
<Filter>Juce\Source\containers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\containers\juce_Expression.cpp">
|
||||
<Filter>Juce\Source\containers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\containers\juce_Identifier.cpp">
|
||||
<Filter>Juce\Source\containers</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -1428,6 +1431,9 @@
|
|||
<ClInclude Include="..\..\src\containers\juce_ElementComparator.h">
|
||||
<Filter>Juce\Source\containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\containers\juce_Expression.h">
|
||||
<Filter>Juce\Source\containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\containers\juce_HeapBlock.h">
|
||||
<Filter>Juce\Source\containers</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
E8DFABC1603D55B97429A8E4 = { isa = PBXBuildFile; fileRef = 35668D8EEA19957C6C9AC83A; };
|
||||
BE25871C34D79FEFFD1B94B6 = { isa = PBXBuildFile; fileRef = 895D742F49DA9F100990879C; };
|
||||
4AB5E55BDF79028F82F83D8E = { isa = PBXBuildFile; fileRef = F77C9170829579FABA5679AD; };
|
||||
25018C91F79D918FEA084630 = { isa = PBXBuildFile; fileRef = 199DFD1C5A282FE13A585FEA; };
|
||||
95577AE91AA6CBA7FE9434F3 = { isa = PBXBuildFile; fileRef = 1CF7CC0EB057F995BBBEFC90; };
|
||||
21BA256CBCC9C15265928A23 = { isa = PBXBuildFile; fileRef = FF40DA899AE16A5E1D8AA54A; };
|
||||
9D2D1BA65C27BDA1F7C44769 = { isa = PBXBuildFile; fileRef = 70E5409425A76782B6188B31; };
|
||||
|
|
@ -481,6 +482,8 @@
|
|||
F77C9170829579FABA5679AD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DynamicObject.cpp; path = ../../src/containers/juce_DynamicObject.cpp; sourceTree = SOURCE_ROOT; };
|
||||
34C402EF9ADCAD34FB657D43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_DynamicObject.h; path = ../../src/containers/juce_DynamicObject.h; sourceTree = SOURCE_ROOT; };
|
||||
7DA9AC75A4D9227C8FC4B2F7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ElementComparator.h; path = ../../src/containers/juce_ElementComparator.h; sourceTree = SOURCE_ROOT; };
|
||||
199DFD1C5A282FE13A585FEA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Expression.cpp; path = ../../src/containers/juce_Expression.cpp; sourceTree = SOURCE_ROOT; };
|
||||
3C12A5E0EBBB0916C01CFC58 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Expression.h; path = ../../src/containers/juce_Expression.h; sourceTree = SOURCE_ROOT; };
|
||||
F364AA2637B7CB89D3657DFF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_HeapBlock.h; path = ../../src/containers/juce_HeapBlock.h; sourceTree = SOURCE_ROOT; };
|
||||
1CF7CC0EB057F995BBBEFC90 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Identifier.cpp; path = ../../src/containers/juce_Identifier.cpp; sourceTree = SOURCE_ROOT; };
|
||||
C16848F86DF014F1CBECE248 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Identifier.h; path = ../../src/containers/juce_Identifier.h; sourceTree = SOURCE_ROOT; };
|
||||
|
|
@ -1195,6 +1198,8 @@
|
|||
F77C9170829579FABA5679AD,
|
||||
34C402EF9ADCAD34FB657D43,
|
||||
7DA9AC75A4D9227C8FC4B2F7,
|
||||
199DFD1C5A282FE13A585FEA,
|
||||
3C12A5E0EBBB0916C01CFC58,
|
||||
F364AA2637B7CB89D3657DFF,
|
||||
1CF7CC0EB057F995BBBEFC90,
|
||||
C16848F86DF014F1CBECE248,
|
||||
|
|
@ -1952,6 +1957,7 @@
|
|||
E8DFABC1603D55B97429A8E4,
|
||||
BE25871C34D79FEFFD1B94B6,
|
||||
4AB5E55BDF79028F82F83D8E,
|
||||
25018C91F79D918FEA084630,
|
||||
95577AE91AA6CBA7FE9434F3,
|
||||
21BA256CBCC9C15265928A23,
|
||||
9D2D1BA65C27BDA1F7C44769,
|
||||
|
|
|
|||
|
|
@ -359,6 +359,10 @@
|
|||
file="src/containers/juce_DynamicObject.h"/>
|
||||
<FILE id="RNHQjBFmS" name="juce_ElementComparator.h" compile="0" resource="0"
|
||||
file="src/containers/juce_ElementComparator.h"/>
|
||||
<FILE id="01ekjVT" name="juce_Expression.cpp" compile="1" resource="0"
|
||||
file="src/containers/juce_Expression.cpp"/>
|
||||
<FILE id="MpE62KG" name="juce_Expression.h" compile="0" resource="0"
|
||||
file="src/containers/juce_Expression.h"/>
|
||||
<FILE id="ssHjnrvya" name="juce_HeapBlock.h" compile="0" resource="0"
|
||||
file="src/containers/juce_HeapBlock.h"/>
|
||||
<FILE id="3Wo76GZwg" name="juce_Identifier.cpp" compile="1" resource="0"
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@
|
|||
#include "../src/containers/juce_Variant.cpp"
|
||||
#include "../src/containers/juce_NamedValueSet.cpp"
|
||||
#include "../src/containers/juce_DynamicObject.cpp"
|
||||
#include "../src/containers/juce_Expression.cpp"
|
||||
#include "../src/cryptography/juce_BlowFish.cpp"
|
||||
#include "../src/cryptography/juce_MD5.cpp"
|
||||
#include "../src/cryptography/juce_Primes.cpp"
|
||||
|
|
|
|||
|
|
@ -333,12 +333,15 @@ void RelativeRectangleLayoutManager::applyLayout()
|
|||
}
|
||||
}
|
||||
|
||||
const RelativeCoordinate RelativeRectangleLayoutManager::findNamedCoordinate (const String& objectName, const String& edge) const
|
||||
const Expression RelativeRectangleLayoutManager::getSymbolValue (const String& symbol) 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 RelativeCoordinate ((double) parent->getWidth());
|
||||
if (edge == RelativeCoordinate::Strings::bottom) return RelativeCoordinate ((double) parent->getHeight());
|
||||
if (edge == RelativeCoordinate::Strings::right) return Expression ((double) parent->getWidth());
|
||||
if (edge == RelativeCoordinate::Strings::bottom) return Expression ((double) parent->getHeight());
|
||||
}
|
||||
|
||||
if (objectName.isNotEmpty() && edge.isNotEmpty())
|
||||
|
|
@ -349,10 +352,10 @@ const RelativeCoordinate RelativeRectangleLayoutManager::findNamedCoordinate (co
|
|||
|
||||
if (c->name == objectName)
|
||||
{
|
||||
if (edge == RelativeCoordinate::Strings::left) return c->coords.left;
|
||||
if (edge == RelativeCoordinate::Strings::right) return c->coords.right;
|
||||
if (edge == RelativeCoordinate::Strings::top) return c->coords.top;
|
||||
if (edge == RelativeCoordinate::Strings::bottom) return c->coords.bottom;
|
||||
if (edge == RelativeCoordinate::Strings::left) return c->coords.left.getTerm();
|
||||
if (edge == RelativeCoordinate::Strings::right) return c->coords.right.getTerm();
|
||||
if (edge == RelativeCoordinate::Strings::top) return c->coords.top.getTerm();
|
||||
if (edge == RelativeCoordinate::Strings::bottom) return c->coords.bottom.getTerm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -362,10 +365,10 @@ const RelativeCoordinate RelativeRectangleLayoutManager::findNamedCoordinate (co
|
|||
MarkerPosition* m = markers.getUnchecked(i);
|
||||
|
||||
if (m->markerName == objectName)
|
||||
return m->position;
|
||||
return m->position.getTerm();
|
||||
}
|
||||
|
||||
return RelativeCoordinate();
|
||||
return Expression();
|
||||
}
|
||||
|
||||
void RelativeRectangleLayoutManager::componentMovedOrResized (Component& component, bool wasMoved, bool wasResized)
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ private:
|
|||
/**
|
||||
*/
|
||||
class RelativeRectangleLayoutManager : public ComponentListener,
|
||||
public RelativeCoordinate::NamedCoordinateFinder,
|
||||
public Expression::EvaluationContext,
|
||||
public AsyncUpdater
|
||||
{
|
||||
public:
|
||||
|
|
@ -169,7 +169,7 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
const RelativeCoordinate findNamedCoordinate (const String& objectName, const String& edge) const;
|
||||
const Expression getSymbolValue (const String& symbol) const;
|
||||
/** @internal */
|
||||
void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized);
|
||||
/** @internal */
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
/** This is the editor component that our filter will display.
|
||||
*/
|
||||
class JuceDemoPluginAudioProcessorEditor : public AudioProcessorEditor,
|
||||
public Slider::Listener,
|
||||
public SliderListener,
|
||||
public Timer
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
1458
juce_amalgamated.cpp
1458
juce_amalgamated.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -64,7 +64,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 49
|
||||
#define JUCE_BUILDNUMBER 50
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
@ -536,7 +536,7 @@
|
|||
|
||||
@see Logger::outputDebugString
|
||||
*/
|
||||
#define DBG(dbgtext) { String tempDbgBuf; tempDbgBuf << dbgtext; JUCE_NAMESPACE::Logger::outputDebugString (tempDbgBuf); }
|
||||
#define DBG(dbgtext) { JUCE_NAMESPACE::String tempDbgBuf; tempDbgBuf << dbgtext; JUCE_NAMESPACE::Logger::outputDebugString (tempDbgBuf); }
|
||||
|
||||
// Assertions..
|
||||
|
||||
|
|
@ -6370,23 +6370,11 @@ private:
|
|||
#ifndef __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_HEAPBLOCK_JUCEHEADER__
|
||||
#ifndef __JUCE_EXPRESSION_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_IDENTIFIER_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_MEMORYBLOCK_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_NAMEDVALUESET_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_OWNEDARRAY_JUCEHEADER__
|
||||
|
||||
/*** Start of inlined file: juce_OwnedArray.h ***/
|
||||
#ifndef __JUCE_OWNEDARRAY_JUCEHEADER__
|
||||
#define __JUCE_OWNEDARRAY_JUCEHEADER__
|
||||
/*** Start of inlined file: juce_Expression.h ***/
|
||||
#ifndef __JUCE_EXPRESSION_JUCEHEADER__
|
||||
#define __JUCE_EXPRESSION_JUCEHEADER__
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_ScopedPointer.h ***/
|
||||
|
|
@ -6562,6 +6550,206 @@ inline bool operator!= (const ScopedPointer<ObjectType>& pointer1, const ObjectT
|
|||
#endif // __JUCE_SCOPEDPOINTER_JUCEHEADER__
|
||||
/*** End of inlined file: juce_ScopedPointer.h ***/
|
||||
|
||||
/**
|
||||
A class for dynamically evaluating simple numeric expressions.
|
||||
|
||||
This class can parse a simple C-style string expression involving floating point
|
||||
numbers, named symbols and functions. The basic arithmetic operations of +, -, *, /
|
||||
are supported, as well as parentheses, and any alphanumeric identifiers are
|
||||
assumed to be named symbols which will be resolved when the expression is
|
||||
evaluated.
|
||||
|
||||
Expressions which use identifiers and functions require a subclass of
|
||||
Expression::EvaluationContext 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.
|
||||
*/
|
||||
class JUCE_API Expression
|
||||
{
|
||||
public:
|
||||
|
||||
/** Creates a simple expression with a value of 0. */
|
||||
Expression();
|
||||
|
||||
/** Destructor. */
|
||||
~Expression();
|
||||
|
||||
/** Creates a simple expression with a specified constant value. */
|
||||
explicit Expression (const double constant);
|
||||
|
||||
/** Creates a copy of an expression. */
|
||||
Expression (const Expression& other);
|
||||
|
||||
/** Copies another expression. */
|
||||
Expression& operator= (const Expression& other);
|
||||
|
||||
/** Creates an expression by parsing a string.
|
||||
If there's a syntax error in the string, this will throw a ParseError exception.
|
||||
@throws ParseError
|
||||
*/
|
||||
explicit Expression (const String& stringToParse);
|
||||
|
||||
/** Returns a string version of the expression. */
|
||||
const String toString() const;
|
||||
|
||||
/** Returns an expression which is an addtion operation of two existing expressions. */
|
||||
const Expression operator+ (const Expression& other) const;
|
||||
/** Returns an expression which is a subtraction operation of two existing expressions. */
|
||||
const Expression operator- (const Expression& other) const;
|
||||
/** Returns an expression which is a multiplication operation of two existing expressions. */
|
||||
const Expression operator* (const Expression& other) const;
|
||||
/** Returns an expression which is a division operation of two existing expressions. */
|
||||
const Expression operator/ (const Expression& other) const;
|
||||
/** Returns an expression which is a negation operation of two existing expressions. */
|
||||
const Expression operator-() const;
|
||||
|
||||
/** Returns an Expression which is an identifier reference. */
|
||||
static const Expression symbol (const String& symbol);
|
||||
|
||||
/** Returns an Expression which is a function call. */
|
||||
static const Expression function (const String& functionName, const Array<Expression>& parameters);
|
||||
|
||||
/** Returns an Expression which parses a string from a specified character index.
|
||||
|
||||
The index value is incremented so that on return, it indicates the character that follows
|
||||
the end of the expression that was parsed.
|
||||
|
||||
If there's a syntax error in the string, this will throw a ParseError exception.
|
||||
@throws ParseError
|
||||
*/
|
||||
static const Expression parse (const String& stringToParse, int& textIndexToStartFrom);
|
||||
|
||||
/** When evaluating an Expression object, this class is used to resolve symbols and
|
||||
perform functions that the expression uses.
|
||||
*/
|
||||
class EvaluationContext
|
||||
{
|
||||
public:
|
||||
EvaluationContext();
|
||||
virtual ~EvaluationContext();
|
||||
|
||||
/** Returns the value of a symbol.
|
||||
If the symbol is unknown, this can throw an Expression::EvaluationError exception.
|
||||
@throws Expression::EvaluationError
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
/** Evaluates this expression, without using an EvaluationContext.
|
||||
Without an EvaluationContext, no symbols can be used, and only basic functions such as sin, cos, tan,
|
||||
min, max are available.
|
||||
*/
|
||||
double evaluate() const;
|
||||
|
||||
/** Evaluates this expression, providing a context that should be able to evaluate any symbols
|
||||
or functions that it uses.
|
||||
*/
|
||||
double evaluate (const EvaluationContext& context) 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.
|
||||
*/
|
||||
const Expression adjustedToGiveNewResult (double targetValue, const EvaluationContext& context) const;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Returns true if this expression makes use of the specified symbol.
|
||||
If a suitable context 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.
|
||||
*/
|
||||
bool referencesSymbol (const String& symbol, const EvaluationContext& context) const;
|
||||
|
||||
/** Returns true if this expression contains any symbols. */
|
||||
bool usesAnySymbols() const;
|
||||
|
||||
/** An exception that can be thrown by Expression::parse(). */
|
||||
class ParseError : public std::exception
|
||||
{
|
||||
public:
|
||||
ParseError (const String& message);
|
||||
|
||||
String description;
|
||||
};
|
||||
|
||||
/** An exception that can be thrown by Expression::evaluate(). */
|
||||
class EvaluationError : public std::exception
|
||||
{
|
||||
public:
|
||||
EvaluationError (const String& message);
|
||||
|
||||
String description;
|
||||
};
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
class Helpers;
|
||||
friend class Helpers;
|
||||
|
||||
class Term : public ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
Term() {}
|
||||
virtual ~Term() {}
|
||||
|
||||
virtual Term* clone() const = 0;
|
||||
virtual double evaluate (const EvaluationContext&, int recursionDepth) const = 0;
|
||||
virtual int getNumInputs() const = 0;
|
||||
virtual Term* getInput (int index) const = 0;
|
||||
virtual int getInputIndexFor (const Term* possibleInput) const;
|
||||
virtual const String toString() const = 0;
|
||||
virtual int getOperatorPrecedence() const;
|
||||
virtual bool referencesSymbol (const String& symbol, const EvaluationContext&, int recursionDepth) const;
|
||||
virtual const ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const EvaluationContext&, Term* inputTerm,
|
||||
double overallTarget, Term* topLevelTerm) const;
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
Term (const Term& other);
|
||||
Term& operator= (const Term&);
|
||||
};
|
||||
|
||||
friend class ScopedPointer<Term>;
|
||||
ReferenceCountedObjectPtr<Term> term;
|
||||
|
||||
explicit Expression (Term* term);
|
||||
};
|
||||
|
||||
#endif // __JUCE_EXPRESSION_JUCEHEADER__
|
||||
/*** End of inlined file: juce_Expression.h ***/
|
||||
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_HEAPBLOCK_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_IDENTIFIER_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_MEMORYBLOCK_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_NAMEDVALUESET_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_OWNEDARRAY_JUCEHEADER__
|
||||
|
||||
/*** Start of inlined file: juce_OwnedArray.h ***/
|
||||
#ifndef __JUCE_OWNEDARRAY_JUCEHEADER__
|
||||
#define __JUCE_OWNEDARRAY_JUCEHEADER__
|
||||
|
||||
/** An array designed for holding objects.
|
||||
|
||||
This holds a list of pointers to objects, and will automatically
|
||||
|
|
@ -29868,6 +30056,15 @@ struct JUCE_API AudioSourceChannelInfo
|
|||
/**
|
||||
Base class for objects that can produce a continuous stream of audio.
|
||||
|
||||
An AudioSource has two states: 'prepared' and 'unprepared'.
|
||||
|
||||
When a source needs to be played, it is first put into a 'prepared' state by a call to
|
||||
prepareToPlay(), and then repeated calls will be made to its getNextAudioBlock() method to
|
||||
process the audio data.
|
||||
|
||||
Once playback has finished, the releaseResources() method is called to put the stream
|
||||
back into an 'unprepared' state.
|
||||
|
||||
@see AudioFormatReaderSource, ResamplingAudioSource
|
||||
*/
|
||||
class JUCE_API AudioSource
|
||||
|
|
@ -29883,7 +30080,14 @@ public:
|
|||
|
||||
/** Tells the source to prepare for playing.
|
||||
|
||||
The source can use this opportunity to initialise anything it needs to.
|
||||
An AudioSource has two states: prepared and unprepared.
|
||||
|
||||
The prepareToPlay() method is guaranteed to be called at least once on an 'unpreprared'
|
||||
source to put it into a 'prepared' state before any calls will be made to getNextAudioBlock().
|
||||
This callback allows the source to initialise any resources it might need when playing.
|
||||
|
||||
Once playback has finished, the releaseResources() method is called to put the stream
|
||||
back into an 'unprepared' state.
|
||||
|
||||
Note that this method could be called more than once in succession without
|
||||
a matching call to releaseResources(), so make sure your code is robust and
|
||||
|
|
@ -31295,6 +31499,9 @@ public:
|
|||
|
||||
/** Returns true if this source is actually playing in a loop. */
|
||||
virtual bool isLooping() const = 0;
|
||||
|
||||
/** Tells the source whether you'd like it to play in a loop. */
|
||||
virtual void setLooping (bool shouldLoop) { (void) shouldLoop; }
|
||||
};
|
||||
|
||||
#endif // __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__
|
||||
|
|
@ -31329,7 +31536,7 @@ public:
|
|||
|
||||
@see isLooping
|
||||
*/
|
||||
void setLooping (const bool shouldLoop) throw();
|
||||
void setLooping (bool shouldLoop);
|
||||
|
||||
/** Returns whether loop-mode is turned on or not. */
|
||||
bool isLooping() const { return looping; }
|
||||
|
|
@ -36616,7 +36823,8 @@ public:
|
|||
|
||||
@param newItemText the text of the item to show in the list
|
||||
@param newItemId an associated ID number that can be set or retrieved - see
|
||||
getSelectedId() and setSelectedId()
|
||||
getSelectedId() and setSelectedId(). Note that this value can not
|
||||
be 0!
|
||||
@see setItemEnabled, addSeparator, addSectionHeading, removeItem, getNumItems, getItemText, getItemId
|
||||
*/
|
||||
void addItem (const String& newItemText,
|
||||
|
|
@ -42813,21 +43021,7 @@ private:
|
|||
#define __JUCE_RELATIVECOORDINATE_JUCEHEADER__
|
||||
|
||||
/**
|
||||
Expresses a coordinate as an absolute or proportional distance from other
|
||||
named coordinates.
|
||||
|
||||
A RelativeCoordinate represents a position as either:
|
||||
- an absolute distance from the origin
|
||||
- an absolute distance from another named RelativeCoordinate
|
||||
- a proportion of the distance between two other named RelativeCoordinates
|
||||
|
||||
Of course, the coordinates that this one is relative to may themselves be relative
|
||||
to other coordinates, so complex arrangements can be built up (as long as you're careful
|
||||
not to create recursive loops!)
|
||||
|
||||
Rather than keeping pointers to the coordinates that this one is dependent on, it
|
||||
stores their names, and when resolving this coordinate to an absolute value, a
|
||||
NamedCoordinateFinder class is required to retrieve these coordinates by name.
|
||||
Expresses a coordinate as a dynamically evaluated expression.
|
||||
|
||||
@see RelativePoint, RelativeRectangle
|
||||
*/
|
||||
|
|
@ -42837,6 +43031,9 @@ public:
|
|||
|
||||
/** Creates a zero coordinate. */
|
||||
RelativeCoordinate();
|
||||
RelativeCoordinate (const Expression& expression);
|
||||
RelativeCoordinate (const RelativeCoordinate& other);
|
||||
RelativeCoordinate& operator= (const RelativeCoordinate& other);
|
||||
|
||||
/** Creates an absolute position from the parent origin on either the X or Y axis.
|
||||
|
||||
|
|
@ -42844,52 +43041,16 @@ public:
|
|||
*/
|
||||
RelativeCoordinate (double absoluteDistanceFromOrigin);
|
||||
|
||||
/** Creates an absolute position relative to a named coordinate.
|
||||
|
||||
@param absoluteDistanceFromAnchor the distance to add to the named anchor point
|
||||
@param anchorPoint the name of the coordinate from which this one will be relative. See the constructor
|
||||
notes for a description of the syntax for coordinate names.
|
||||
*/
|
||||
RelativeCoordinate (double absoluteDistanceFromAnchor, const String& anchorPoint);
|
||||
|
||||
/** Creates a relative position between two named points.
|
||||
|
||||
@param relativeProportionBetweenAnchors a value between 0 and 1 indicating this coordinate's relative position
|
||||
between anchorPoint1 and anchorPoint2.
|
||||
@param anchorPoint1 the name of the first coordinate from which this one will be relative. See the constructor
|
||||
notes for a description of the syntax for coordinate names.
|
||||
@param anchorPoint2 the name of the first coordinate from which this one will be relative. See the constructor
|
||||
notes for a description of the syntax for coordinate names.
|
||||
*/
|
||||
RelativeCoordinate (double relativeProportionBetweenAnchors, const String& anchorPoint1, const String& anchorPoint2);
|
||||
|
||||
/** Recreates a coordinate from a string description.
|
||||
|
||||
The string can be in one of the following formats:
|
||||
- "123" = 123 pixels from parent origin (this is equivalent to "parent.left + 123"
|
||||
or "parent.top + 123", depending on which axis the coordinate is using)
|
||||
- "anchor" = the same position as the coordinate named "anchor"
|
||||
- "anchor + 123" = the coordinate named "anchor" + 123 pixels
|
||||
- "anchor - 123" = the coordinate named "anchor" - 123 pixels
|
||||
- "50%" = 50% of the distance between the coordinate space's top-left origin and its extent
|
||||
(this is equivalent to "50% * parent.left -> parent.right" or "50% * parent.top -> parent.bottom")
|
||||
- "50% * anchor" = 50% of the distance between the coordinate space's origin and the coordinate named "anchor"
|
||||
(this is equivalent to "50% * parent.left -> anchor" or "50% * parent.top -> anchor")
|
||||
- "50% * anchor1 -> anchor2" = 50% of the distance between the coordinate "anchor1" and the coordinate "anchor2"
|
||||
The string will be parsed by ExpressionParser::parse().
|
||||
|
||||
An anchor name can either be just a single identifier (letters, digits and underscores only - no spaces),
|
||||
e.g. "marker1", or it can be a two-part name in the form "objectName.edge". For example "parent.left" is
|
||||
the origin, or "myComponent.top" is the top edge of a component called "myComponent". The exact names that
|
||||
will be recognised are dependent on the NamedCoordinateFinder that you provide for looking them up, but
|
||||
"parent.left" and "parent.top" are always available, meaning the origin. "parent.right" and "parent.bottom"
|
||||
may also be available if the coordinate space has a fixed size.
|
||||
|
||||
@param stringVersion the string to parse
|
||||
@param stringVersion the expression to use
|
||||
@param isHorizontal this must be true if this is an X coordinate, or false if it's on the Y axis.
|
||||
|
||||
@see toString
|
||||
*/
|
||||
RelativeCoordinate (const String& stringVersion, bool isHorizontal);
|
||||
RelativeCoordinate (const String& stringVersion);
|
||||
|
||||
/** Destructor. */
|
||||
~RelativeCoordinate();
|
||||
|
|
@ -42897,44 +43058,20 @@ public:
|
|||
bool operator== (const RelativeCoordinate& other) const throw();
|
||||
bool operator!= (const RelativeCoordinate& other) const throw();
|
||||
|
||||
/**
|
||||
Provides an interface for looking up the position of a named anchor when resolving a RelativeCoordinate.
|
||||
|
||||
When using RelativeCoordinates, to resolve their names you need to provide a subclass of this which
|
||||
can retrieve a coordinate by name.
|
||||
*/
|
||||
class JUCE_API NamedCoordinateFinder
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~NamedCoordinateFinder() {}
|
||||
|
||||
/** Returns the coordinate for a given name.
|
||||
|
||||
The objectName parameter will be the first section of the name, and the edge the name of the second part.
|
||||
E.g. for "parent.right", objectName would be "parent" and edge would be "right". If the name
|
||||
has no dot, the edge parameter will be an empty string.
|
||||
|
||||
This method must be able to resolve "parent.left", "parent.top", "parent.right" and "parent.bottom", as
|
||||
well as any other objects that your application uses.
|
||||
*/
|
||||
virtual const RelativeCoordinate findNamedCoordinate (const String& objectName, const String& edge) const = 0;
|
||||
};
|
||||
|
||||
/** Calculates the absolute position of this coordinate.
|
||||
|
||||
You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may
|
||||
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
double resolve (const NamedCoordinateFinder* nameFinder) const;
|
||||
double resolve (const Expression::EvaluationContext* evaluationContext) 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 NamedCoordinateFinder* nameFinder) const;
|
||||
bool references (const String& coordName, const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Returns true if there's a recursive loop when trying to resolve this coordinate's position. */
|
||||
bool isRecursive (const NamedCoordinateFinder* nameFinder) const;
|
||||
bool isRecursive (const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Returns true if this coordinate depends on any other coordinates for its position. */
|
||||
bool isDynamic() const;
|
||||
|
|
@ -42945,62 +43082,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 NamedCoordinateFinder* nameFinder);
|
||||
|
||||
/** Returns true if the coordinate is calculated as a proportion of the distance between two other points.
|
||||
@see toggleProportionality
|
||||
*/
|
||||
bool isProportional() const throw() { return anchor2.isNotEmpty(); }
|
||||
|
||||
/** Toggles the coordinate between using a proportional or absolute position.
|
||||
Note that calling this will reset the names of any anchor points, and just make the
|
||||
coordinate relative to the parent origin and parent size.
|
||||
*/
|
||||
void toggleProportionality (const NamedCoordinateFinder* nameFinder,
|
||||
const String& proportionalAnchor1, const String& proportionalAnchor2);
|
||||
|
||||
/** Returns a value that can be edited to set this coordinate's position.
|
||||
The meaning of this number depends on the coordinate's mode. If the coordinate is
|
||||
proportional, the number will be a percentage between 0 and 100. If the
|
||||
coordinate is absolute, then it will be the number of pixels from its anchor point.
|
||||
@see setEditableNumber
|
||||
*/
|
||||
const double getEditableNumber() const;
|
||||
|
||||
/** Sets the value that controls this coordinate's position.
|
||||
The meaning of this number depends on the coordinate's mode. If the coordinate is
|
||||
proportional, the number must be a percentage between 0 and 100. If the
|
||||
coordinate is absolute, then it indicates the number of pixels from its anchor point.
|
||||
@see setEditableNumber
|
||||
*/
|
||||
void setEditableNumber (const double newValue);
|
||||
|
||||
/** Returns the name of the first anchor point from which this coordinate is relative.
|
||||
*/
|
||||
const String getAnchorName1 (const String& returnValueIfOrigin) const;
|
||||
|
||||
/** Returns the name of the second anchor point from which this coordinate is relative.
|
||||
The second anchor is only valid if the coordinate is in proportional mode.
|
||||
*/
|
||||
const String getAnchorName2 (const String& returnValueIfOrigin) const;
|
||||
|
||||
/** Returns the first anchor point as a coordinate. */
|
||||
const RelativeCoordinate getAnchorCoordinate1() const;
|
||||
|
||||
/** Returns the first anchor point as a coordinate.
|
||||
The second anchor is only valid if the coordinate is in proportional mode.
|
||||
*/
|
||||
const RelativeCoordinate getAnchorCoordinate2() const;
|
||||
|
||||
/** Changes the first anchor point, keeping the resultant position of this coordinate in
|
||||
the same place it was previously.
|
||||
*/
|
||||
void changeAnchor1 (const String& newAnchor, const NamedCoordinateFinder* nameFinder);
|
||||
|
||||
/** Changes the second anchor point, keeping the resultant position of this coordinate in
|
||||
the same place it was previously.
|
||||
*/
|
||||
void changeAnchor2 (const String& newAnchor, const NamedCoordinateFinder* nameFinder);
|
||||
void moveToAbsolute (double absoluteTargetPosition, const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Tells the coordinate that an object is changing its name or being deleted.
|
||||
|
||||
|
|
@ -43009,8 +43091,11 @@ public:
|
|||
this coordinate was using it, the coordinate is changed to be relative to the origin
|
||||
instead.
|
||||
*/
|
||||
void renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const NamedCoordinateFinder* nameFinder);
|
||||
void renameSymbolIfUsed (const String& oldName, const String& newName,
|
||||
const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Returns the expression that defines this coordinate. */
|
||||
const Expression& getExpression() const { return term; }
|
||||
|
||||
/** Returns a string which represents this coordinate.
|
||||
For details of the string syntax, see the constructor notes.
|
||||
|
|
@ -43039,11 +43124,10 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
String anchor1, anchor2;
|
||||
double value;
|
||||
Expression term;
|
||||
|
||||
double resolve (const NamedCoordinateFinder* nameFinder, int recursionCounter) const;
|
||||
static double resolveAnchor (const String& anchorName, const NamedCoordinateFinder* nameFinder, int recursionCounter);
|
||||
// double resolve (const Expression::EvaluationContext* evaluationContext, int recursionCounter) const;
|
||||
// static double resolveAnchor (const String& anchorName, const Expression::EvaluationContext* evaluationContext, int recursionCounter);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -43078,10 +43162,10 @@ public:
|
|||
|
||||
/** Calculates the absolute position of this point.
|
||||
|
||||
You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may
|
||||
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
const Point<float> resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
const Point<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Changes the values of this point's coordinates to make it resolve to the specified position.
|
||||
|
||||
|
|
@ -43089,7 +43173,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 RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
void moveToAbsolute (const Point<float>& newPos, const Expression::EvaluationContext* 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
|
||||
|
|
@ -43101,8 +43185,8 @@ public:
|
|||
/** Tells the point that an object is changing its name or being deleted.
|
||||
This calls RelativeCoordinate::renameAnchorIfUsed() on its X and Y coordinates.
|
||||
*/
|
||||
void renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
void renameSymbolIfUsed (const String& oldName, const String& newName,
|
||||
const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Returns true if this point depends on any other coordinates for its position. */
|
||||
bool isDynamic() const;
|
||||
|
|
@ -43145,10 +43229,10 @@ public:
|
|||
|
||||
/** Calculates the absolute position of this rectangle.
|
||||
|
||||
You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may
|
||||
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
const Rectangle<float> resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
const Rectangle<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Changes the values of this rectangle's coordinates to make it resolve to the specified position.
|
||||
|
||||
|
|
@ -43156,7 +43240,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 RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
void moveToAbsolute (const Rectangle<float>& newPos, const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Returns a string which represents this point.
|
||||
This returns a comma-separated list of coordinates, in the order left, top, right, bottom. For details of
|
||||
|
|
@ -43166,10 +43250,10 @@ public:
|
|||
const String toString() const;
|
||||
|
||||
/** Tells the rectangle that an object is changing its name or being deleted.
|
||||
This calls RelativeCoordinate::renameAnchorIfUsed() on the rectangle's coordinates.
|
||||
This calls RelativeCoordinate::renameSymbolIfUsed() on the rectangle's coordinates.
|
||||
*/
|
||||
void renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
void renameSymbolIfUsed (const String& oldName, const String& newName,
|
||||
const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
// The actual rectangle coords...
|
||||
RelativeCoordinate left, right, top, bottom;
|
||||
|
|
@ -43194,7 +43278,7 @@ public:
|
|||
~RelativePointPath();
|
||||
|
||||
/** Resolves this points in this path and adds them to a normal Path object. */
|
||||
void createPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder);
|
||||
void createPath (Path& path, Expression::EvaluationContext* coordFinder);
|
||||
|
||||
/** Returns true if the path contains any non-fixed points. */
|
||||
bool containsAnyDynamicPoints() const;
|
||||
|
|
@ -43226,7 +43310,7 @@ public:
|
|||
ElementBase (ElementType type);
|
||||
virtual ~ElementBase() {}
|
||||
virtual const ValueTree createTree() const = 0;
|
||||
virtual void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const = 0;
|
||||
virtual void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const = 0;
|
||||
virtual RelativePoint* getControlPoints (int& numPoints) = 0;
|
||||
|
||||
const ElementType type;
|
||||
|
|
@ -43242,7 +43326,7 @@ public:
|
|||
StartSubPath (const RelativePoint& pos);
|
||||
~StartSubPath() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
RelativePoint startPos;
|
||||
|
|
@ -43258,7 +43342,7 @@ public:
|
|||
CloseSubPath();
|
||||
~CloseSubPath() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
private:
|
||||
|
|
@ -43272,7 +43356,7 @@ public:
|
|||
LineTo (const RelativePoint& endPoint);
|
||||
~LineTo() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
RelativePoint endPoint;
|
||||
|
|
@ -43288,7 +43372,7 @@ public:
|
|||
QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint);
|
||||
~QuadraticTo() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
RelativePoint controlPoints[2];
|
||||
|
|
@ -43304,7 +43388,7 @@ public:
|
|||
CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint);
|
||||
~CubicTo() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
RelativePoint controlPoints[3];
|
||||
|
|
@ -43339,11 +43423,11 @@ public:
|
|||
RelativeParallelogram (const String& topLeft, const String& topRight, const String& bottomLeft);
|
||||
~RelativeParallelogram();
|
||||
|
||||
void resolveThreePoints (Point<float>* points, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void resolveFourCorners (Point<float>* points, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
const Rectangle<float> getBounds (RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void getPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
const AffineTransform resetToPerpendicular (RelativeCoordinate::NamedCoordinateFinder* coordFinder);
|
||||
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);
|
||||
|
||||
bool operator== (const RelativeParallelogram& other) const throw();
|
||||
bool operator!= (const RelativeParallelogram& other) const throw();
|
||||
|
|
@ -43566,7 +43650,7 @@ public:
|
|||
|
||||
static const FillType readFillType (const ValueTree& v, RelativePoint* gradientPoint1,
|
||||
RelativePoint* gradientPoint2, RelativePoint* gradientPoint3,
|
||||
RelativeCoordinate::NamedCoordinateFinder* nameFinder,
|
||||
Expression::EvaluationContext* nameFinder,
|
||||
ImageProvider* imageProvider);
|
||||
|
||||
static void writeFillType (ValueTree& v, const FillType& fillType,
|
||||
|
|
@ -59069,7 +59153,7 @@ protected:
|
|||
@see Drawable
|
||||
*/
|
||||
class JUCE_API DrawableComposite : public Drawable,
|
||||
public RelativeCoordinate::NamedCoordinateFinder
|
||||
public Expression::EvaluationContext
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
@ -59230,7 +59314,7 @@ public:
|
|||
/** @internal */
|
||||
const Identifier getValueTreeType() const { return valueTreeType; }
|
||||
/** @internal */
|
||||
const RelativeCoordinate findNamedCoordinate (const String& objectName, const String& edge) const;
|
||||
const Expression getSymbolValue (const String& symbol) const;
|
||||
|
||||
/** Internally-used class for wrapping a DrawableComposite's state into a ValueTree. */
|
||||
class ValueTreeWrapper : public ValueTreeWrapperBase
|
||||
|
|
@ -59506,14 +59590,14 @@ public:
|
|||
public:
|
||||
ValueTreeWrapper (const ValueTree& state);
|
||||
|
||||
const FillType getMainFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder,
|
||||
const FillType getMainFill (Expression::EvaluationContext* nameFinder,
|
||||
ImageProvider* imageProvider) const;
|
||||
ValueTree getMainFillState();
|
||||
void setMainFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, const RelativePoint* gradientPoint3,
|
||||
ImageProvider* imageProvider, UndoManager* undoManager);
|
||||
|
||||
const FillType getStrokeFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder,
|
||||
const FillType getStrokeFill (Expression::EvaluationContext* nameFinder,
|
||||
ImageProvider* imageProvider) const;
|
||||
ValueTree getStrokeFillState();
|
||||
void setStrokeFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
|
|
@ -59540,7 +59624,7 @@ public:
|
|||
const RelativePoint getStartPoint() const;
|
||||
const RelativePoint getEndPoint() const;
|
||||
void setControlPoint (int index, const RelativePoint& point, UndoManager* undoManager);
|
||||
float getLength (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
float getLength (Expression::EvaluationContext* nameFinder) const;
|
||||
|
||||
ValueTreeWrapper getParent() const;
|
||||
Element getPreviousElement() const;
|
||||
|
|
@ -59549,11 +59633,11 @@ public:
|
|||
void setModeOfEndPoint (const String& newMode, UndoManager* undoManager);
|
||||
|
||||
void convertToLine (UndoManager* undoManager);
|
||||
void convertToCubic (RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager);
|
||||
void convertToCubic (Expression::EvaluationContext* nameFinder, UndoManager* undoManager);
|
||||
void convertToPathBreak (UndoManager* undoManager);
|
||||
ValueTree insertPoint (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager);
|
||||
ValueTree insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder, UndoManager* undoManager);
|
||||
void removePoint (UndoManager* undoManager);
|
||||
float findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder) const;
|
||||
|
||||
static const Identifier mode, startSubPathElement, closeSubPathElement,
|
||||
lineToElement, quadraticToElement, cubicToElement;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ void AudioFormatReaderSource::setNextReadPosition (int newPosition)
|
|||
nextPlayPos = newPosition;
|
||||
}
|
||||
|
||||
void AudioFormatReaderSource::setLooping (const bool shouldLoop) throw()
|
||||
void AudioFormatReaderSource::setLooping (bool shouldLoop)
|
||||
{
|
||||
looping = shouldLoop;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public:
|
|||
|
||||
@see isLooping
|
||||
*/
|
||||
void setLooping (const bool shouldLoop) throw();
|
||||
void setLooping (bool shouldLoop);
|
||||
|
||||
/** Returns whether loop-mode is turned on or not. */
|
||||
bool isLooping() const { return looping; }
|
||||
|
|
|
|||
|
|
@ -74,6 +74,15 @@ struct JUCE_API AudioSourceChannelInfo
|
|||
/**
|
||||
Base class for objects that can produce a continuous stream of audio.
|
||||
|
||||
An AudioSource has two states: 'prepared' and 'unprepared'.
|
||||
|
||||
When a source needs to be played, it is first put into a 'prepared' state by a call to
|
||||
prepareToPlay(), and then repeated calls will be made to its getNextAudioBlock() method to
|
||||
process the audio data.
|
||||
|
||||
Once playback has finished, the releaseResources() method is called to put the stream
|
||||
back into an 'unprepared' state.
|
||||
|
||||
@see AudioFormatReaderSource, ResamplingAudioSource
|
||||
*/
|
||||
class JUCE_API AudioSource
|
||||
|
|
@ -90,7 +99,14 @@ public:
|
|||
//==============================================================================
|
||||
/** Tells the source to prepare for playing.
|
||||
|
||||
The source can use this opportunity to initialise anything it needs to.
|
||||
An AudioSource has two states: prepared and unprepared.
|
||||
|
||||
The prepareToPlay() method is guaranteed to be called at least once on an 'unpreprared'
|
||||
source to put it into a 'prepared' state before any calls will be made to getNextAudioBlock().
|
||||
This callback allows the source to initialise any resources it might need when playing.
|
||||
|
||||
Once playback has finished, the releaseResources() method is called to put the stream
|
||||
back into an 'unprepared' state.
|
||||
|
||||
Note that this method could be called more than once in succession without
|
||||
a matching call to releaseResources(), so make sure your code is robust and
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ public:
|
|||
|
||||
/** Returns true if this source is actually playing in a loop. */
|
||||
virtual bool isLooping() const = 0;
|
||||
|
||||
/** Tells the source whether you'd like it to play in a loop. */
|
||||
virtual void setLooping (bool shouldLoop) { (void) shouldLoop; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
949
src/containers/juce_Expression.cpp
Normal file
949
src/containers/juce_Expression.cpp
Normal file
|
|
@ -0,0 +1,949 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-10 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_Expression.h"
|
||||
#include "juce_ReferenceCountedArray.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class Expression::Helpers
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
class Constant : public Term
|
||||
{
|
||||
public:
|
||||
Constant (const double value_) : value (value_), isResolutionTarget (false) {}
|
||||
|
||||
Term* clone() const { return new Constant (value); }
|
||||
double evaluate (const EvaluationContext&, int) const { return value; }
|
||||
int getNumInputs() const { return 0; }
|
||||
Term* getInput (int) const { return 0; }
|
||||
|
||||
const String toString() const
|
||||
{
|
||||
if (isResolutionTarget)
|
||||
return "@" + String (value);
|
||||
|
||||
return String (value);
|
||||
}
|
||||
|
||||
double value;
|
||||
bool isResolutionTarget;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class Symbol : public Term
|
||||
{
|
||||
public:
|
||||
Symbol (const String& symbol_) : symbol (symbol_) {}
|
||||
|
||||
double evaluate (const EvaluationContext& c, int recursionDepth) const
|
||||
{
|
||||
if (++recursionDepth > 256)
|
||||
throw EvaluationError ("Recursive symbol references");
|
||||
|
||||
return c.getSymbolValue (symbol).term->evaluate (c, recursionDepth);
|
||||
}
|
||||
|
||||
Term* clone() const { return new Symbol (symbol); }
|
||||
int getNumInputs() const { return 0; }
|
||||
Term* getInput (int) const { return 0; }
|
||||
const String toString() const { return symbol; }
|
||||
|
||||
bool referencesSymbol (const String& s, const EvaluationContext& c, int recursionDepth) const
|
||||
{
|
||||
if (s == symbol)
|
||||
return true;
|
||||
|
||||
if (++recursionDepth > 256)
|
||||
throw EvaluationError ("Recursive symbol references");
|
||||
|
||||
return c.getSymbolValue (symbol).term->referencesSymbol (s, c, recursionDepth);
|
||||
}
|
||||
|
||||
String symbol;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class Function : public Term
|
||||
{
|
||||
public:
|
||||
Function (const String& functionName_, const ReferenceCountedArray<Term>& parameters_)
|
||||
: functionName (functionName_), parameters (parameters_)
|
||||
{}
|
||||
|
||||
Term* clone() const { return new Function (functionName, parameters); }
|
||||
|
||||
double evaluate (const EvaluationContext& c, int recursionDepth) const
|
||||
{
|
||||
HeapBlock <double> params (parameters.size());
|
||||
for (int i = 0; i < parameters.size(); ++i)
|
||||
params[i] = parameters.getUnchecked(i)->evaluate (c, recursionDepth);
|
||||
|
||||
return c.evaluateFunction (functionName, params, parameters.size());
|
||||
}
|
||||
|
||||
int getInputIndexFor (const Term* possibleInput) const { return parameters.indexOf (possibleInput); }
|
||||
int getNumInputs() const { return parameters.size(); }
|
||||
Term* getInput (int i) const { return parameters [i]; }
|
||||
|
||||
bool referencesSymbol (const String& s, const EvaluationContext& c, int recursionDepth) const
|
||||
{
|
||||
for (int i = 0; i < parameters.size(); ++i)
|
||||
if (parameters.getUnchecked(i)->referencesSymbol (s, c, recursionDepth))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const String toString() const
|
||||
{
|
||||
if (parameters.size() == 0)
|
||||
return functionName + "()";
|
||||
|
||||
String s (functionName + " (");
|
||||
|
||||
for (int i = 0; i < parameters.size(); ++i)
|
||||
{
|
||||
s << parameters.getUnchecked(i)->toString();
|
||||
|
||||
if (i < parameters.size() - 1)
|
||||
s << ", ";
|
||||
}
|
||||
|
||||
s << ')';
|
||||
return s;
|
||||
}
|
||||
|
||||
const String functionName;
|
||||
ReferenceCountedArray<Term> parameters;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class Negate : public Term
|
||||
{
|
||||
public:
|
||||
Negate (Term* const input_) : input (input_)
|
||||
{
|
||||
jassert (input_ != 0);
|
||||
}
|
||||
|
||||
int getInputIndexFor (const Term* possibleInput) const { return possibleInput == input ? 0 : -1; }
|
||||
int getNumInputs() const { return 1; }
|
||||
Term* getInput (int index) const { return index == 0 ? static_cast<Term*> (input) : 0; }
|
||||
Term* clone() const { return new Negate (input->clone()); }
|
||||
double evaluate (const EvaluationContext& c, int recursionDepth) const { return -input->evaluate (c, recursionDepth); }
|
||||
|
||||
const ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const EvaluationContext&, Term* input_, double overallTarget, Term* topLevelTerm) const
|
||||
{
|
||||
jassert (input_ == input);
|
||||
|
||||
const Term* const dest = findDestinationFor (topLevelTerm, this);
|
||||
Term* newDest;
|
||||
if (dest == 0)
|
||||
newDest = new Constant (overallTarget);
|
||||
else
|
||||
newDest = dest->clone();
|
||||
|
||||
return new Negate (newDest);
|
||||
}
|
||||
|
||||
const String toString() const
|
||||
{
|
||||
if (input->getOperatorPrecedence() > 0)
|
||||
return "-(" + input->toString() + ")";
|
||||
else
|
||||
return "-" + input->toString();
|
||||
}
|
||||
|
||||
bool referencesSymbol (const String& s, const EvaluationContext& c, int recursionDepth) const
|
||||
{
|
||||
return input->referencesSymbol (s, c, recursionDepth);
|
||||
}
|
||||
|
||||
private:
|
||||
const ReferenceCountedObjectPtr<Term> input;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class BinaryTerm : public Term
|
||||
{
|
||||
public:
|
||||
BinaryTerm (Term* const left_, Term* const right_) : left (left_), right (right_)
|
||||
{
|
||||
jassert (left_ != 0 && right_ != 0);
|
||||
}
|
||||
|
||||
int getInputIndexFor (const Term* possibleInput) const
|
||||
{
|
||||
return possibleInput == left ? 0 : (possibleInput == right ? 1 : -1);
|
||||
}
|
||||
|
||||
int getNumInputs() const { return 2; }
|
||||
Term* getInput (int index) const { return index == 0 ? static_cast<Term*> (left) : (index == 1 ? static_cast<Term*> (right) : 0); }
|
||||
|
||||
bool referencesSymbol (const String& s, const EvaluationContext& c, int recursionDepth) const
|
||||
{
|
||||
return left->referencesSymbol (s, c, recursionDepth)
|
||||
|| right->referencesSymbol (s, c, recursionDepth);
|
||||
}
|
||||
|
||||
protected:
|
||||
const ReferenceCountedObjectPtr<Term> left, right;
|
||||
|
||||
const String createString (const String& op) const
|
||||
{
|
||||
String s;
|
||||
|
||||
const int ourPrecendence = getOperatorPrecedence();
|
||||
if (left->getOperatorPrecedence() > ourPrecendence)
|
||||
s << '(' << left->toString() << ')';
|
||||
else
|
||||
s = left->toString();
|
||||
|
||||
s << ' ' << op << ' ';
|
||||
|
||||
if (right->getOperatorPrecedence() >= ourPrecendence)
|
||||
s << '(' << right->toString() << ')';
|
||||
else
|
||||
s << right->toString();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
Term* createDestinationTerm (const EvaluationContext&, Term* input, double overallTarget, Term* topLevelTerm) const
|
||||
{
|
||||
jassert (input == left || input == right);
|
||||
if (input != left && input != right)
|
||||
return 0;
|
||||
|
||||
const Term* const dest = findDestinationFor (topLevelTerm, this);
|
||||
|
||||
if (dest == 0)
|
||||
return new Constant (overallTarget);
|
||||
|
||||
return dest->clone();
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class Add : public BinaryTerm
|
||||
{
|
||||
public:
|
||||
Add (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {}
|
||||
|
||||
Term* clone() const { return new Add (left->clone(), right->clone()); }
|
||||
double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) + right->evaluate (c, recursionDepth); }
|
||||
const String toString() const { return createString ("+"); }
|
||||
int getOperatorPrecedence() const { return 2; }
|
||||
|
||||
const ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const EvaluationContext& c, Term* input, double overallTarget, Term* topLevelTerm) const
|
||||
{
|
||||
Term* const newDest = createDestinationTerm (c, input, overallTarget, topLevelTerm);
|
||||
if (newDest == 0)
|
||||
return 0;
|
||||
|
||||
return new Subtract (newDest, (input == left ? right : left)->clone());
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class Subtract : public BinaryTerm
|
||||
{
|
||||
public:
|
||||
Subtract (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {}
|
||||
|
||||
Term* clone() const { return new Subtract (left->clone(), right->clone()); }
|
||||
double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) - right->evaluate (c, recursionDepth); }
|
||||
const String toString() const { return createString ("-"); }
|
||||
int getOperatorPrecedence() const { return 2; }
|
||||
|
||||
const ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const EvaluationContext& c, Term* input, double overallTarget, Term* topLevelTerm) const
|
||||
{
|
||||
Term* const newDest = createDestinationTerm (c, input, overallTarget, topLevelTerm);
|
||||
if (newDest == 0)
|
||||
return 0;
|
||||
|
||||
if (input == left)
|
||||
return new Add (newDest, right->clone());
|
||||
else
|
||||
return new Subtract (left->clone(), newDest);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class Multiply : public BinaryTerm
|
||||
{
|
||||
public:
|
||||
Multiply (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {}
|
||||
|
||||
Term* clone() const { return new Multiply (left->clone(), right->clone()); }
|
||||
double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) * right->evaluate (c, recursionDepth); }
|
||||
const String toString() const { return createString ("*"); }
|
||||
int getOperatorPrecedence() const { return 1; }
|
||||
|
||||
const ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const EvaluationContext& c, Term* input, double overallTarget, Term* topLevelTerm) const
|
||||
{
|
||||
Term* const newDest = createDestinationTerm (c, input, overallTarget, topLevelTerm);
|
||||
if (newDest == 0)
|
||||
return 0;
|
||||
|
||||
return new Divide (newDest, (input == left ? right : left)->clone());
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class Divide : public BinaryTerm
|
||||
{
|
||||
public:
|
||||
Divide (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {}
|
||||
|
||||
Term* clone() const { return new Divide (left->clone(), right->clone()); }
|
||||
double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) / right->evaluate (c, recursionDepth); }
|
||||
const String toString() const { return createString ("/"); }
|
||||
int getOperatorPrecedence() const { return 1; }
|
||||
|
||||
const ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const EvaluationContext& c, Term* input, double overallTarget, Term* topLevelTerm) const
|
||||
{
|
||||
Term* const newDest = createDestinationTerm (c, input, overallTarget, topLevelTerm);
|
||||
if (newDest == 0)
|
||||
return 0;
|
||||
|
||||
if (input == left)
|
||||
return new Multiply (newDest, right->clone());
|
||||
else
|
||||
return new Divide (left->clone(), newDest);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static Term* findDestinationFor (Term* const topLevel, const Term* const inputTerm)
|
||||
{
|
||||
const int inputIndex = topLevel->getInputIndexFor (inputTerm);
|
||||
if (inputIndex >= 0)
|
||||
return topLevel;
|
||||
|
||||
for (int i = topLevel->getNumInputs(); --i >= 0;)
|
||||
{
|
||||
Term* t = findDestinationFor (topLevel->getInput (i), inputTerm);
|
||||
|
||||
if (t != 0)
|
||||
return t;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Constant* findTermToAdjust (Term* const term, const bool mustBeFlagged)
|
||||
{
|
||||
Constant* c = dynamic_cast<Constant*> (term);
|
||||
if (c != 0 && (c->isResolutionTarget || ! mustBeFlagged))
|
||||
return c;
|
||||
|
||||
int i;
|
||||
for (i = term->getNumInputs(); --i >= 0;)
|
||||
{
|
||||
Constant* c = dynamic_cast<Constant*> (term->getInput (i));
|
||||
if (c != 0 && (c->isResolutionTarget || ! mustBeFlagged))
|
||||
return c;
|
||||
}
|
||||
|
||||
for (i = term->getNumInputs(); --i >= 0;)
|
||||
{
|
||||
Constant* c = findTermToAdjust (term->getInput (i), mustBeFlagged);
|
||||
if (c != 0)
|
||||
return c;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool containsAnySymbols (const Term* const t)
|
||||
{
|
||||
if (dynamic_cast <const Symbol*> (t) != 0)
|
||||
return true;
|
||||
|
||||
for (int i = t->getNumInputs(); --i >= 0;)
|
||||
if (containsAnySymbols (t->getInput (i)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool renameSymbol (Term* const t, const String& oldName, const String& newName)
|
||||
{
|
||||
Symbol* sym = dynamic_cast <Symbol*> (t);
|
||||
|
||||
if (sym != 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
bool anyChanged = false;
|
||||
|
||||
for (int i = t->getNumInputs(); --i >= 0;)
|
||||
if (renameSymbol (t->getInput (i), oldName, newName))
|
||||
anyChanged = true;
|
||||
|
||||
return anyChanged;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
Parser (const String& stringToParse, int& textIndex_)
|
||||
: textString (stringToParse), textIndex (textIndex_)
|
||||
{
|
||||
text = textString;
|
||||
}
|
||||
|
||||
Term* readExpression()
|
||||
{
|
||||
ScopedPointer<Term> lhs (readMultiplyOrDivideExpression());
|
||||
|
||||
char opType;
|
||||
while (lhs != 0 && readOperator ("+-", &opType))
|
||||
{
|
||||
Term* rhs = readMultiplyOrDivideExpression();
|
||||
|
||||
if (rhs == 0)
|
||||
throw ParseError ("Expected expression after \"" + String::charToString (opType) + "\"");
|
||||
|
||||
if (opType == '+')
|
||||
lhs = new Add (lhs.release(), rhs);
|
||||
else
|
||||
lhs = new Subtract (lhs.release(), rhs);
|
||||
}
|
||||
|
||||
return lhs.release();
|
||||
}
|
||||
|
||||
private:
|
||||
const String textString;
|
||||
const juce_wchar* text;
|
||||
int& textIndex;
|
||||
|
||||
//==============================================================================
|
||||
static inline bool isDecimalDigit (const juce_wchar c) throw()
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
void skipWhitespace (int& i)
|
||||
{
|
||||
while (CharacterFunctions::isWhitespace (text [i]))
|
||||
++i;
|
||||
}
|
||||
|
||||
bool readChar (const juce_wchar required)
|
||||
{
|
||||
if (text[textIndex] == required)
|
||||
{
|
||||
++textIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool readOperator (const char* ops, char* const opType = 0)
|
||||
{
|
||||
skipWhitespace (textIndex);
|
||||
|
||||
while (*ops != 0)
|
||||
{
|
||||
if (readChar (*ops))
|
||||
{
|
||||
if (opType != 0)
|
||||
*opType = *ops;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
++ops;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool readIdentifier (String& identifier)
|
||||
{
|
||||
skipWhitespace (textIndex);
|
||||
int i = textIndex;
|
||||
|
||||
if (CharacterFunctions::isLetter (text[i]) || text[i] == '_')
|
||||
{
|
||||
++i;
|
||||
|
||||
while (CharacterFunctions::isLetterOrDigit (text[i]) || text[i] == '_' || text[i] == '.')
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i > textIndex)
|
||||
{
|
||||
identifier = String (text + textIndex, i - textIndex);
|
||||
textIndex = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Term* readNumber()
|
||||
{
|
||||
skipWhitespace (textIndex);
|
||||
int i = textIndex;
|
||||
|
||||
const bool isResolutionTarget = (text[i] == '@');
|
||||
if (isResolutionTarget)
|
||||
{
|
||||
++i;
|
||||
skipWhitespace (i);
|
||||
}
|
||||
|
||||
int numDigits = 0;
|
||||
|
||||
while (isDecimalDigit (text[i]))
|
||||
{
|
||||
++i;
|
||||
++numDigits;
|
||||
}
|
||||
|
||||
const bool hasPoint = (text[i] == '.');
|
||||
|
||||
if (hasPoint)
|
||||
{
|
||||
++i;
|
||||
|
||||
while (isDecimalDigit (text[i]))
|
||||
{
|
||||
++i;
|
||||
++numDigits;
|
||||
}
|
||||
}
|
||||
|
||||
if (numDigits == 0)
|
||||
return 0;
|
||||
|
||||
juce_wchar c = text[i];
|
||||
const bool hasExponent = (c == 'e' || c == 'E');
|
||||
|
||||
if (hasExponent)
|
||||
{
|
||||
++i;
|
||||
c = text[i];
|
||||
if (c == '+' || c == '-')
|
||||
++i;
|
||||
|
||||
int numExpDigits = 0;
|
||||
while (isDecimalDigit (text[i]))
|
||||
{
|
||||
++i;
|
||||
++numExpDigits;
|
||||
}
|
||||
|
||||
if (numExpDigits == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Constant* t = new Constant (String (text + textIndex, i - textIndex).getDoubleValue());
|
||||
t->isResolutionTarget = isResolutionTarget;
|
||||
textIndex = i;
|
||||
return t;
|
||||
}
|
||||
|
||||
Term* readMultiplyOrDivideExpression()
|
||||
{
|
||||
ScopedPointer<Term> lhs (readUnaryExpression());
|
||||
|
||||
char opType;
|
||||
while (lhs != 0 && readOperator ("*/", &opType))
|
||||
{
|
||||
Term* rhs = readUnaryExpression();
|
||||
|
||||
if (rhs == 0)
|
||||
throw ParseError ("Expected expression after \"" + String::charToString (opType) + "\"");
|
||||
|
||||
if (opType == '*')
|
||||
lhs = new Multiply (lhs.release(), rhs);
|
||||
else
|
||||
lhs = new Divide (lhs.release(), rhs);
|
||||
}
|
||||
|
||||
return lhs.release();
|
||||
}
|
||||
|
||||
Term* readUnaryExpression()
|
||||
{
|
||||
char opType;
|
||||
if (readOperator ("+-", &opType))
|
||||
{
|
||||
Term* term = readUnaryExpression();
|
||||
|
||||
if (term == 0)
|
||||
throw ParseError ("Expected expression after \"" + String::charToString (opType) + "\"");
|
||||
|
||||
if (opType == '-')
|
||||
term = new Negate (term);
|
||||
|
||||
return term;
|
||||
}
|
||||
|
||||
return readPrimaryExpression();
|
||||
}
|
||||
|
||||
Term* readPrimaryExpression()
|
||||
{
|
||||
Term* e = readParenthesisedExpression();
|
||||
if (e != 0)
|
||||
return e;
|
||||
|
||||
e = readNumber();
|
||||
if (e != 0)
|
||||
return e;
|
||||
|
||||
String identifier;
|
||||
if (readIdentifier (identifier))
|
||||
{
|
||||
if (readOperator ("(")) // method call...
|
||||
{
|
||||
Function* f = new Function (identifier, ReferenceCountedArray<Term>());
|
||||
ScopedPointer<Term> func (f); // (can't use ScopedPointer<Function> in MSVC)
|
||||
|
||||
Term* param = readExpression();
|
||||
|
||||
if (param == 0)
|
||||
{
|
||||
if (readOperator (")"))
|
||||
return func.release();
|
||||
|
||||
throw ParseError ("Expected parameters after \"" + identifier + " (\"");
|
||||
}
|
||||
|
||||
f->parameters.add (param);
|
||||
|
||||
while (readOperator (","))
|
||||
{
|
||||
param = readExpression();
|
||||
|
||||
if (param == 0)
|
||||
throw ParseError ("Expected expression after \",\"");
|
||||
|
||||
f->parameters.add (param);
|
||||
}
|
||||
|
||||
if (readOperator (")"))
|
||||
return func.release();
|
||||
|
||||
throw ParseError ("Expected \")\"");
|
||||
}
|
||||
else // just a symbol..
|
||||
{
|
||||
return new Symbol (identifier);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Term* readParenthesisedExpression()
|
||||
{
|
||||
if (! readOperator ("("))
|
||||
return 0;
|
||||
|
||||
ScopedPointer<Term> e (readExpression());
|
||||
if (e == 0)
|
||||
return 0;
|
||||
|
||||
if (! readOperator (")"))
|
||||
e = 0;
|
||||
|
||||
return e.release();
|
||||
}
|
||||
|
||||
Parser (const Parser&);
|
||||
Parser& operator= (const Parser&);
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
Expression::Expression()
|
||||
: term (new Expression::Helpers::Constant (0))
|
||||
{
|
||||
}
|
||||
|
||||
Expression::~Expression()
|
||||
{
|
||||
}
|
||||
|
||||
Expression::Expression (Term* const term_)
|
||||
: term (term_)
|
||||
{
|
||||
jassert (term != 0);
|
||||
}
|
||||
|
||||
Expression::Expression (const double constant)
|
||||
: term (new Expression::Helpers::Constant (constant))
|
||||
{
|
||||
}
|
||||
|
||||
Expression::Expression (const Expression& other)
|
||||
: term (other.term)
|
||||
{
|
||||
}
|
||||
|
||||
Expression& Expression::operator= (const Expression& other)
|
||||
{
|
||||
term = other.term;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Expression::Expression (const String& stringToParse)
|
||||
{
|
||||
int i = 0;
|
||||
Helpers::Parser parser (stringToParse, i);
|
||||
term = parser.readExpression();
|
||||
|
||||
if (term == 0)
|
||||
term = new Helpers::Constant (0);
|
||||
}
|
||||
|
||||
const Expression Expression::parse (const String& stringToParse, int& textIndexToStartFrom)
|
||||
{
|
||||
Helpers::Parser parser (stringToParse, textIndexToStartFrom);
|
||||
Term* term = parser.readExpression();
|
||||
|
||||
if (term != 0)
|
||||
return Expression (term);
|
||||
|
||||
return Expression();
|
||||
}
|
||||
|
||||
double Expression::evaluate() const
|
||||
{
|
||||
return evaluate (Expression::EvaluationContext());
|
||||
}
|
||||
|
||||
double Expression::evaluate (const Expression::EvaluationContext& context) const
|
||||
{
|
||||
return term->evaluate (context, 0);
|
||||
}
|
||||
|
||||
const Expression Expression::operator+ (const Expression& other) const
|
||||
{
|
||||
return Expression (new Helpers::Add (term, other.term));
|
||||
}
|
||||
|
||||
const Expression Expression::operator- (const Expression& other) const
|
||||
{
|
||||
return Expression (new Helpers::Subtract (term, other.term));
|
||||
}
|
||||
|
||||
const Expression Expression::operator* (const Expression& other) const
|
||||
{
|
||||
return Expression (new Helpers::Multiply (term, other.term));
|
||||
}
|
||||
|
||||
const Expression Expression::operator/ (const Expression& other) const
|
||||
{
|
||||
return Expression (new Helpers::Divide (term, other.term));
|
||||
}
|
||||
|
||||
const Expression Expression::operator-() const
|
||||
{
|
||||
return Expression (new Helpers::Negate (term));
|
||||
}
|
||||
|
||||
const String Expression::toString() const
|
||||
{
|
||||
return term->toString();
|
||||
}
|
||||
|
||||
const Expression Expression::symbol (const String& symbol)
|
||||
{
|
||||
return Expression (new Helpers::Symbol (symbol));
|
||||
}
|
||||
|
||||
const Expression Expression::function (const String& functionName, const Array<Expression>& parameters)
|
||||
{
|
||||
ReferenceCountedArray<Term> params;
|
||||
for (int i = 0; i < parameters.size(); ++i)
|
||||
params.add (parameters.getReference(i).term);
|
||||
|
||||
return Expression (new Helpers::Function (functionName, params));
|
||||
}
|
||||
|
||||
const Expression Expression::adjustedToGiveNewResult (const double targetValue,
|
||||
const Expression::EvaluationContext& context) const
|
||||
{
|
||||
ScopedPointer<Term> newTerm (term->clone());
|
||||
|
||||
Helpers::Constant* termToAdjust = Helpers::findTermToAdjust (newTerm, true);
|
||||
|
||||
if (termToAdjust == 0)
|
||||
termToAdjust = Helpers::findTermToAdjust (newTerm, false);
|
||||
|
||||
if (termToAdjust == 0)
|
||||
{
|
||||
newTerm = new Helpers::Add (newTerm.release(), new Helpers::Constant (0));
|
||||
termToAdjust = Helpers::findTermToAdjust (newTerm, false);
|
||||
}
|
||||
|
||||
jassert (termToAdjust != 0);
|
||||
|
||||
const Term* parent = Helpers::findDestinationFor (newTerm, termToAdjust);
|
||||
|
||||
if (parent == 0)
|
||||
{
|
||||
termToAdjust->value = targetValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ReferenceCountedObjectPtr<Term> reverseTerm (parent->createTermToEvaluateInput (context, termToAdjust, targetValue, newTerm));
|
||||
|
||||
if (reverseTerm == 0)
|
||||
return Expression();
|
||||
|
||||
termToAdjust->value = reverseTerm->evaluate (context, 0);
|
||||
}
|
||||
|
||||
return Expression (newTerm.release());
|
||||
}
|
||||
|
||||
const Expression Expression::withRenamedSymbol (const String& oldSymbol, const String& newSymbol) const
|
||||
{
|
||||
jassert (newSymbol.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_."));
|
||||
|
||||
Expression newExpression (term->clone());
|
||||
Helpers::renameSymbol (newExpression.term, oldSymbol, newSymbol);
|
||||
return newExpression;
|
||||
}
|
||||
|
||||
bool Expression::referencesSymbol (const String& symbol, const EvaluationContext& context) const
|
||||
{
|
||||
return term->referencesSymbol (symbol, context, 0);
|
||||
}
|
||||
|
||||
bool Expression::usesAnySymbols() const
|
||||
{
|
||||
return Helpers::containsAnySymbols (term);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int Expression::Term::getOperatorPrecedence() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Expression::Term::referencesSymbol (const String&, const EvaluationContext&, int) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Expression::Term::getInputIndexFor (const Term*) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
const ReferenceCountedObjectPtr<Expression::Term> Expression::Term::createTermToEvaluateInput (const EvaluationContext&, Term*, double, Term*) const
|
||||
{
|
||||
jassertfalse;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Expression::ParseError::ParseError (const String& message)
|
||||
: description (message)
|
||||
{
|
||||
}
|
||||
|
||||
Expression::EvaluationError::EvaluationError (const String& message)
|
||||
: description (message)
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Expression::EvaluationContext::EvaluationContext() {}
|
||||
Expression::EvaluationContext::~EvaluationContext() {}
|
||||
|
||||
const Expression Expression::EvaluationContext::getSymbolValue (const String& symbol) const
|
||||
{
|
||||
throw EvaluationError ("Unknown symbol: \"" + symbol + "\"");
|
||||
}
|
||||
|
||||
double Expression::EvaluationContext::evaluateFunction (const String& functionName, const double* parameters, int numParams) const
|
||||
{
|
||||
if (numParams > 0)
|
||||
{
|
||||
if (functionName == "min")
|
||||
{
|
||||
double v = parameters[0];
|
||||
for (int i = 1; i < numParams; ++i)
|
||||
v = jmin (v, parameters[i]);
|
||||
|
||||
return v;
|
||||
}
|
||||
else if (functionName == "max")
|
||||
{
|
||||
double v = parameters[0];
|
||||
for (int i = 1; i < numParams; ++i)
|
||||
v = jmax (v, parameters[i]);
|
||||
|
||||
return v;
|
||||
}
|
||||
else if (numParams == 1)
|
||||
{
|
||||
if (functionName == "sin")
|
||||
return sin (parameters[0]);
|
||||
else if (functionName == "cos")
|
||||
return cos (parameters[0]);
|
||||
else if (functionName == "tan")
|
||||
return tan (parameters[0]);
|
||||
else if (functionName == "abs")
|
||||
return std::abs (parameters[0]);
|
||||
}
|
||||
}
|
||||
|
||||
throw EvaluationError ("Unknown function: \"" + functionName + "\"");
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
216
src/containers/juce_Expression.h
Normal file
216
src/containers/juce_Expression.h
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-10 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_EXPRESSION_JUCEHEADER__
|
||||
#define __JUCE_EXPRESSION_JUCEHEADER__
|
||||
|
||||
#include "juce_ReferenceCountedObject.h"
|
||||
#include "juce_Array.h"
|
||||
#include "juce_ScopedPointer.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A class for dynamically evaluating simple numeric expressions.
|
||||
|
||||
This class can parse a simple C-style string expression involving floating point
|
||||
numbers, named symbols and functions. The basic arithmetic operations of +, -, *, /
|
||||
are supported, as well as parentheses, and any alphanumeric identifiers are
|
||||
assumed to be named symbols which will be resolved when the expression is
|
||||
evaluated.
|
||||
|
||||
Expressions which use identifiers and functions require a subclass of
|
||||
Expression::EvaluationContext 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.
|
||||
*/
|
||||
class JUCE_API Expression
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a simple expression with a value of 0. */
|
||||
Expression();
|
||||
|
||||
/** Destructor. */
|
||||
~Expression();
|
||||
|
||||
/** Creates a simple expression with a specified constant value. */
|
||||
explicit Expression (const double constant);
|
||||
|
||||
/** Creates a copy of an expression. */
|
||||
Expression (const Expression& other);
|
||||
|
||||
/** Copies another expression. */
|
||||
Expression& operator= (const Expression& other);
|
||||
|
||||
/** Creates an expression by parsing a string.
|
||||
If there's a syntax error in the string, this will throw a ParseError exception.
|
||||
@throws ParseError
|
||||
*/
|
||||
explicit Expression (const String& stringToParse);
|
||||
|
||||
/** Returns a string version of the expression. */
|
||||
const String toString() const;
|
||||
|
||||
/** Returns an expression which is an addtion operation of two existing expressions. */
|
||||
const Expression operator+ (const Expression& other) const;
|
||||
/** Returns an expression which is a subtraction operation of two existing expressions. */
|
||||
const Expression operator- (const Expression& other) const;
|
||||
/** Returns an expression which is a multiplication operation of two existing expressions. */
|
||||
const Expression operator* (const Expression& other) const;
|
||||
/** Returns an expression which is a division operation of two existing expressions. */
|
||||
const Expression operator/ (const Expression& other) const;
|
||||
/** Returns an expression which is a negation operation of two existing expressions. */
|
||||
const Expression operator-() const;
|
||||
|
||||
/** Returns an Expression which is an identifier reference. */
|
||||
static const Expression symbol (const String& symbol);
|
||||
|
||||
/** Returns an Expression which is a function call. */
|
||||
static const Expression function (const String& functionName, const Array<Expression>& parameters);
|
||||
|
||||
/** Returns an Expression which parses a string from a specified character index.
|
||||
|
||||
The index value is incremented so that on return, it indicates the character that follows
|
||||
the end of the expression that was parsed.
|
||||
|
||||
If there's a syntax error in the string, this will throw a ParseError exception.
|
||||
@throws ParseError
|
||||
*/
|
||||
static const Expression parse (const String& stringToParse, int& textIndexToStartFrom);
|
||||
|
||||
//==============================================================================
|
||||
/** When evaluating an Expression object, this class is used to resolve symbols and
|
||||
perform functions that the expression uses.
|
||||
*/
|
||||
class EvaluationContext
|
||||
{
|
||||
public:
|
||||
EvaluationContext();
|
||||
virtual ~EvaluationContext();
|
||||
|
||||
/** Returns the value of a symbol.
|
||||
If the symbol is unknown, this can throw an Expression::EvaluationError exception.
|
||||
@throws Expression::EvaluationError
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
/** Evaluates this expression, without using an EvaluationContext.
|
||||
Without an EvaluationContext, no symbols can be used, and only basic functions such as sin, cos, tan,
|
||||
min, max are available.
|
||||
*/
|
||||
double evaluate() const;
|
||||
|
||||
/** Evaluates this expression, providing a context that should be able to evaluate any symbols
|
||||
or functions that it uses.
|
||||
*/
|
||||
double evaluate (const EvaluationContext& context) 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.
|
||||
*/
|
||||
const Expression adjustedToGiveNewResult (double targetValue, const EvaluationContext& context) const;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Returns true if this expression makes use of the specified symbol.
|
||||
If a suitable context 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.
|
||||
*/
|
||||
bool referencesSymbol (const String& symbol, const EvaluationContext& context) const;
|
||||
|
||||
/** Returns true if this expression contains any symbols. */
|
||||
bool usesAnySymbols() const;
|
||||
|
||||
//==============================================================================
|
||||
/** An exception that can be thrown by Expression::parse(). */
|
||||
class ParseError : public std::exception
|
||||
{
|
||||
public:
|
||||
ParseError (const String& message);
|
||||
|
||||
String description;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** An exception that can be thrown by Expression::evaluate(). */
|
||||
class EvaluationError : public std::exception
|
||||
{
|
||||
public:
|
||||
EvaluationError (const String& message);
|
||||
|
||||
String description;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
class Helpers;
|
||||
friend class Helpers;
|
||||
|
||||
class Term : public ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
Term() {}
|
||||
virtual ~Term() {}
|
||||
|
||||
virtual Term* clone() const = 0;
|
||||
virtual double evaluate (const EvaluationContext&, int recursionDepth) const = 0;
|
||||
virtual int getNumInputs() const = 0;
|
||||
virtual Term* getInput (int index) const = 0;
|
||||
virtual int getInputIndexFor (const Term* possibleInput) const;
|
||||
virtual const String toString() const = 0;
|
||||
virtual int getOperatorPrecedence() const;
|
||||
virtual bool referencesSymbol (const String& symbol, const EvaluationContext&, int recursionDepth) const;
|
||||
virtual const ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const EvaluationContext&, Term* inputTerm,
|
||||
double overallTarget, Term* topLevelTerm) const;
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
Term (const Term& other);
|
||||
Term& operator= (const Term&);
|
||||
};
|
||||
|
||||
friend class ScopedPointer<Term>;
|
||||
ReferenceCountedObjectPtr<Term> term;
|
||||
|
||||
explicit Expression (Term* term);
|
||||
};
|
||||
|
||||
#endif // __JUCE_EXPRESSION_JUCEHEADER__
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
|
||||
@see Logger::outputDebugString
|
||||
*/
|
||||
#define DBG(dbgtext) { String tempDbgBuf; tempDbgBuf << dbgtext; JUCE_NAMESPACE::Logger::outputDebugString (tempDbgBuf); }
|
||||
#define DBG(dbgtext) { JUCE_NAMESPACE::String tempDbgBuf; tempDbgBuf << dbgtext; JUCE_NAMESPACE::Logger::outputDebugString (tempDbgBuf); }
|
||||
|
||||
//==============================================================================
|
||||
// Assertions..
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 49
|
||||
#define JUCE_BUILDNUMBER 50
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,8 @@ public:
|
|||
|
||||
@param newItemText the text of the item to show in the list
|
||||
@param newItemId an associated ID number that can be set or retrieved - see
|
||||
getSelectedId() and setSelectedId()
|
||||
getSelectedId() and setSelectedId(). Note that this value can not
|
||||
be 0!
|
||||
@see setItemEnabled, addSeparator, addSectionHeading, removeItem, getNumItems, getItemText, getItemId
|
||||
*/
|
||||
void addItem (const String& newItemText,
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ public:
|
|||
row = newRow;
|
||||
isSelected = isNowSelected;
|
||||
repaint();
|
||||
deleteAllChildren();
|
||||
}
|
||||
|
||||
if (row < owner.getNumRows())
|
||||
|
|
@ -105,13 +106,12 @@ public:
|
|||
|
||||
const TableHeaderComponent* const header = owner.getHeader();
|
||||
const int numColumns = header->getNumColumns (true);
|
||||
int i;
|
||||
|
||||
columnsWithComponents.clear();
|
||||
|
||||
if (owner.getModel() != 0)
|
||||
{
|
||||
for (i = 0; i < numColumns; ++i)
|
||||
for (int i = 0; i < numColumns; ++i)
|
||||
{
|
||||
const int columnId = header->getColumnIdOfIndex (i, true);
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
for (i = getNumChildComponents(); --i >= 0;)
|
||||
for (int i = getNumChildComponents(); --i >= 0;)
|
||||
{
|
||||
Component* const c = getChildComponent (i);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ BEGIN_JUCE_NAMESPACE
|
|||
#include "juce_CallOutBox.h"
|
||||
#include "juce_ComponentPeer.h"
|
||||
#include "../lookandfeel/juce_LookAndFeel.h"
|
||||
#include "../../../application/juce_Application.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -50,6 +51,9 @@ CallOutBox::CallOutBox (Component& contentComponent,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (! JUCEApplication::isStandaloneApp())
|
||||
setAlwaysOnTop (true); // for a plugin, make it always-on-top because the host windows are often top-level
|
||||
|
||||
updatePosition (componentToPointTo.getScreenBounds(),
|
||||
componentToPointTo.getParentMonitorArea());
|
||||
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ void Drawable::ValueTreeWrapperBase::setID (const String& newID, UndoManager* co
|
|||
}
|
||||
|
||||
const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v, RelativePoint* const gp1, RelativePoint* const gp2, RelativePoint* const gp3,
|
||||
RelativeCoordinate::NamedCoordinateFinder* const nameFinder, ImageProvider* imageProvider)
|
||||
Expression::EvaluationContext* const nameFinder, ImageProvider* imageProvider)
|
||||
{
|
||||
const String newType (v[type].toString());
|
||||
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ public:
|
|||
|
||||
static const FillType readFillType (const ValueTree& v, RelativePoint* gradientPoint1,
|
||||
RelativePoint* gradientPoint2, RelativePoint* gradientPoint3,
|
||||
RelativeCoordinate::NamedCoordinateFinder* nameFinder,
|
||||
Expression::EvaluationContext* nameFinder,
|
||||
ImageProvider* imageProvider);
|
||||
|
||||
static void writeFillType (ValueTree& v, const FillType& fillType,
|
||||
|
|
|
|||
|
|
@ -247,33 +247,26 @@ void DrawableComposite::render (const Drawable::RenderingContext& context) const
|
|||
}
|
||||
}
|
||||
|
||||
const RelativeCoordinate DrawableComposite::findNamedCoordinate (const String& objectName, const String& edge) const
|
||||
const Expression DrawableComposite::getSymbolValue (const String& symbol) const
|
||||
{
|
||||
if (objectName == RelativeCoordinate::Strings::parent)
|
||||
{
|
||||
if (edge == RelativeCoordinate::Strings::right || edge == RelativeCoordinate::Strings::bottom)
|
||||
{
|
||||
jassertfalse; // a Drawable doesn't have a fixed right-hand or bottom edge - use a marker instead if you need a point of reference.
|
||||
return RelativeCoordinate (100.0);
|
||||
}
|
||||
}
|
||||
jassert (! symbol.containsChar ('.')) // the only symbols available in a Drawable are markers.
|
||||
|
||||
int i;
|
||||
for (i = 0; i < markersX.size(); ++i)
|
||||
{
|
||||
Marker* const m = markersX.getUnchecked(i);
|
||||
if (m->name == objectName)
|
||||
return m->position;
|
||||
if (m->name == symbol)
|
||||
return m->position.getExpression();
|
||||
}
|
||||
|
||||
for (i = 0; i < markersY.size(); ++i)
|
||||
{
|
||||
Marker* const m = markersY.getUnchecked(i);
|
||||
if (m->name == objectName)
|
||||
return m->position;
|
||||
if (m->name == symbol)
|
||||
return m->position.getExpression();
|
||||
}
|
||||
|
||||
return RelativeCoordinate();
|
||||
return Expression::EvaluationContext::getSymbolValue (symbol);
|
||||
}
|
||||
|
||||
const Rectangle<float> DrawableComposite::getUntransformedBounds (const bool includeMarkers) const
|
||||
|
|
@ -535,7 +528,7 @@ const DrawableComposite::Marker DrawableComposite::ValueTreeWrapper::getMarker (
|
|||
{
|
||||
jassert (containsMarker (xAxis, state));
|
||||
|
||||
return Marker (state [nameProperty], RelativeCoordinate (state [posProperty].toString(), xAxis));
|
||||
return Marker (state [nameProperty], RelativeCoordinate (state [posProperty].toString()));
|
||||
}
|
||||
|
||||
void DrawableComposite::ValueTreeWrapper::setMarker (bool xAxis, const Marker& m, UndoManager* undoManager)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
@see Drawable
|
||||
*/
|
||||
class JUCE_API DrawableComposite : public Drawable,
|
||||
public RelativeCoordinate::NamedCoordinateFinder
|
||||
public Expression::EvaluationContext
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
|
@ -201,7 +201,7 @@ public:
|
|||
/** @internal */
|
||||
const Identifier getValueTreeType() const { return valueTreeType; }
|
||||
/** @internal */
|
||||
const RelativeCoordinate findNamedCoordinate (const String& objectName, const String& edge) const;
|
||||
const Expression getSymbolValue (const String& symbol) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Internally-used class for wrapping a DrawableComposite's state into a ValueTree. */
|
||||
|
|
|
|||
|
|
@ -143,6 +143,8 @@ void DrawablePath::render (const Drawable::RenderingContext& context) const
|
|||
FillType f (mainFill);
|
||||
if (f.isGradient())
|
||||
f.gradient->multiplyOpacity (context.opacity);
|
||||
else
|
||||
f.setOpacity (f.getOpacity() * context.opacity);
|
||||
|
||||
f.transform = f.transform.followedBy (context.transform);
|
||||
context.g.setFillType (f);
|
||||
|
|
@ -154,6 +156,8 @@ void DrawablePath::render (const Drawable::RenderingContext& context) const
|
|||
FillType f (strokeFill);
|
||||
if (f.isGradient())
|
||||
f.gradient->multiplyOpacity (context.opacity);
|
||||
else
|
||||
f.setOpacity (f.getOpacity() * context.opacity);
|
||||
|
||||
f.transform = f.transform.followedBy (context.transform);
|
||||
context.g.setFillType (f);
|
||||
|
|
@ -226,7 +230,7 @@ ValueTree DrawablePath::ValueTreeWrapper::getStrokeFillState()
|
|||
return getStrokeFillState();
|
||||
}
|
||||
|
||||
const FillType DrawablePath::ValueTreeWrapper::getMainFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder,
|
||||
const FillType DrawablePath::ValueTreeWrapper::getMainFill (Expression::EvaluationContext* nameFinder,
|
||||
ImageProvider* imageProvider) const
|
||||
{
|
||||
return readFillType (state.getChildWithName (fill), 0, 0, 0, nameFinder, imageProvider);
|
||||
|
|
@ -240,7 +244,7 @@ void DrawablePath::ValueTreeWrapper::setMainFill (const FillType& newFill, const
|
|||
writeFillType (v, newFill, gp1, gp2, gp3, imageProvider, undoManager);
|
||||
}
|
||||
|
||||
const FillType DrawablePath::ValueTreeWrapper::getStrokeFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder,
|
||||
const FillType DrawablePath::ValueTreeWrapper::getStrokeFill (Expression::EvaluationContext* nameFinder,
|
||||
ImageProvider* imageProvider) const
|
||||
{
|
||||
return readFillType (state.getChildWithName (stroke), 0, 0, 0, nameFinder, imageProvider);
|
||||
|
|
@ -368,7 +372,7 @@ const RelativePoint DrawablePath::ValueTreeWrapper::Element::getEndPoint() const
|
|||
return RelativePoint();
|
||||
}
|
||||
|
||||
float DrawablePath::ValueTreeWrapper::Element::getLength (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const
|
||||
float DrawablePath::ValueTreeWrapper::Element::getLength (Expression::EvaluationContext* nameFinder) const
|
||||
{
|
||||
const Identifier i (state.getType());
|
||||
|
||||
|
|
@ -419,7 +423,7 @@ void DrawablePath::ValueTreeWrapper::Element::convertToLine (UndoManager* undoMa
|
|||
}
|
||||
}
|
||||
|
||||
void DrawablePath::ValueTreeWrapper::Element::convertToCubic (RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager)
|
||||
void DrawablePath::ValueTreeWrapper::Element::convertToCubic (Expression::EvaluationContext* nameFinder, UndoManager* undoManager)
|
||||
{
|
||||
const Identifier i (state.getType());
|
||||
|
||||
|
|
@ -473,7 +477,7 @@ static const Point<float> findQuadraticSubdivisionPoint (float proportion, const
|
|||
return mid1 + (mid2 - mid1) * proportion;
|
||||
}
|
||||
|
||||
float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const
|
||||
float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder) const
|
||||
{
|
||||
const Identifier i (state.getType());
|
||||
float bestProp = 0;
|
||||
|
|
@ -529,7 +533,7 @@ float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Po
|
|||
return bestProp;
|
||||
}
|
||||
|
||||
ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager)
|
||||
ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder, UndoManager* undoManager)
|
||||
{
|
||||
ValueTree newTree;
|
||||
const Identifier i (state.getType());
|
||||
|
|
|
|||
|
|
@ -129,14 +129,14 @@ public:
|
|||
public:
|
||||
ValueTreeWrapper (const ValueTree& state);
|
||||
|
||||
const FillType getMainFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder,
|
||||
const FillType getMainFill (Expression::EvaluationContext* nameFinder,
|
||||
ImageProvider* imageProvider) const;
|
||||
ValueTree getMainFillState();
|
||||
void setMainFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, const RelativePoint* gradientPoint3,
|
||||
ImageProvider* imageProvider, UndoManager* undoManager);
|
||||
|
||||
const FillType getStrokeFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder,
|
||||
const FillType getStrokeFill (Expression::EvaluationContext* nameFinder,
|
||||
ImageProvider* imageProvider) const;
|
||||
ValueTree getStrokeFillState();
|
||||
void setStrokeFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
|
|
@ -163,7 +163,7 @@ public:
|
|||
const RelativePoint getStartPoint() const;
|
||||
const RelativePoint getEndPoint() const;
|
||||
void setControlPoint (int index, const RelativePoint& point, UndoManager* undoManager);
|
||||
float getLength (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
float getLength (Expression::EvaluationContext* nameFinder) const;
|
||||
|
||||
ValueTreeWrapper getParent() const;
|
||||
Element getPreviousElement() const;
|
||||
|
|
@ -172,11 +172,11 @@ public:
|
|||
void setModeOfEndPoint (const String& newMode, UndoManager* undoManager);
|
||||
|
||||
void convertToLine (UndoManager* undoManager);
|
||||
void convertToCubic (RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager);
|
||||
void convertToCubic (Expression::EvaluationContext* nameFinder, UndoManager* undoManager);
|
||||
void convertToPathBreak (UndoManager* undoManager);
|
||||
ValueTree insertPoint (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager);
|
||||
ValueTree insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder, UndoManager* undoManager);
|
||||
void removePoint (UndoManager* undoManager);
|
||||
float findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder) const;
|
||||
|
||||
static const Identifier mode, startSubPathElement, closeSubPathElement,
|
||||
lineToElement, quadraticToElement, cubicToElement;
|
||||
|
|
|
|||
|
|
@ -35,166 +35,14 @@ BEGIN_JUCE_NAMESPACE
|
|||
//==============================================================================
|
||||
namespace RelativeCoordinateHelpers
|
||||
{
|
||||
static bool isOrigin (const String& name)
|
||||
{
|
||||
return name.isEmpty()
|
||||
|| name == RelativeCoordinate::Strings::parentLeft
|
||||
|| name == RelativeCoordinate::Strings::parentTop;
|
||||
}
|
||||
|
||||
static const String getExtentAnchorName (const bool isHorizontal) throw()
|
||||
{
|
||||
return isHorizontal ? RelativeCoordinate::Strings::parentRight
|
||||
: RelativeCoordinate::Strings::parentBottom;
|
||||
}
|
||||
|
||||
static const String getObjectName (const String& fullName)
|
||||
{
|
||||
return fullName.upToFirstOccurrenceOf (".", false, false);
|
||||
}
|
||||
|
||||
static const String getEdgeName (const String& fullName)
|
||||
{
|
||||
return fullName.fromFirstOccurrenceOf (".", false, false);
|
||||
}
|
||||
|
||||
static const RelativeCoordinate findCoordinate (const String& name, const RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
return nameFinder != 0 ? nameFinder->findNamedCoordinate (getObjectName (name), getEdgeName (name))
|
||||
: RelativeCoordinate();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct RecursionException : public std::runtime_error
|
||||
{
|
||||
RecursionException() : std::runtime_error ("Recursive RelativeCoordinate expression")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static void skipWhitespace (const juce_wchar* const s, int& i)
|
||||
static void skipComma (const juce_wchar* const s, int& i)
|
||||
{
|
||||
while (CharacterFunctions::isWhitespace (s[i]))
|
||||
++i;
|
||||
}
|
||||
|
||||
static void skipComma (const juce_wchar* const s, int& i)
|
||||
{
|
||||
skipWhitespace (s, i);
|
||||
if (s[i] == ',')
|
||||
++i;
|
||||
}
|
||||
|
||||
static const String readAnchorName (const juce_wchar* const s, int& i)
|
||||
{
|
||||
skipWhitespace (s, i);
|
||||
|
||||
if (CharacterFunctions::isLetter (s[i]) || s[i] == '_')
|
||||
{
|
||||
int start = i;
|
||||
while (CharacterFunctions::isLetterOrDigit (s[i]) || s[i] == '_' || s[i] == '.')
|
||||
++i;
|
||||
|
||||
return String (s + start, i - start);
|
||||
}
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
|
||||
static double readNumber (const juce_wchar* const s, int& i)
|
||||
{
|
||||
skipWhitespace (s, i);
|
||||
|
||||
int start = i;
|
||||
if (CharacterFunctions::isDigit (s[i]) || s[i] == '.' || s[i] == '-')
|
||||
++i;
|
||||
|
||||
while (CharacterFunctions::isDigit (s[i]) || s[i] == '.')
|
||||
++i;
|
||||
|
||||
if ((s[i] == 'e' || s[i] == 'E')
|
||||
&& (CharacterFunctions::isDigit (s[i + 1])
|
||||
|| s[i + 1] == '-'
|
||||
|| s[i + 1] == '+'))
|
||||
{
|
||||
i += 2;
|
||||
|
||||
while (CharacterFunctions::isDigit (s[i]))
|
||||
++i;
|
||||
}
|
||||
|
||||
const double value = String (s + start, i - start).getDoubleValue();
|
||||
while (CharacterFunctions::isWhitespace (s[i]) || s[i] == ',')
|
||||
++i;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static const RelativeCoordinate readNextCoordinate (const juce_wchar* const s, int& i, const bool isHorizontal)
|
||||
{
|
||||
String anchor1 (readAnchorName (s, i));
|
||||
double value = 0;
|
||||
|
||||
if (anchor1.isNotEmpty())
|
||||
{
|
||||
skipWhitespace (s, i);
|
||||
|
||||
if (s[i] == '+')
|
||||
value = readNumber (s, ++i);
|
||||
else if (s[i] == '-')
|
||||
value = -readNumber (s, ++i);
|
||||
|
||||
return RelativeCoordinate (value, anchor1);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = readNumber (s, i);
|
||||
skipWhitespace (s, i);
|
||||
|
||||
if (s[i] == '%')
|
||||
{
|
||||
value /= 100.0;
|
||||
skipWhitespace (s, ++i);
|
||||
String anchor2;
|
||||
|
||||
if (s[i] == '*')
|
||||
{
|
||||
anchor1 = readAnchorName (s, ++i);
|
||||
|
||||
skipWhitespace (s, i);
|
||||
|
||||
if (s[i] == '-' && s[i + 1] == '>')
|
||||
{
|
||||
i += 2;
|
||||
anchor2 = readAnchorName (s, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
anchor2 = anchor1;
|
||||
anchor1 = String::empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
anchor1 = String::empty;
|
||||
anchor2 = getExtentAnchorName (isHorizontal);
|
||||
}
|
||||
|
||||
return RelativeCoordinate (value, anchor1, anchor2);
|
||||
}
|
||||
|
||||
return RelativeCoordinate (value);
|
||||
}
|
||||
}
|
||||
|
||||
static const String limitedAccuracyString (const double n)
|
||||
{
|
||||
if (! (n < -0.001 || n > 0.001)) // to detect NaN and inf as well as for rounding
|
||||
return "0";
|
||||
|
||||
return String (n, 3).trimCharactersAtEnd ("0").trimCharactersAtEnd (".");
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -210,33 +58,38 @@ const String RelativeCoordinate::Strings::parentBottom ("parent.bottom");
|
|||
|
||||
//==============================================================================
|
||||
RelativeCoordinate::RelativeCoordinate()
|
||||
: value (0)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const Expression& term_)
|
||||
: term (term_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const RelativeCoordinate& other)
|
||||
: term (other.term)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate& RelativeCoordinate::operator= (const RelativeCoordinate& other)
|
||||
{
|
||||
term = other.term;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const double absoluteDistanceFromOrigin)
|
||||
: value (absoluteDistanceFromOrigin)
|
||||
: term (absoluteDistanceFromOrigin)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const double absoluteDistance, const String& source)
|
||||
: anchor1 (source.trim()),
|
||||
value (absoluteDistance)
|
||||
RelativeCoordinate::RelativeCoordinate (const String& s)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const double relativeProportion, const String& pos1, const String& pos2)
|
||||
: anchor1 (pos1.trim()),
|
||||
anchor2 (pos2.trim()),
|
||||
value (relativeProportion)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const String& s, const bool isHorizontal)
|
||||
: value (0)
|
||||
{
|
||||
int i = 0;
|
||||
*this = RelativeCoordinateHelpers::readNextCoordinate (s, i, isHorizontal);
|
||||
try
|
||||
{
|
||||
term = Expression (s);
|
||||
}
|
||||
catch (...)
|
||||
{}
|
||||
}
|
||||
|
||||
RelativeCoordinate::~RelativeCoordinate()
|
||||
|
|
@ -245,7 +98,7 @@ RelativeCoordinate::~RelativeCoordinate()
|
|||
|
||||
bool RelativeCoordinate::operator== (const RelativeCoordinate& other) const throw()
|
||||
{
|
||||
return value == other.value && anchor1 == other.anchor1 && anchor2 == other.anchor2;
|
||||
return term.toString() == other.term.toString();
|
||||
}
|
||||
|
||||
bool RelativeCoordinate::operator!= (const RelativeCoordinate& other) const throw()
|
||||
|
|
@ -253,58 +106,31 @@ bool RelativeCoordinate::operator!= (const RelativeCoordinate& other) const thro
|
|||
return ! operator== (other);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const RelativeCoordinate RelativeCoordinate::getAnchorCoordinate1() const
|
||||
{
|
||||
return RelativeCoordinate (0.0, anchor1);
|
||||
}
|
||||
|
||||
const RelativeCoordinate RelativeCoordinate::getAnchorCoordinate2() const
|
||||
{
|
||||
return RelativeCoordinate (0.0, anchor2);
|
||||
}
|
||||
|
||||
double RelativeCoordinate::resolveAnchor (const String& anchorName, const NamedCoordinateFinder* nameFinder, int recursionCounter)
|
||||
{
|
||||
if (RelativeCoordinateHelpers::isOrigin (anchorName))
|
||||
return 0.0;
|
||||
|
||||
return RelativeCoordinateHelpers::findCoordinate (anchorName, nameFinder).resolve (nameFinder, recursionCounter + 1);
|
||||
}
|
||||
|
||||
double RelativeCoordinate::resolve (const NamedCoordinateFinder* nameFinder, int recursionCounter) const
|
||||
{
|
||||
if (recursionCounter > 150)
|
||||
{
|
||||
jassertfalse
|
||||
throw RelativeCoordinateHelpers::RecursionException();
|
||||
}
|
||||
|
||||
const double pos1 = resolveAnchor (anchor1, nameFinder, recursionCounter);
|
||||
|
||||
return isProportional() ? pos1 + (resolveAnchor (anchor2, nameFinder, recursionCounter) - pos1) * value
|
||||
: pos1 + value;
|
||||
}
|
||||
|
||||
double RelativeCoordinate::resolve (const NamedCoordinateFinder* nameFinder) const
|
||||
double RelativeCoordinate::resolve (const Expression::EvaluationContext* context) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return resolve (nameFinder, 0);
|
||||
if (context != 0)
|
||||
return term.evaluate (*context);
|
||||
else
|
||||
return term.evaluate();
|
||||
}
|
||||
catch (RelativeCoordinateHelpers::RecursionException&)
|
||||
catch (...)
|
||||
{}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder* nameFinder) const
|
||||
bool RelativeCoordinate::isRecursive (const Expression::EvaluationContext* context) const
|
||||
{
|
||||
try
|
||||
{
|
||||
(void) resolve (nameFinder, 0);
|
||||
if (context != 0)
|
||||
term.evaluate (*context);
|
||||
else
|
||||
term.evaluate();
|
||||
}
|
||||
catch (RelativeCoordinateHelpers::RecursionException&)
|
||||
catch (...)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -312,153 +138,61 @@ bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder* nameFinder) c
|
|||
return false;
|
||||
}
|
||||
|
||||
void RelativeCoordinate::moveToAbsolute (double newPos, const NamedCoordinateFinder* nameFinder)
|
||||
void RelativeCoordinate::moveToAbsolute (double newPos, const Expression::EvaluationContext* context)
|
||||
{
|
||||
try
|
||||
{
|
||||
const double pos1 = resolveAnchor (anchor1, nameFinder, 0);
|
||||
|
||||
if (isProportional())
|
||||
if (context != 0)
|
||||
{
|
||||
const double size = resolveAnchor (anchor2, nameFinder, 0) - pos1;
|
||||
|
||||
if (size != 0)
|
||||
value = (newPos - pos1) / size;
|
||||
term = term.adjustedToGiveNewResult (newPos, *context);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = newPos - pos1;
|
||||
Expression::EvaluationContext defaultContext;
|
||||
term = term.adjustedToGiveNewResult (newPos, defaultContext);
|
||||
}
|
||||
}
|
||||
catch (RelativeCoordinateHelpers::RecursionException&)
|
||||
catch (...)
|
||||
{}
|
||||
}
|
||||
|
||||
void RelativeCoordinate::toggleProportionality (const NamedCoordinateFinder* nameFinder,
|
||||
const String& proportionalAnchor1, const String& proportionalAnchor2)
|
||||
bool RelativeCoordinate::references (const String& coordName, const Expression::EvaluationContext* context) const
|
||||
{
|
||||
const double oldValue = resolve (nameFinder);
|
||||
try
|
||||
{
|
||||
if (context != 0)
|
||||
return term.referencesSymbol (coordName, *context);
|
||||
|
||||
anchor1 = proportionalAnchor1;
|
||||
anchor2 = isProportional() ? String::empty : proportionalAnchor2;
|
||||
Expression::EvaluationContext defaultContext;
|
||||
return term.referencesSymbol (coordName, defaultContext);
|
||||
}
|
||||
catch (...)
|
||||
{}
|
||||
|
||||
moveToAbsolute (oldValue, nameFinder);
|
||||
}
|
||||
|
||||
bool RelativeCoordinate::references (const String& coordName, const NamedCoordinateFinder* nameFinder) const
|
||||
{
|
||||
using namespace RelativeCoordinateHelpers;
|
||||
|
||||
if (isOrigin (anchor1) && ! isProportional())
|
||||
return isOrigin (coordName);
|
||||
|
||||
return anchor1 == coordName
|
||||
|| anchor2 == coordName
|
||||
|| findCoordinate (anchor1, nameFinder).references (coordName, nameFinder)
|
||||
|| (isProportional() && findCoordinate (anchor2, nameFinder).references (coordName, nameFinder));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RelativeCoordinate::isDynamic() const
|
||||
{
|
||||
return anchor2.isNotEmpty() || ! RelativeCoordinateHelpers::isOrigin (anchor1);
|
||||
return term.usesAnySymbols();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const String RelativeCoordinate::toString() const
|
||||
{
|
||||
using namespace RelativeCoordinateHelpers;
|
||||
return term.toString();
|
||||
}
|
||||
|
||||
if (isProportional())
|
||||
void RelativeCoordinate::renameSymbolIfUsed (const String& oldName, const String& newName,
|
||||
const Expression::EvaluationContext* context)
|
||||
{
|
||||
jassert (newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_."));
|
||||
|
||||
if (term.referencesSymbol (oldName, *context))
|
||||
{
|
||||
const String percent (limitedAccuracyString (value * 100.0));
|
||||
const double oldValue = resolve (context);
|
||||
|
||||
if (isOrigin (anchor1))
|
||||
{
|
||||
if (anchor2 == Strings::parentRight || anchor2 == Strings::parentBottom)
|
||||
return percent + "%";
|
||||
else
|
||||
return percent + "% * " + anchor2;
|
||||
}
|
||||
else
|
||||
return percent + "% * " + anchor1 + " -> " + anchor2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isOrigin (anchor1))
|
||||
return limitedAccuracyString (value);
|
||||
else if (value > 0)
|
||||
return anchor1 + " + " + limitedAccuracyString (value);
|
||||
else if (value < 0)
|
||||
return anchor1 + " - " + limitedAccuracyString (-value);
|
||||
else
|
||||
return anchor1;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const double RelativeCoordinate::getEditableNumber() const
|
||||
{
|
||||
return isProportional() ? value * 100.0 : value;
|
||||
}
|
||||
|
||||
void RelativeCoordinate::setEditableNumber (const double newValue)
|
||||
{
|
||||
value = isProportional() ? newValue / 100.0 : newValue;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const String RelativeCoordinate::getAnchorName1 (const String& returnValueIfOrigin) const
|
||||
{
|
||||
return RelativeCoordinateHelpers::isOrigin (anchor1) ? returnValueIfOrigin : anchor1;
|
||||
}
|
||||
|
||||
const String RelativeCoordinate::getAnchorName2 (const String& returnValueIfOrigin) const
|
||||
{
|
||||
return RelativeCoordinateHelpers::isOrigin (anchor2) ? returnValueIfOrigin : anchor2;
|
||||
}
|
||||
|
||||
void RelativeCoordinate::changeAnchor1 (const String& newAnchorName, const NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
jassert (newAnchorName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_."));
|
||||
|
||||
const double oldValue = resolve (nameFinder);
|
||||
anchor1 = RelativeCoordinateHelpers::isOrigin (newAnchorName) ? String::empty : newAnchorName;
|
||||
moveToAbsolute (oldValue, nameFinder);
|
||||
}
|
||||
|
||||
void RelativeCoordinate::changeAnchor2 (const String& newAnchorName, const NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
jassert (isProportional());
|
||||
jassert (newAnchorName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_."));
|
||||
|
||||
const double oldValue = resolve (nameFinder);
|
||||
anchor2 = RelativeCoordinateHelpers::isOrigin (newAnchorName) ? String::empty : newAnchorName;
|
||||
moveToAbsolute (oldValue, nameFinder);
|
||||
}
|
||||
|
||||
void RelativeCoordinate::renameAnchorIfUsed (const String& oldName, const String& newName, const NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
using namespace RelativeCoordinateHelpers;
|
||||
jassert (oldName.isNotEmpty());
|
||||
jassert (newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_"));
|
||||
|
||||
if (newName.isEmpty())
|
||||
{
|
||||
if (getObjectName (anchor1) == oldName
|
||||
|| getObjectName (anchor2) == oldName)
|
||||
{
|
||||
value = resolve (nameFinder);
|
||||
anchor1 = String::empty;
|
||||
anchor2 = String::empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (getObjectName (anchor1) == oldName)
|
||||
anchor1 = newName + "." + getEdgeName (anchor1);
|
||||
|
||||
if (getObjectName (anchor2) == oldName)
|
||||
anchor2 = newName + "." + getEdgeName (anchor2);
|
||||
term = term.withRenamedSymbol (oldName, newName);
|
||||
moveToAbsolute (oldValue, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -485,9 +219,9 @@ RelativePoint::RelativePoint (const RelativeCoordinate& x_, const RelativeCoordi
|
|||
RelativePoint::RelativePoint (const String& s)
|
||||
{
|
||||
int i = 0;
|
||||
x = RelativeCoordinateHelpers::readNextCoordinate (s, i, true);
|
||||
x = RelativeCoordinate (Expression::parse (s, i));
|
||||
RelativeCoordinateHelpers::skipComma (s, i);
|
||||
y = RelativeCoordinateHelpers::readNextCoordinate (s, i, false);
|
||||
y = RelativeCoordinate (Expression::parse (s, i));
|
||||
}
|
||||
|
||||
bool RelativePoint::operator== (const RelativePoint& other) const throw()
|
||||
|
|
@ -500,16 +234,16 @@ bool RelativePoint::operator!= (const RelativePoint& other) const throw()
|
|||
return ! operator== (other);
|
||||
}
|
||||
|
||||
const Point<float> RelativePoint::resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const
|
||||
const Point<float> RelativePoint::resolve (const Expression::EvaluationContext* context) const
|
||||
{
|
||||
return Point<float> ((float) x.resolve (nameFinder),
|
||||
(float) y.resolve (nameFinder));
|
||||
return Point<float> ((float) x.resolve (context),
|
||||
(float) y.resolve (context));
|
||||
}
|
||||
|
||||
void RelativePoint::moveToAbsolute (const Point<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
||||
void RelativePoint::moveToAbsolute (const Point<float>& newPos, const Expression::EvaluationContext* context)
|
||||
{
|
||||
x.moveToAbsolute (newPos.getX(), nameFinder);
|
||||
y.moveToAbsolute (newPos.getY(), nameFinder);
|
||||
x.moveToAbsolute (newPos.getX(), context);
|
||||
y.moveToAbsolute (newPos.getY(), context);
|
||||
}
|
||||
|
||||
const String RelativePoint::toString() const
|
||||
|
|
@ -517,10 +251,10 @@ const String RelativePoint::toString() const
|
|||
return x.toString() + ", " + y.toString();
|
||||
}
|
||||
|
||||
void RelativePoint::renameAnchorIfUsed (const String& oldName, const String& newName, const RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
||||
void RelativePoint::renameSymbolIfUsed (const String& oldName, const String& newName, const Expression::EvaluationContext* context)
|
||||
{
|
||||
x.renameAnchorIfUsed (oldName, newName, nameFinder);
|
||||
y.renameAnchorIfUsed (oldName, newName, nameFinder);
|
||||
x.renameSymbolIfUsed (oldName, newName, context);
|
||||
y.renameSymbolIfUsed (oldName, newName, context);
|
||||
}
|
||||
|
||||
bool RelativePoint::isDynamic() const
|
||||
|
|
@ -542,22 +276,22 @@ RelativeRectangle::RelativeRectangle (const RelativeCoordinate& left_, const Rel
|
|||
|
||||
RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect, const String& componentName)
|
||||
: left (rect.getX()),
|
||||
right (rect.getWidth(), componentName + "." + RelativeCoordinate::Strings::left),
|
||||
right (componentName + "." + RelativeCoordinate::Strings::left + " + " + String (rect.getWidth())),
|
||||
top (rect.getY()),
|
||||
bottom (rect.getHeight(), componentName + "." + RelativeCoordinate::Strings::top)
|
||||
bottom (componentName + "." + RelativeCoordinate::Strings::top + " + " + String (rect.getHeight()))
|
||||
{
|
||||
}
|
||||
|
||||
RelativeRectangle::RelativeRectangle (const String& s)
|
||||
{
|
||||
int i = 0;
|
||||
left = RelativeCoordinateHelpers::readNextCoordinate (s, i, true);
|
||||
left = RelativeCoordinate (Expression::parse (s, i));
|
||||
RelativeCoordinateHelpers::skipComma (s, i);
|
||||
top = RelativeCoordinateHelpers::readNextCoordinate (s, i, false);
|
||||
top = RelativeCoordinate (Expression::parse (s, i));
|
||||
RelativeCoordinateHelpers::skipComma (s, i);
|
||||
right = RelativeCoordinateHelpers::readNextCoordinate (s, i, true);
|
||||
right = RelativeCoordinate (Expression::parse (s, i));
|
||||
RelativeCoordinateHelpers::skipComma (s, i);
|
||||
bottom = RelativeCoordinateHelpers::readNextCoordinate (s, i, false);
|
||||
bottom = RelativeCoordinate (Expression::parse (s, i));
|
||||
}
|
||||
|
||||
bool RelativeRectangle::operator== (const RelativeRectangle& other) const throw()
|
||||
|
|
@ -570,22 +304,22 @@ bool RelativeRectangle::operator!= (const RelativeRectangle& other) const throw(
|
|||
return ! operator== (other);
|
||||
}
|
||||
|
||||
const Rectangle<float> RelativeRectangle::resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const
|
||||
const Rectangle<float> RelativeRectangle::resolve (const Expression::EvaluationContext* context) const
|
||||
{
|
||||
const double l = left.resolve (nameFinder);
|
||||
const double r = right.resolve (nameFinder);
|
||||
const double t = top.resolve (nameFinder);
|
||||
const double b = bottom.resolve (nameFinder);
|
||||
const double l = left.resolve (context);
|
||||
const double r = right.resolve (context);
|
||||
const double t = top.resolve (context);
|
||||
const double b = bottom.resolve (context);
|
||||
|
||||
return Rectangle<float> ((float) l, (float) t, (float) (r - l), (float) (b - t));
|
||||
}
|
||||
|
||||
void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
||||
void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const Expression::EvaluationContext* context)
|
||||
{
|
||||
left.moveToAbsolute (newPos.getX(), nameFinder);
|
||||
right.moveToAbsolute (newPos.getRight(), nameFinder);
|
||||
top.moveToAbsolute (newPos.getY(), nameFinder);
|
||||
bottom.moveToAbsolute (newPos.getBottom(), nameFinder);
|
||||
left.moveToAbsolute (newPos.getX(), context);
|
||||
right.moveToAbsolute (newPos.getRight(), context);
|
||||
top.moveToAbsolute (newPos.getY(), context);
|
||||
bottom.moveToAbsolute (newPos.getBottom(), context);
|
||||
}
|
||||
|
||||
const String RelativeRectangle::toString() const
|
||||
|
|
@ -593,13 +327,13 @@ const String RelativeRectangle::toString() const
|
|||
return left.toString() + ", " + top.toString() + ", " + right.toString() + ", " + bottom.toString();
|
||||
}
|
||||
|
||||
void RelativeRectangle::renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
||||
void RelativeRectangle::renameSymbolIfUsed (const String& oldName, const String& newName,
|
||||
const Expression::EvaluationContext* context)
|
||||
{
|
||||
left.renameAnchorIfUsed (oldName, newName, nameFinder);
|
||||
right.renameAnchorIfUsed (oldName, newName, nameFinder);
|
||||
top.renameAnchorIfUsed (oldName, newName, nameFinder);
|
||||
bottom.renameAnchorIfUsed (oldName, newName, nameFinder);
|
||||
left.renameSymbolIfUsed (oldName, newName, context);
|
||||
right.renameSymbolIfUsed (oldName, newName, context);
|
||||
top.renameSymbolIfUsed (oldName, newName, context);
|
||||
bottom.renameSymbolIfUsed (oldName, newName, context);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -704,7 +438,7 @@ void RelativePointPath::swapWith (RelativePointPath& other) throw()
|
|||
swapVariables (usesNonZeroWinding, other.usesNonZeroWinding);
|
||||
}
|
||||
|
||||
void RelativePointPath::createPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder)
|
||||
void RelativePointPath::createPath (Path& path, Expression::EvaluationContext* coordFinder)
|
||||
{
|
||||
for (int i = 0; i < elements.size(); ++i)
|
||||
elements.getUnchecked(i)->addToPath (path, coordFinder);
|
||||
|
|
@ -733,7 +467,7 @@ const ValueTree RelativePointPath::StartSubPath::createTree() const
|
|||
return v;
|
||||
}
|
||||
|
||||
void RelativePointPath::StartSubPath::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const
|
||||
void RelativePointPath::StartSubPath::addToPath (Path& path, Expression::EvaluationContext* coordFinder) const
|
||||
{
|
||||
path.startNewSubPath (startPos.resolve (coordFinder));
|
||||
}
|
||||
|
|
@ -755,7 +489,7 @@ const ValueTree RelativePointPath::CloseSubPath::createTree() const
|
|||
return ValueTree (DrawablePath::ValueTreeWrapper::Element::closeSubPathElement);
|
||||
}
|
||||
|
||||
void RelativePointPath::CloseSubPath::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder*) const
|
||||
void RelativePointPath::CloseSubPath::addToPath (Path& path, Expression::EvaluationContext*) const
|
||||
{
|
||||
path.closeSubPath();
|
||||
}
|
||||
|
|
@ -779,7 +513,7 @@ const ValueTree RelativePointPath::LineTo::createTree() const
|
|||
return v;
|
||||
}
|
||||
|
||||
void RelativePointPath::LineTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const
|
||||
void RelativePointPath::LineTo::addToPath (Path& path, Expression::EvaluationContext* coordFinder) const
|
||||
{
|
||||
path.lineTo (endPoint.resolve (coordFinder));
|
||||
}
|
||||
|
|
@ -806,7 +540,7 @@ const ValueTree RelativePointPath::QuadraticTo::createTree() const
|
|||
return v;
|
||||
}
|
||||
|
||||
void RelativePointPath::QuadraticTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const
|
||||
void RelativePointPath::QuadraticTo::addToPath (Path& path, Expression::EvaluationContext* coordFinder) const
|
||||
{
|
||||
path.quadraticTo (controlPoints[0].resolve (coordFinder),
|
||||
controlPoints[1].resolve (coordFinder));
|
||||
|
|
@ -836,7 +570,7 @@ const ValueTree RelativePointPath::CubicTo::createTree() const
|
|||
return v;
|
||||
}
|
||||
|
||||
void RelativePointPath::CubicTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const
|
||||
void RelativePointPath::CubicTo::addToPath (Path& path, Expression::EvaluationContext* coordFinder) const
|
||||
{
|
||||
path.cubicTo (controlPoints[0].resolve (coordFinder),
|
||||
controlPoints[1].resolve (coordFinder),
|
||||
|
|
@ -869,27 +603,27 @@ RelativeParallelogram::~RelativeParallelogram()
|
|||
{
|
||||
}
|
||||
|
||||
void RelativeParallelogram::resolveThreePoints (Point<float>* points, RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const
|
||||
void RelativeParallelogram::resolveThreePoints (Point<float>* points, Expression::EvaluationContext* const coordFinder) const
|
||||
{
|
||||
points[0] = topLeft.resolve (coordFinder);
|
||||
points[1] = topRight.resolve (coordFinder);
|
||||
points[2] = bottomLeft.resolve (coordFinder);
|
||||
}
|
||||
|
||||
void RelativeParallelogram::resolveFourCorners (Point<float>* points, RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const
|
||||
void RelativeParallelogram::resolveFourCorners (Point<float>* points, Expression::EvaluationContext* const coordFinder) const
|
||||
{
|
||||
resolveThreePoints (points, coordFinder);
|
||||
points[3] = points[1] + (points[2] - points[0]);
|
||||
}
|
||||
|
||||
const Rectangle<float> RelativeParallelogram::getBounds (RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const
|
||||
const Rectangle<float> RelativeParallelogram::getBounds (Expression::EvaluationContext* const coordFinder) const
|
||||
{
|
||||
Point<float> points[4];
|
||||
resolveFourCorners (points, coordFinder);
|
||||
return Rectangle<float>::findAreaContainingPoints (points, 4);
|
||||
}
|
||||
|
||||
void RelativeParallelogram::getPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const
|
||||
void RelativeParallelogram::getPath (Path& path, Expression::EvaluationContext* const coordFinder) const
|
||||
{
|
||||
Point<float> points[4];
|
||||
resolveFourCorners (points, coordFinder);
|
||||
|
|
@ -901,7 +635,7 @@ void RelativeParallelogram::getPath (Path& path, RelativeCoordinate::NamedCoordi
|
|||
path.closeSubPath();
|
||||
}
|
||||
|
||||
const AffineTransform RelativeParallelogram::resetToPerpendicular (RelativeCoordinate::NamedCoordinateFinder* const coordFinder)
|
||||
const AffineTransform RelativeParallelogram::resetToPerpendicular (Expression::EvaluationContext* const coordFinder)
|
||||
{
|
||||
Point<float> corners[3];
|
||||
resolveThreePoints (corners, coordFinder);
|
||||
|
|
|
|||
|
|
@ -28,27 +28,14 @@
|
|||
|
||||
#include "juce_Path.h"
|
||||
#include "juce_Rectangle.h"
|
||||
#include "../../../containers/juce_Expression.h"
|
||||
#include "../../../containers/juce_OwnedArray.h"
|
||||
#include "../../../containers/juce_ValueTree.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Expresses a coordinate as an absolute or proportional distance from other
|
||||
named coordinates.
|
||||
|
||||
A RelativeCoordinate represents a position as either:
|
||||
- an absolute distance from the origin
|
||||
- an absolute distance from another named RelativeCoordinate
|
||||
- a proportion of the distance between two other named RelativeCoordinates
|
||||
|
||||
Of course, the coordinates that this one is relative to may themselves be relative
|
||||
to other coordinates, so complex arrangements can be built up (as long as you're careful
|
||||
not to create recursive loops!)
|
||||
|
||||
Rather than keeping pointers to the coordinates that this one is dependent on, it
|
||||
stores their names, and when resolving this coordinate to an absolute value, a
|
||||
NamedCoordinateFinder class is required to retrieve these coordinates by name.
|
||||
Expresses a coordinate as a dynamically evaluated expression.
|
||||
|
||||
@see RelativePoint, RelativeRectangle
|
||||
*/
|
||||
|
|
@ -58,6 +45,9 @@ public:
|
|||
//==============================================================================
|
||||
/** Creates a zero coordinate. */
|
||||
RelativeCoordinate();
|
||||
RelativeCoordinate (const Expression& expression);
|
||||
RelativeCoordinate (const RelativeCoordinate& other);
|
||||
RelativeCoordinate& operator= (const RelativeCoordinate& other);
|
||||
|
||||
/** Creates an absolute position from the parent origin on either the X or Y axis.
|
||||
|
||||
|
|
@ -65,53 +55,16 @@ public:
|
|||
*/
|
||||
RelativeCoordinate (double absoluteDistanceFromOrigin);
|
||||
|
||||
/** Creates an absolute position relative to a named coordinate.
|
||||
|
||||
@param absoluteDistanceFromAnchor the distance to add to the named anchor point
|
||||
@param anchorPoint the name of the coordinate from which this one will be relative. See the constructor
|
||||
notes for a description of the syntax for coordinate names.
|
||||
*/
|
||||
RelativeCoordinate (double absoluteDistanceFromAnchor, const String& anchorPoint);
|
||||
|
||||
/** Creates a relative position between two named points.
|
||||
|
||||
|
||||
@param relativeProportionBetweenAnchors a value between 0 and 1 indicating this coordinate's relative position
|
||||
between anchorPoint1 and anchorPoint2.
|
||||
@param anchorPoint1 the name of the first coordinate from which this one will be relative. See the constructor
|
||||
notes for a description of the syntax for coordinate names.
|
||||
@param anchorPoint2 the name of the first coordinate from which this one will be relative. See the constructor
|
||||
notes for a description of the syntax for coordinate names.
|
||||
*/
|
||||
RelativeCoordinate (double relativeProportionBetweenAnchors, const String& anchorPoint1, const String& anchorPoint2);
|
||||
|
||||
/** Recreates a coordinate from a string description.
|
||||
|
||||
The string can be in one of the following formats:
|
||||
- "123" = 123 pixels from parent origin (this is equivalent to "parent.left + 123"
|
||||
or "parent.top + 123", depending on which axis the coordinate is using)
|
||||
- "anchor" = the same position as the coordinate named "anchor"
|
||||
- "anchor + 123" = the coordinate named "anchor" + 123 pixels
|
||||
- "anchor - 123" = the coordinate named "anchor" - 123 pixels
|
||||
- "50%" = 50% of the distance between the coordinate space's top-left origin and its extent
|
||||
(this is equivalent to "50% * parent.left -> parent.right" or "50% * parent.top -> parent.bottom")
|
||||
- "50% * anchor" = 50% of the distance between the coordinate space's origin and the coordinate named "anchor"
|
||||
(this is equivalent to "50% * parent.left -> anchor" or "50% * parent.top -> anchor")
|
||||
- "50% * anchor1 -> anchor2" = 50% of the distance between the coordinate "anchor1" and the coordinate "anchor2"
|
||||
The string will be parsed by ExpressionParser::parse().
|
||||
|
||||
An anchor name can either be just a single identifier (letters, digits and underscores only - no spaces),
|
||||
e.g. "marker1", or it can be a two-part name in the form "objectName.edge". For example "parent.left" is
|
||||
the origin, or "myComponent.top" is the top edge of a component called "myComponent". The exact names that
|
||||
will be recognised are dependent on the NamedCoordinateFinder that you provide for looking them up, but
|
||||
"parent.left" and "parent.top" are always available, meaning the origin. "parent.right" and "parent.bottom"
|
||||
may also be available if the coordinate space has a fixed size.
|
||||
|
||||
@param stringVersion the string to parse
|
||||
@param stringVersion the expression to use
|
||||
@param isHorizontal this must be true if this is an X coordinate, or false if it's on the Y axis.
|
||||
|
||||
@see toString
|
||||
*/
|
||||
RelativeCoordinate (const String& stringVersion, bool isHorizontal);
|
||||
RelativeCoordinate (const String& stringVersion);
|
||||
|
||||
/** Destructor. */
|
||||
~RelativeCoordinate();
|
||||
|
|
@ -119,46 +72,21 @@ public:
|
|||
bool operator== (const RelativeCoordinate& other) const throw();
|
||||
bool operator!= (const RelativeCoordinate& other) const throw();
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Provides an interface for looking up the position of a named anchor when resolving a RelativeCoordinate.
|
||||
|
||||
When using RelativeCoordinates, to resolve their names you need to provide a subclass of this which
|
||||
can retrieve a coordinate by name.
|
||||
*/
|
||||
class JUCE_API NamedCoordinateFinder
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~NamedCoordinateFinder() {}
|
||||
|
||||
/** Returns the coordinate for a given name.
|
||||
|
||||
The objectName parameter will be the first section of the name, and the edge the name of the second part.
|
||||
E.g. for "parent.right", objectName would be "parent" and edge would be "right". If the name
|
||||
has no dot, the edge parameter will be an empty string.
|
||||
|
||||
This method must be able to resolve "parent.left", "parent.top", "parent.right" and "parent.bottom", as
|
||||
well as any other objects that your application uses.
|
||||
*/
|
||||
virtual const RelativeCoordinate findNamedCoordinate (const String& objectName, const String& edge) const = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Calculates the absolute position of this coordinate.
|
||||
|
||||
You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may
|
||||
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
double resolve (const NamedCoordinateFinder* nameFinder) const;
|
||||
double resolve (const Expression::EvaluationContext* evaluationContext) 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 NamedCoordinateFinder* nameFinder) const;
|
||||
bool references (const String& coordName, const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Returns true if there's a recursive loop when trying to resolve this coordinate's position. */
|
||||
bool isRecursive (const NamedCoordinateFinder* nameFinder) const;
|
||||
bool isRecursive (const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Returns true if this coordinate depends on any other coordinates for its position. */
|
||||
bool isDynamic() const;
|
||||
|
|
@ -170,63 +98,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 NamedCoordinateFinder* nameFinder);
|
||||
|
||||
/** Returns true if the coordinate is calculated as a proportion of the distance between two other points.
|
||||
@see toggleProportionality
|
||||
*/
|
||||
bool isProportional() const throw() { return anchor2.isNotEmpty(); }
|
||||
|
||||
/** Toggles the coordinate between using a proportional or absolute position.
|
||||
Note that calling this will reset the names of any anchor points, and just make the
|
||||
coordinate relative to the parent origin and parent size.
|
||||
*/
|
||||
void toggleProportionality (const NamedCoordinateFinder* nameFinder,
|
||||
const String& proportionalAnchor1, const String& proportionalAnchor2);
|
||||
|
||||
/** Returns a value that can be edited to set this coordinate's position.
|
||||
The meaning of this number depends on the coordinate's mode. If the coordinate is
|
||||
proportional, the number will be a percentage between 0 and 100. If the
|
||||
coordinate is absolute, then it will be the number of pixels from its anchor point.
|
||||
@see setEditableNumber
|
||||
*/
|
||||
const double getEditableNumber() const;
|
||||
|
||||
/** Sets the value that controls this coordinate's position.
|
||||
The meaning of this number depends on the coordinate's mode. If the coordinate is
|
||||
proportional, the number must be a percentage between 0 and 100. If the
|
||||
coordinate is absolute, then it indicates the number of pixels from its anchor point.
|
||||
@see setEditableNumber
|
||||
*/
|
||||
void setEditableNumber (const double newValue);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the name of the first anchor point from which this coordinate is relative.
|
||||
*/
|
||||
const String getAnchorName1 (const String& returnValueIfOrigin) const;
|
||||
|
||||
/** Returns the name of the second anchor point from which this coordinate is relative.
|
||||
The second anchor is only valid if the coordinate is in proportional mode.
|
||||
*/
|
||||
const String getAnchorName2 (const String& returnValueIfOrigin) const;
|
||||
|
||||
/** Returns the first anchor point as a coordinate. */
|
||||
const RelativeCoordinate getAnchorCoordinate1() const;
|
||||
|
||||
/** Returns the first anchor point as a coordinate.
|
||||
The second anchor is only valid if the coordinate is in proportional mode.
|
||||
*/
|
||||
const RelativeCoordinate getAnchorCoordinate2() const;
|
||||
|
||||
/** Changes the first anchor point, keeping the resultant position of this coordinate in
|
||||
the same place it was previously.
|
||||
*/
|
||||
void changeAnchor1 (const String& newAnchor, const NamedCoordinateFinder* nameFinder);
|
||||
|
||||
/** Changes the second anchor point, keeping the resultant position of this coordinate in
|
||||
the same place it was previously.
|
||||
*/
|
||||
void changeAnchor2 (const String& newAnchor, const NamedCoordinateFinder* nameFinder);
|
||||
void moveToAbsolute (double absoluteTargetPosition, const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Tells the coordinate that an object is changing its name or being deleted.
|
||||
|
||||
|
|
@ -235,8 +107,12 @@ public:
|
|||
this coordinate was using it, the coordinate is changed to be relative to the origin
|
||||
instead.
|
||||
*/
|
||||
void renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const NamedCoordinateFinder* nameFinder);
|
||||
void renameSymbolIfUsed (const String& oldName, const String& newName,
|
||||
const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Returns the expression that defines this coordinate. */
|
||||
const Expression& getExpression() const { return term; }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a string which represents this coordinate.
|
||||
|
|
@ -267,11 +143,10 @@ public:
|
|||
|
||||
private:
|
||||
//==============================================================================
|
||||
String anchor1, anchor2;
|
||||
double value;
|
||||
Expression term;
|
||||
|
||||
double resolve (const NamedCoordinateFinder* nameFinder, int recursionCounter) const;
|
||||
static double resolveAnchor (const String& anchorName, const NamedCoordinateFinder* nameFinder, int recursionCounter);
|
||||
// double resolve (const Expression::EvaluationContext* evaluationContext, int recursionCounter) const;
|
||||
// static double resolveAnchor (const String& anchorName, const Expression::EvaluationContext* evaluationContext, int recursionCounter);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -308,10 +183,10 @@ public:
|
|||
|
||||
/** Calculates the absolute position of this point.
|
||||
|
||||
You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may
|
||||
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
const Point<float> resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
const Point<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Changes the values of this point's coordinates to make it resolve to the specified position.
|
||||
|
||||
|
|
@ -319,7 +194,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 RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
void moveToAbsolute (const Point<float>& newPos, const Expression::EvaluationContext* 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
|
||||
|
|
@ -331,8 +206,8 @@ public:
|
|||
/** Tells the point that an object is changing its name or being deleted.
|
||||
This calls RelativeCoordinate::renameAnchorIfUsed() on its X and Y coordinates.
|
||||
*/
|
||||
void renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
void renameSymbolIfUsed (const String& oldName, const String& newName,
|
||||
const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Returns true if this point depends on any other coordinates for its position. */
|
||||
bool isDynamic() const;
|
||||
|
|
@ -378,10 +253,10 @@ public:
|
|||
//==============================================================================
|
||||
/** Calculates the absolute position of this rectangle.
|
||||
|
||||
You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may
|
||||
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
const Rectangle<float> resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
const Rectangle<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Changes the values of this rectangle's coordinates to make it resolve to the specified position.
|
||||
|
||||
|
|
@ -389,7 +264,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 RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
void moveToAbsolute (const Rectangle<float>& newPos, const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Returns a string which represents this point.
|
||||
This returns a comma-separated list of coordinates, in the order left, top, right, bottom. For details of
|
||||
|
|
@ -399,10 +274,10 @@ public:
|
|||
const String toString() const;
|
||||
|
||||
/** Tells the rectangle that an object is changing its name or being deleted.
|
||||
This calls RelativeCoordinate::renameAnchorIfUsed() on the rectangle's coordinates.
|
||||
This calls RelativeCoordinate::renameSymbolIfUsed() on the rectangle's coordinates.
|
||||
*/
|
||||
void renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
void renameSymbolIfUsed (const String& oldName, const String& newName,
|
||||
const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
// The actual rectangle coords...
|
||||
RelativeCoordinate left, right, top, bottom;
|
||||
|
|
@ -430,7 +305,7 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/** Resolves this points in this path and adds them to a normal Path object. */
|
||||
void createPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder);
|
||||
void createPath (Path& path, Expression::EvaluationContext* coordFinder);
|
||||
|
||||
/** Returns true if the path contains any non-fixed points. */
|
||||
bool containsAnyDynamicPoints() const;
|
||||
|
|
@ -464,7 +339,7 @@ public:
|
|||
ElementBase (ElementType type);
|
||||
virtual ~ElementBase() {}
|
||||
virtual const ValueTree createTree() const = 0;
|
||||
virtual void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const = 0;
|
||||
virtual void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const = 0;
|
||||
virtual RelativePoint* getControlPoints (int& numPoints) = 0;
|
||||
|
||||
const ElementType type;
|
||||
|
|
@ -480,7 +355,7 @@ public:
|
|||
StartSubPath (const RelativePoint& pos);
|
||||
~StartSubPath() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
RelativePoint startPos;
|
||||
|
|
@ -496,7 +371,7 @@ public:
|
|||
CloseSubPath();
|
||||
~CloseSubPath() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
private:
|
||||
|
|
@ -510,7 +385,7 @@ public:
|
|||
LineTo (const RelativePoint& endPoint);
|
||||
~LineTo() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
RelativePoint endPoint;
|
||||
|
|
@ -526,7 +401,7 @@ public:
|
|||
QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint);
|
||||
~QuadraticTo() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
RelativePoint controlPoints[2];
|
||||
|
|
@ -542,7 +417,7 @@ public:
|
|||
CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint);
|
||||
~CubicTo() {}
|
||||
const ValueTree createTree() const;
|
||||
void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void addToPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
RelativePoint* getControlPoints (int& numPoints);
|
||||
|
||||
RelativePoint controlPoints[3];
|
||||
|
|
@ -580,11 +455,11 @@ public:
|
|||
~RelativeParallelogram();
|
||||
|
||||
//==============================================================================
|
||||
void resolveThreePoints (Point<float>* points, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void resolveFourCorners (Point<float>* points, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
const Rectangle<float> getBounds (RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
void getPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const;
|
||||
const AffineTransform resetToPerpendicular (RelativeCoordinate::NamedCoordinateFinder* coordFinder);
|
||||
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);
|
||||
|
||||
bool operator== (const RelativeParallelogram& other) const throw();
|
||||
bool operator!= (const RelativeParallelogram& other) const throw();
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@
|
|||
#ifndef __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__
|
||||
#include "containers/juce_ElementComparator.h"
|
||||
#endif
|
||||
#ifndef __JUCE_EXPRESSION_JUCEHEADER__
|
||||
#include "containers/juce_Expression.h"
|
||||
#endif
|
||||
#ifndef __JUCE_HEAPBLOCK_JUCEHEADER__
|
||||
#include "containers/juce_HeapBlock.h"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -167,8 +167,6 @@ public:
|
|||
[renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval];
|
||||
|
||||
[view setOpenGLContext: renderContext];
|
||||
[renderContext setView: view];
|
||||
|
||||
[format release];
|
||||
|
||||
viewHolder = new NSViewComponentInternal (view, component);
|
||||
|
|
@ -192,6 +190,10 @@ public:
|
|||
bool makeActive() const throw()
|
||||
{
|
||||
jassert (renderContext != 0);
|
||||
|
||||
if ([renderContext view] != view)
|
||||
[renderContext setView: view];
|
||||
|
||||
[view makeActive];
|
||||
return isActive();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -479,8 +479,7 @@ void XmlDocument::readChildElements (XmlElement* parent)
|
|||
++len;
|
||||
}
|
||||
|
||||
XmlElement* const e = new XmlElement ((int) 0);
|
||||
e->setText (String (inputStart, len));
|
||||
XmlElement* const e = XmlElement::createTextElement (String (inputStart, len));
|
||||
|
||||
if (lastChildNode != 0)
|
||||
lastChildNode->nextElement = e;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue