diff --git a/amalgamation/juce_amalgamated_template.cpp b/amalgamation/juce_amalgamated_template.cpp index 2628e59bff..649ef824e1 100644 --- a/amalgamation/juce_amalgamated_template.cpp +++ b/amalgamation/juce_amalgamated_template.cpp @@ -319,6 +319,7 @@ #include "../src/gui/components/windows/juce_ThreadWithProgressWindow.cpp" #include "../src/gui/components/windows/juce_TooltipWindow.cpp" #include "../src/gui/components/windows/juce_TopLevelWindow.cpp" + #include "../src/gui/graphics/geometry/juce_RelativeCoordinate.cpp" #endif #if JUCE_BUILD_MISC // (put these in misc to balance the file sizes and avoid problems in iphone build) @@ -352,7 +353,6 @@ #include "../src/gui/graphics/geometry/juce_PathStrokeType.cpp" #include "../src/gui/graphics/geometry/juce_PositionedRectangle.cpp" #include "../src/gui/graphics/geometry/juce_RectangleList.cpp" - #include "../src/gui/graphics/geometry/juce_RelativeCoordinate.cpp" #include "../src/gui/graphics/imaging/juce_Image.cpp" #include "../src/gui/graphics/imaging/juce_ImageCache.cpp" #include "../src/gui/graphics/imaging/juce_ImageConvolutionKernel.cpp" diff --git a/extras/Jucer (experimental)/Source/Application/jucer_Application.h b/extras/Jucer (experimental)/Source/Application/jucer_Application.h index 78d77a088b..3236bbde09 100644 --- a/extras/Jucer (experimental)/Source/Application/jucer_Application.h +++ b/extras/Jucer (experimental)/Source/Application/jucer_Application.h @@ -292,7 +292,7 @@ public: commands.addArray (ids, numElementsInArray (ids)); } - void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result) + void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result) { switch (commandID) { diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 0f814ea39b..a2b744951b 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -37826,6 +37826,10 @@ MessageManager::~MessageManager() throw() doPlatformSpecificShutdown(); + // If you hit this assertion, then you've probably leaked a Component or some other + // kind of MessageListener object... + jassert (messageListeners.size() == 0); + jassert (instance == this); instance = 0; // do this last in case this instance is still needed by doPlatformSpecificShutdown() } @@ -78799,6 +78803,905 @@ TopLevelWindow* TopLevelWindow::getActiveTopLevelWindow() throw() END_JUCE_NAMESPACE /*** End of inlined file: juce_TopLevelWindow.cpp ***/ + +/*** Start of inlined file: juce_RelativeCoordinate.cpp ***/ +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) + { + 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 ("."); + } +} + +const String RelativeCoordinate::Strings::parent ("parent"); +const String RelativeCoordinate::Strings::left ("left"); +const String RelativeCoordinate::Strings::right ("right"); +const String RelativeCoordinate::Strings::top ("top"); +const String RelativeCoordinate::Strings::bottom ("bottom"); +const String RelativeCoordinate::Strings::parentLeft ("parent.left"); +const String RelativeCoordinate::Strings::parentTop ("parent.top"); +const String RelativeCoordinate::Strings::parentRight ("parent.right"); +const String RelativeCoordinate::Strings::parentBottom ("parent.bottom"); + +RelativeCoordinate::RelativeCoordinate() + : value (0) +{ +} + +RelativeCoordinate::RelativeCoordinate (const double absoluteDistanceFromOrigin) + : value (absoluteDistanceFromOrigin) +{ +} + +RelativeCoordinate::RelativeCoordinate (const double absoluteDistance, const String& source) + : anchor1 (source.trim()), + value (absoluteDistance) +{ +} + +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); +} + +RelativeCoordinate::~RelativeCoordinate() +{ +} + +bool RelativeCoordinate::operator== (const RelativeCoordinate& other) const throw() +{ + return value == other.value && anchor1 == other.anchor1 && anchor2 == other.anchor2; +} + +bool RelativeCoordinate::operator!= (const RelativeCoordinate& other) const throw() +{ + 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 +{ + try + { + return resolve (nameFinder, 0); + } + catch (RelativeCoordinateHelpers::RecursionException&) + {} + + return 0.0; +} + +bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder* nameFinder) const +{ + try + { + (void) resolve (nameFinder, 0); + } + catch (RelativeCoordinateHelpers::RecursionException&) + { + return true; + } + + return false; +} + +void RelativeCoordinate::moveToAbsolute (double newPos, const NamedCoordinateFinder* nameFinder) +{ + try + { + const double pos1 = resolveAnchor (anchor1, nameFinder, 0); + + if (isProportional()) + { + const double size = resolveAnchor (anchor2, nameFinder, 0) - pos1; + + if (size != 0) + value = (newPos - pos1) / size; + } + else + { + value = newPos - pos1; + } + } + catch (RelativeCoordinateHelpers::RecursionException&) + {} +} + +void RelativeCoordinate::toggleProportionality (const NamedCoordinateFinder* nameFinder, + const String& proportionalAnchor1, const String& proportionalAnchor2) +{ + const double oldValue = resolve (nameFinder); + + anchor1 = proportionalAnchor1; + anchor2 = isProportional() ? String::empty : proportionalAnchor2; + + 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)); +} + +bool RelativeCoordinate::isDynamic() const +{ + return anchor2.isNotEmpty() || ! RelativeCoordinateHelpers::isOrigin (anchor1); +} + +const String RelativeCoordinate::toString() const +{ + using namespace RelativeCoordinateHelpers; + + if (isProportional()) + { + const String percent (limitedAccuracyString (value * 100.0)); + + 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); + } +} + +RelativePoint::RelativePoint() +{ +} + +RelativePoint::RelativePoint (const Point& absolutePoint) + : x (absolutePoint.getX()), y (absolutePoint.getY()) +{ +} + +RelativePoint::RelativePoint (const float x_, const float y_) + : x (x_), y (y_) +{ +} + +RelativePoint::RelativePoint (const RelativeCoordinate& x_, const RelativeCoordinate& y_) + : x (x_), y (y_) +{ +} + +RelativePoint::RelativePoint (const String& s) +{ + int i = 0; + x = RelativeCoordinateHelpers::readNextCoordinate (s, i, true); + RelativeCoordinateHelpers::skipComma (s, i); + y = RelativeCoordinateHelpers::readNextCoordinate (s, i, false); +} + +bool RelativePoint::operator== (const RelativePoint& other) const throw() +{ + return x == other.x && y == other.y; +} + +bool RelativePoint::operator!= (const RelativePoint& other) const throw() +{ + return ! operator== (other); +} + +const Point RelativePoint::resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const +{ + return Point ((float) x.resolve (nameFinder), + (float) y.resolve (nameFinder)); +} + +void RelativePoint::moveToAbsolute (const Point& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) +{ + x.moveToAbsolute (newPos.getX(), nameFinder); + y.moveToAbsolute (newPos.getY(), nameFinder); +} + +const String RelativePoint::toString() const +{ + return x.toString() + ", " + y.toString(); +} + +void RelativePoint::renameAnchorIfUsed (const String& oldName, const String& newName, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) +{ + x.renameAnchorIfUsed (oldName, newName, nameFinder); + y.renameAnchorIfUsed (oldName, newName, nameFinder); +} + +bool RelativePoint::isDynamic() const +{ + return x.isDynamic() || y.isDynamic(); +} + +RelativeRectangle::RelativeRectangle() +{ +} + +RelativeRectangle::RelativeRectangle (const RelativeCoordinate& left_, const RelativeCoordinate& right_, + const RelativeCoordinate& top_, const RelativeCoordinate& bottom_) + : left (left_), right (right_), top (top_), bottom (bottom_) +{ +} + +RelativeRectangle::RelativeRectangle (const Rectangle& rect, const String& componentName) + : left (rect.getX()), + right (rect.getWidth(), componentName + "." + RelativeCoordinate::Strings::left), + top (rect.getY()), + bottom (rect.getHeight(), componentName + "." + RelativeCoordinate::Strings::top) +{ +} + +RelativeRectangle::RelativeRectangle (const String& s) +{ + int i = 0; + left = RelativeCoordinateHelpers::readNextCoordinate (s, i, true); + RelativeCoordinateHelpers::skipComma (s, i); + top = RelativeCoordinateHelpers::readNextCoordinate (s, i, false); + RelativeCoordinateHelpers::skipComma (s, i); + right = RelativeCoordinateHelpers::readNextCoordinate (s, i, true); + RelativeCoordinateHelpers::skipComma (s, i); + bottom = RelativeCoordinateHelpers::readNextCoordinate (s, i, false); +} + +bool RelativeRectangle::operator== (const RelativeRectangle& other) const throw() +{ + return left == other.left && top == other.top && right == other.right && bottom == other.bottom; +} + +bool RelativeRectangle::operator!= (const RelativeRectangle& other) const throw() +{ + return ! operator== (other); +} + +const Rectangle RelativeRectangle::resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) 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); + + return Rectangle ((float) l, (float) t, (float) (r - l), (float) (b - t)); +} + +void RelativeRectangle::moveToAbsolute (const Rectangle& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) +{ + left.moveToAbsolute (newPos.getX(), nameFinder); + right.moveToAbsolute (newPos.getRight(), nameFinder); + top.moveToAbsolute (newPos.getY(), nameFinder); + bottom.moveToAbsolute (newPos.getBottom(), nameFinder); +} + +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) +{ + left.renameAnchorIfUsed (oldName, newName, nameFinder); + right.renameAnchorIfUsed (oldName, newName, nameFinder); + top.renameAnchorIfUsed (oldName, newName, nameFinder); + bottom.renameAnchorIfUsed (oldName, newName, nameFinder); +} + +RelativePointPath::RelativePointPath() + : usesNonZeroWinding (true), + containsDynamicPoints (false) +{ +} + +RelativePointPath::RelativePointPath (const RelativePointPath& other) + : usesNonZeroWinding (true), + containsDynamicPoints (false) +{ + ValueTree state (DrawablePath::valueTreeType); + other.writeTo (state, 0); + parse (state); +} + +RelativePointPath::RelativePointPath (const ValueTree& drawable) + : usesNonZeroWinding (true), + containsDynamicPoints (false) +{ + parse (drawable); +} + +RelativePointPath::RelativePointPath (const Path& path) +{ + usesNonZeroWinding = path.isUsingNonZeroWinding(); + + Path::Iterator i (path); + + while (i.next()) + { + switch (i.elementType) + { + case Path::Iterator::startNewSubPath: elements.add (new StartSubPath (RelativePoint (i.x1, i.y1))); break; + case Path::Iterator::lineTo: elements.add (new LineTo (RelativePoint (i.x1, i.y1))); break; + case Path::Iterator::quadraticTo: elements.add (new QuadraticTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2))); break; + case Path::Iterator::cubicTo: elements.add (new CubicTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2), RelativePoint (i.x3, i.y3))); break; + case Path::Iterator::closePath: elements.add (new CloseSubPath()); break; + default: jassertfalse; break; + } + } +} + +void RelativePointPath::writeTo (ValueTree state, UndoManager* undoManager) const +{ + DrawablePath::ValueTreeWrapper wrapper (state); + wrapper.setUsesNonZeroWinding (usesNonZeroWinding, undoManager); + + ValueTree pathTree (wrapper.getPathState()); + pathTree.removeAllChildren (undoManager); + + for (int i = 0; i < elements.size(); ++i) + pathTree.addChild (elements.getUnchecked(i)->createTree(), -1, undoManager); +} + +void RelativePointPath::parse (const ValueTree& state) +{ + DrawablePath::ValueTreeWrapper wrapper (state); + usesNonZeroWinding = wrapper.usesNonZeroWinding(); + RelativePoint points[3]; + + const ValueTree pathTree (wrapper.getPathState()); + const int num = pathTree.getNumChildren(); + for (int i = 0; i < num; ++i) + { + const DrawablePath::ValueTreeWrapper::Element e (pathTree.getChild(i)); + + const int numCps = e.getNumControlPoints(); + for (int j = 0; j < numCps; ++j) + { + points[j] = e.getControlPoint (j); + containsDynamicPoints = containsDynamicPoints || points[j].isDynamic(); + } + + const Identifier type (e.getType()); + + if (type == DrawablePath::ValueTreeWrapper::Element::startSubPathElement) + elements.add (new StartSubPath (points[0])); + else if (type == DrawablePath::ValueTreeWrapper::Element::closeSubPathElement) + elements.add (new CloseSubPath()); + else if (type == DrawablePath::ValueTreeWrapper::Element::lineToElement) + elements.add (new LineTo (points[0])); + else if (type == DrawablePath::ValueTreeWrapper::Element::quadraticToElement) + elements.add (new QuadraticTo (points[0], points[1])); + else if (type == DrawablePath::ValueTreeWrapper::Element::cubicToElement) + elements.add (new CubicTo (points[0], points[1], points[2])); + else + jassertfalse; + } +} + +RelativePointPath::~RelativePointPath() +{ +} + +void RelativePointPath::swapWith (RelativePointPath& other) throw() +{ + elements.swapWithArray (other.elements); + swapVariables (usesNonZeroWinding, other.usesNonZeroWinding); +} + +void RelativePointPath::createPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) +{ + for (int i = 0; i < elements.size(); ++i) + elements.getUnchecked(i)->addToPath (path, coordFinder); +} + +bool RelativePointPath::containsAnyDynamicPoints() const +{ + return containsDynamicPoints; +} + +RelativePointPath::ElementBase::ElementBase (const ElementType type_) : type (type_) +{ +} + +RelativePointPath::StartSubPath::StartSubPath (const RelativePoint& pos) + : ElementBase (startSubPathElement), startPos (pos) +{ +} + +const ValueTree RelativePointPath::StartSubPath::createTree() const +{ + ValueTree v (DrawablePath::ValueTreeWrapper::Element::startSubPathElement); + v.setProperty (DrawablePath::ValueTreeWrapper::point1, startPos.toString(), 0); + return v; +} + +void RelativePointPath::StartSubPath::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const +{ + path.startNewSubPath (startPos.resolve (coordFinder)); +} + +RelativePoint* RelativePointPath::StartSubPath::getControlPoints (int& numPoints) +{ + numPoints = 1; + return &startPos; +} + +RelativePointPath::CloseSubPath::CloseSubPath() + : ElementBase (closeSubPathElement) +{ +} + +const ValueTree RelativePointPath::CloseSubPath::createTree() const +{ + return ValueTree (DrawablePath::ValueTreeWrapper::Element::closeSubPathElement); +} + +void RelativePointPath::CloseSubPath::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder*) const +{ + path.closeSubPath(); +} + +RelativePoint* RelativePointPath::CloseSubPath::getControlPoints (int& numPoints) +{ + numPoints = 0; + return 0; +} + +RelativePointPath::LineTo::LineTo (const RelativePoint& endPoint_) + : ElementBase (lineToElement), endPoint (endPoint_) +{ +} + +const ValueTree RelativePointPath::LineTo::createTree() const +{ + ValueTree v (DrawablePath::ValueTreeWrapper::Element::lineToElement); + v.setProperty (DrawablePath::ValueTreeWrapper::point1, endPoint.toString(), 0); + return v; +} + +void RelativePointPath::LineTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const +{ + path.lineTo (endPoint.resolve (coordFinder)); +} + +RelativePoint* RelativePointPath::LineTo::getControlPoints (int& numPoints) +{ + numPoints = 1; + return &endPoint; +} + +RelativePointPath::QuadraticTo::QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint) + : ElementBase (quadraticToElement) +{ + controlPoints[0] = controlPoint; + controlPoints[1] = endPoint; +} + +const ValueTree RelativePointPath::QuadraticTo::createTree() const +{ + ValueTree v (DrawablePath::ValueTreeWrapper::Element::quadraticToElement); + v.setProperty (DrawablePath::ValueTreeWrapper::point1, controlPoints[0].toString(), 0); + v.setProperty (DrawablePath::ValueTreeWrapper::point2, controlPoints[1].toString(), 0); + return v; +} + +void RelativePointPath::QuadraticTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const +{ + path.quadraticTo (controlPoints[0].resolve (coordFinder), + controlPoints[1].resolve (coordFinder)); +} + +RelativePoint* RelativePointPath::QuadraticTo::getControlPoints (int& numPoints) +{ + numPoints = 2; + return controlPoints; +} + +RelativePointPath::CubicTo::CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint) + : ElementBase (cubicToElement) +{ + controlPoints[0] = controlPoint1; + controlPoints[1] = controlPoint2; + controlPoints[2] = endPoint; +} + +const ValueTree RelativePointPath::CubicTo::createTree() const +{ + ValueTree v (DrawablePath::ValueTreeWrapper::Element::cubicToElement); + v.setProperty (DrawablePath::ValueTreeWrapper::point1, controlPoints[0].toString(), 0); + v.setProperty (DrawablePath::ValueTreeWrapper::point2, controlPoints[1].toString(), 0); + v.setProperty (DrawablePath::ValueTreeWrapper::point3, controlPoints[2].toString(), 0); + return v; +} + +void RelativePointPath::CubicTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const +{ + path.cubicTo (controlPoints[0].resolve (coordFinder), + controlPoints[1].resolve (coordFinder), + controlPoints[2].resolve (coordFinder)); +} + +RelativePoint* RelativePointPath::CubicTo::getControlPoints (int& numPoints) +{ + numPoints = 3; + return controlPoints; +} + +RelativeParallelogram::RelativeParallelogram() +{ +} + +RelativeParallelogram::RelativeParallelogram (const RelativePoint& topLeft_, const RelativePoint& topRight_, const RelativePoint& bottomLeft_) + : topLeft (topLeft_), topRight (topRight_), bottomLeft (bottomLeft_) +{ +} + +RelativeParallelogram::RelativeParallelogram (const String& topLeft_, const String& topRight_, const String& bottomLeft_) + : topLeft (topLeft_), topRight (topRight_), bottomLeft (bottomLeft_) +{ +} + +RelativeParallelogram::~RelativeParallelogram() +{ +} + +void RelativeParallelogram::resolveThreePoints (Point* points, RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const +{ + points[0] = topLeft.resolve (coordFinder); + points[1] = topRight.resolve (coordFinder); + points[2] = bottomLeft.resolve (coordFinder); +} + +void RelativeParallelogram::resolveFourCorners (Point* points, RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const +{ + resolveThreePoints (points, coordFinder); + points[3] = points[1] + (points[2] - points[0]); +} + +const Rectangle RelativeParallelogram::getBounds (RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const +{ + Point points[4]; + resolveFourCorners (points, coordFinder); + return Rectangle::findAreaContainingPoints (points, 4); +} + +void RelativeParallelogram::getPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const +{ + Point points[4]; + resolveFourCorners (points, coordFinder); + + path.startNewSubPath (points[0]); + path.lineTo (points[1]); + path.lineTo (points[3]); + path.lineTo (points[2]); + path.closeSubPath(); +} + +const AffineTransform RelativeParallelogram::resetToPerpendicular (RelativeCoordinate::NamedCoordinateFinder* const coordFinder) +{ + Point corners[3]; + resolveThreePoints (corners, coordFinder); + + const Line top (corners[0], corners[1]); + const Line left (corners[0], corners[2]); + const Point newTopRight (corners[0] + Point (top.getLength(), 0.0f)); + const Point newBottomLeft (corners[0] + Point (0.0f, left.getLength())); + + topRight.moveToAbsolute (newTopRight, coordFinder); + bottomLeft.moveToAbsolute (newBottomLeft, coordFinder); + + return AffineTransform::fromTargetPoints (corners[0].getX(), corners[0].getY(), corners[0].getX(), corners[0].getY(), + corners[1].getX(), corners[1].getY(), newTopRight.getX(), newTopRight.getY(), + corners[2].getX(), corners[2].getY(), newBottomLeft.getX(), newBottomLeft.getY()); +} + +bool RelativeParallelogram::operator== (const RelativeParallelogram& other) const throw() +{ + return topLeft == other.topLeft && topRight == other.topRight && bottomLeft == other.bottomLeft; +} + +bool RelativeParallelogram::operator!= (const RelativeParallelogram& other) const throw() +{ + return ! operator== (other); +} + +const Point RelativeParallelogram::getInternalCoordForPoint (const Point* const corners, Point target) throw() +{ + const Point tr (corners[1] - corners[0]); + const Point bl (corners[2] - corners[0]); + target -= corners[0]; + + return Point (Line (Point(), tr).getIntersection (Line (target, target - bl)).getDistanceFromOrigin(), + Line (Point(), bl).getIntersection (Line (target, target - tr)).getDistanceFromOrigin()); +} + +const Point RelativeParallelogram::getPointForInternalCoord (const Point* const corners, const Point& point) throw() +{ + return corners[0] + + Line (Point(), corners[1] - corners[0]).getPointAlongLine (point.getX()) + + Line (Point(), corners[2] - corners[0]).getPointAlongLine (point.getY()); +} + +END_JUCE_NAMESPACE +/*** End of inlined file: juce_RelativeCoordinate.cpp ***/ + #endif #if JUCE_BUILD_MISC // (put these in misc to balance the file sizes and avoid problems in iphone build) @@ -93341,905 +94244,6 @@ END_JUCE_NAMESPACE /*** End of inlined file: juce_RectangleList.cpp ***/ -/*** Start of inlined file: juce_RelativeCoordinate.cpp ***/ -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) - { - 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 ("."); - } -} - -const String RelativeCoordinate::Strings::parent ("parent"); -const String RelativeCoordinate::Strings::left ("left"); -const String RelativeCoordinate::Strings::right ("right"); -const String RelativeCoordinate::Strings::top ("top"); -const String RelativeCoordinate::Strings::bottom ("bottom"); -const String RelativeCoordinate::Strings::parentLeft ("parent.left"); -const String RelativeCoordinate::Strings::parentTop ("parent.top"); -const String RelativeCoordinate::Strings::parentRight ("parent.right"); -const String RelativeCoordinate::Strings::parentBottom ("parent.bottom"); - -RelativeCoordinate::RelativeCoordinate() - : value (0) -{ -} - -RelativeCoordinate::RelativeCoordinate (const double absoluteDistanceFromOrigin) - : value (absoluteDistanceFromOrigin) -{ -} - -RelativeCoordinate::RelativeCoordinate (const double absoluteDistance, const String& source) - : anchor1 (source.trim()), - value (absoluteDistance) -{ -} - -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); -} - -RelativeCoordinate::~RelativeCoordinate() -{ -} - -bool RelativeCoordinate::operator== (const RelativeCoordinate& other) const throw() -{ - return value == other.value && anchor1 == other.anchor1 && anchor2 == other.anchor2; -} - -bool RelativeCoordinate::operator!= (const RelativeCoordinate& other) const throw() -{ - 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 -{ - try - { - return resolve (nameFinder, 0); - } - catch (RelativeCoordinateHelpers::RecursionException&) - {} - - return 0.0; -} - -bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder* nameFinder) const -{ - try - { - (void) resolve (nameFinder, 0); - } - catch (RelativeCoordinateHelpers::RecursionException&) - { - return true; - } - - return false; -} - -void RelativeCoordinate::moveToAbsolute (double newPos, const NamedCoordinateFinder* nameFinder) -{ - try - { - const double pos1 = resolveAnchor (anchor1, nameFinder, 0); - - if (isProportional()) - { - const double size = resolveAnchor (anchor2, nameFinder, 0) - pos1; - - if (size != 0) - value = (newPos - pos1) / size; - } - else - { - value = newPos - pos1; - } - } - catch (RelativeCoordinateHelpers::RecursionException&) - {} -} - -void RelativeCoordinate::toggleProportionality (const NamedCoordinateFinder* nameFinder, - const String& proportionalAnchor1, const String& proportionalAnchor2) -{ - const double oldValue = resolve (nameFinder); - - anchor1 = proportionalAnchor1; - anchor2 = isProportional() ? String::empty : proportionalAnchor2; - - 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)); -} - -bool RelativeCoordinate::isDynamic() const -{ - return anchor2.isNotEmpty() || ! RelativeCoordinateHelpers::isOrigin (anchor1); -} - -const String RelativeCoordinate::toString() const -{ - using namespace RelativeCoordinateHelpers; - - if (isProportional()) - { - const String percent (limitedAccuracyString (value * 100.0)); - - 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); - } -} - -RelativePoint::RelativePoint() -{ -} - -RelativePoint::RelativePoint (const Point& absolutePoint) - : x (absolutePoint.getX()), y (absolutePoint.getY()) -{ -} - -RelativePoint::RelativePoint (const float x_, const float y_) - : x (x_), y (y_) -{ -} - -RelativePoint::RelativePoint (const RelativeCoordinate& x_, const RelativeCoordinate& y_) - : x (x_), y (y_) -{ -} - -RelativePoint::RelativePoint (const String& s) -{ - int i = 0; - x = RelativeCoordinateHelpers::readNextCoordinate (s, i, true); - RelativeCoordinateHelpers::skipComma (s, i); - y = RelativeCoordinateHelpers::readNextCoordinate (s, i, false); -} - -bool RelativePoint::operator== (const RelativePoint& other) const throw() -{ - return x == other.x && y == other.y; -} - -bool RelativePoint::operator!= (const RelativePoint& other) const throw() -{ - return ! operator== (other); -} - -const Point RelativePoint::resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const -{ - return Point ((float) x.resolve (nameFinder), - (float) y.resolve (nameFinder)); -} - -void RelativePoint::moveToAbsolute (const Point& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) -{ - x.moveToAbsolute (newPos.getX(), nameFinder); - y.moveToAbsolute (newPos.getY(), nameFinder); -} - -const String RelativePoint::toString() const -{ - return x.toString() + ", " + y.toString(); -} - -void RelativePoint::renameAnchorIfUsed (const String& oldName, const String& newName, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) -{ - x.renameAnchorIfUsed (oldName, newName, nameFinder); - y.renameAnchorIfUsed (oldName, newName, nameFinder); -} - -bool RelativePoint::isDynamic() const -{ - return x.isDynamic() || y.isDynamic(); -} - -RelativeRectangle::RelativeRectangle() -{ -} - -RelativeRectangle::RelativeRectangle (const RelativeCoordinate& left_, const RelativeCoordinate& right_, - const RelativeCoordinate& top_, const RelativeCoordinate& bottom_) - : left (left_), right (right_), top (top_), bottom (bottom_) -{ -} - -RelativeRectangle::RelativeRectangle (const Rectangle& rect, const String& componentName) - : left (rect.getX()), - right (rect.getWidth(), componentName + "." + RelativeCoordinate::Strings::left), - top (rect.getY()), - bottom (rect.getHeight(), componentName + "." + RelativeCoordinate::Strings::top) -{ -} - -RelativeRectangle::RelativeRectangle (const String& s) -{ - int i = 0; - left = RelativeCoordinateHelpers::readNextCoordinate (s, i, true); - RelativeCoordinateHelpers::skipComma (s, i); - top = RelativeCoordinateHelpers::readNextCoordinate (s, i, false); - RelativeCoordinateHelpers::skipComma (s, i); - right = RelativeCoordinateHelpers::readNextCoordinate (s, i, true); - RelativeCoordinateHelpers::skipComma (s, i); - bottom = RelativeCoordinateHelpers::readNextCoordinate (s, i, false); -} - -bool RelativeRectangle::operator== (const RelativeRectangle& other) const throw() -{ - return left == other.left && top == other.top && right == other.right && bottom == other.bottom; -} - -bool RelativeRectangle::operator!= (const RelativeRectangle& other) const throw() -{ - return ! operator== (other); -} - -const Rectangle RelativeRectangle::resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) 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); - - return Rectangle ((float) l, (float) t, (float) (r - l), (float) (b - t)); -} - -void RelativeRectangle::moveToAbsolute (const Rectangle& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) -{ - left.moveToAbsolute (newPos.getX(), nameFinder); - right.moveToAbsolute (newPos.getRight(), nameFinder); - top.moveToAbsolute (newPos.getY(), nameFinder); - bottom.moveToAbsolute (newPos.getBottom(), nameFinder); -} - -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) -{ - left.renameAnchorIfUsed (oldName, newName, nameFinder); - right.renameAnchorIfUsed (oldName, newName, nameFinder); - top.renameAnchorIfUsed (oldName, newName, nameFinder); - bottom.renameAnchorIfUsed (oldName, newName, nameFinder); -} - -RelativePointPath::RelativePointPath() - : usesNonZeroWinding (true), - containsDynamicPoints (false) -{ -} - -RelativePointPath::RelativePointPath (const RelativePointPath& other) - : usesNonZeroWinding (true), - containsDynamicPoints (false) -{ - ValueTree state (DrawablePath::valueTreeType); - other.writeTo (state, 0); - parse (state); -} - -RelativePointPath::RelativePointPath (const ValueTree& drawable) - : usesNonZeroWinding (true), - containsDynamicPoints (false) -{ - parse (drawable); -} - -RelativePointPath::RelativePointPath (const Path& path) -{ - usesNonZeroWinding = path.isUsingNonZeroWinding(); - - Path::Iterator i (path); - - while (i.next()) - { - switch (i.elementType) - { - case Path::Iterator::startNewSubPath: elements.add (new StartSubPath (RelativePoint (i.x1, i.y1))); break; - case Path::Iterator::lineTo: elements.add (new LineTo (RelativePoint (i.x1, i.y1))); break; - case Path::Iterator::quadraticTo: elements.add (new QuadraticTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2))); break; - case Path::Iterator::cubicTo: elements.add (new CubicTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2), RelativePoint (i.x3, i.y3))); break; - case Path::Iterator::closePath: elements.add (new CloseSubPath()); break; - default: jassertfalse; break; - } - } -} - -void RelativePointPath::writeTo (ValueTree state, UndoManager* undoManager) const -{ - DrawablePath::ValueTreeWrapper wrapper (state); - wrapper.setUsesNonZeroWinding (usesNonZeroWinding, undoManager); - - ValueTree pathTree (wrapper.getPathState()); - pathTree.removeAllChildren (undoManager); - - for (int i = 0; i < elements.size(); ++i) - pathTree.addChild (elements.getUnchecked(i)->createTree(), -1, undoManager); -} - -void RelativePointPath::parse (const ValueTree& state) -{ - DrawablePath::ValueTreeWrapper wrapper (state); - usesNonZeroWinding = wrapper.usesNonZeroWinding(); - RelativePoint points[3]; - - const ValueTree pathTree (wrapper.getPathState()); - const int num = pathTree.getNumChildren(); - for (int i = 0; i < num; ++i) - { - const DrawablePath::ValueTreeWrapper::Element e (pathTree.getChild(i)); - - const int numCps = e.getNumControlPoints(); - for (int j = 0; j < numCps; ++j) - { - points[j] = e.getControlPoint (j); - containsDynamicPoints = containsDynamicPoints || points[j].isDynamic(); - } - - const Identifier type (e.getType()); - - if (type == DrawablePath::ValueTreeWrapper::Element::startSubPathElement) - elements.add (new StartSubPath (points[0])); - else if (type == DrawablePath::ValueTreeWrapper::Element::closeSubPathElement) - elements.add (new CloseSubPath()); - else if (type == DrawablePath::ValueTreeWrapper::Element::lineToElement) - elements.add (new LineTo (points[0])); - else if (type == DrawablePath::ValueTreeWrapper::Element::quadraticToElement) - elements.add (new QuadraticTo (points[0], points[1])); - else if (type == DrawablePath::ValueTreeWrapper::Element::cubicToElement) - elements.add (new CubicTo (points[0], points[1], points[2])); - else - jassertfalse; - } -} - -RelativePointPath::~RelativePointPath() -{ -} - -void RelativePointPath::swapWith (RelativePointPath& other) throw() -{ - elements.swapWithArray (other.elements); - swapVariables (usesNonZeroWinding, other.usesNonZeroWinding); -} - -void RelativePointPath::createPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) -{ - for (int i = 0; i < elements.size(); ++i) - elements.getUnchecked(i)->addToPath (path, coordFinder); -} - -bool RelativePointPath::containsAnyDynamicPoints() const -{ - return containsDynamicPoints; -} - -RelativePointPath::ElementBase::ElementBase (const ElementType type_) : type (type_) -{ -} - -RelativePointPath::StartSubPath::StartSubPath (const RelativePoint& pos) - : ElementBase (startSubPathElement), startPos (pos) -{ -} - -const ValueTree RelativePointPath::StartSubPath::createTree() const -{ - ValueTree v (DrawablePath::ValueTreeWrapper::Element::startSubPathElement); - v.setProperty (DrawablePath::ValueTreeWrapper::point1, startPos.toString(), 0); - return v; -} - -void RelativePointPath::StartSubPath::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const -{ - path.startNewSubPath (startPos.resolve (coordFinder)); -} - -RelativePoint* RelativePointPath::StartSubPath::getControlPoints (int& numPoints) -{ - numPoints = 1; - return &startPos; -} - -RelativePointPath::CloseSubPath::CloseSubPath() - : ElementBase (closeSubPathElement) -{ -} - -const ValueTree RelativePointPath::CloseSubPath::createTree() const -{ - return ValueTree (DrawablePath::ValueTreeWrapper::Element::closeSubPathElement); -} - -void RelativePointPath::CloseSubPath::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder*) const -{ - path.closeSubPath(); -} - -RelativePoint* RelativePointPath::CloseSubPath::getControlPoints (int& numPoints) -{ - numPoints = 0; - return 0; -} - -RelativePointPath::LineTo::LineTo (const RelativePoint& endPoint_) - : ElementBase (lineToElement), endPoint (endPoint_) -{ -} - -const ValueTree RelativePointPath::LineTo::createTree() const -{ - ValueTree v (DrawablePath::ValueTreeWrapper::Element::lineToElement); - v.setProperty (DrawablePath::ValueTreeWrapper::point1, endPoint.toString(), 0); - return v; -} - -void RelativePointPath::LineTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const -{ - path.lineTo (endPoint.resolve (coordFinder)); -} - -RelativePoint* RelativePointPath::LineTo::getControlPoints (int& numPoints) -{ - numPoints = 1; - return &endPoint; -} - -RelativePointPath::QuadraticTo::QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint) - : ElementBase (quadraticToElement) -{ - controlPoints[0] = controlPoint; - controlPoints[1] = endPoint; -} - -const ValueTree RelativePointPath::QuadraticTo::createTree() const -{ - ValueTree v (DrawablePath::ValueTreeWrapper::Element::quadraticToElement); - v.setProperty (DrawablePath::ValueTreeWrapper::point1, controlPoints[0].toString(), 0); - v.setProperty (DrawablePath::ValueTreeWrapper::point2, controlPoints[1].toString(), 0); - return v; -} - -void RelativePointPath::QuadraticTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const -{ - path.quadraticTo (controlPoints[0].resolve (coordFinder), - controlPoints[1].resolve (coordFinder)); -} - -RelativePoint* RelativePointPath::QuadraticTo::getControlPoints (int& numPoints) -{ - numPoints = 2; - return controlPoints; -} - -RelativePointPath::CubicTo::CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint) - : ElementBase (cubicToElement) -{ - controlPoints[0] = controlPoint1; - controlPoints[1] = controlPoint2; - controlPoints[2] = endPoint; -} - -const ValueTree RelativePointPath::CubicTo::createTree() const -{ - ValueTree v (DrawablePath::ValueTreeWrapper::Element::cubicToElement); - v.setProperty (DrawablePath::ValueTreeWrapper::point1, controlPoints[0].toString(), 0); - v.setProperty (DrawablePath::ValueTreeWrapper::point2, controlPoints[1].toString(), 0); - v.setProperty (DrawablePath::ValueTreeWrapper::point3, controlPoints[2].toString(), 0); - return v; -} - -void RelativePointPath::CubicTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const -{ - path.cubicTo (controlPoints[0].resolve (coordFinder), - controlPoints[1].resolve (coordFinder), - controlPoints[2].resolve (coordFinder)); -} - -RelativePoint* RelativePointPath::CubicTo::getControlPoints (int& numPoints) -{ - numPoints = 3; - return controlPoints; -} - -RelativeParallelogram::RelativeParallelogram() -{ -} - -RelativeParallelogram::RelativeParallelogram (const RelativePoint& topLeft_, const RelativePoint& topRight_, const RelativePoint& bottomLeft_) - : topLeft (topLeft_), topRight (topRight_), bottomLeft (bottomLeft_) -{ -} - -RelativeParallelogram::RelativeParallelogram (const String& topLeft_, const String& topRight_, const String& bottomLeft_) - : topLeft (topLeft_), topRight (topRight_), bottomLeft (bottomLeft_) -{ -} - -RelativeParallelogram::~RelativeParallelogram() -{ -} - -void RelativeParallelogram::resolveThreePoints (Point* points, RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const -{ - points[0] = topLeft.resolve (coordFinder); - points[1] = topRight.resolve (coordFinder); - points[2] = bottomLeft.resolve (coordFinder); -} - -void RelativeParallelogram::resolveFourCorners (Point* points, RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const -{ - resolveThreePoints (points, coordFinder); - points[3] = points[1] + (points[2] - points[0]); -} - -const Rectangle RelativeParallelogram::getBounds (RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const -{ - Point points[4]; - resolveFourCorners (points, coordFinder); - return Rectangle::findAreaContainingPoints (points, 4); -} - -void RelativeParallelogram::getPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* const coordFinder) const -{ - Point points[4]; - resolveFourCorners (points, coordFinder); - - path.startNewSubPath (points[0]); - path.lineTo (points[1]); - path.lineTo (points[3]); - path.lineTo (points[2]); - path.closeSubPath(); -} - -const AffineTransform RelativeParallelogram::resetToPerpendicular (RelativeCoordinate::NamedCoordinateFinder* const coordFinder) -{ - Point corners[3]; - resolveThreePoints (corners, coordFinder); - - const Line top (corners[0], corners[1]); - const Line left (corners[0], corners[2]); - const Point newTopRight (corners[0] + Point (top.getLength(), 0.0f)); - const Point newBottomLeft (corners[0] + Point (0.0f, left.getLength())); - - topRight.moveToAbsolute (newTopRight, coordFinder); - bottomLeft.moveToAbsolute (newBottomLeft, coordFinder); - - return AffineTransform::fromTargetPoints (corners[0].getX(), corners[0].getY(), corners[0].getX(), corners[0].getY(), - corners[1].getX(), corners[1].getY(), newTopRight.getX(), newTopRight.getY(), - corners[2].getX(), corners[2].getY(), newBottomLeft.getX(), newBottomLeft.getY()); -} - -bool RelativeParallelogram::operator== (const RelativeParallelogram& other) const throw() -{ - return topLeft == other.topLeft && topRight == other.topRight && bottomLeft == other.bottomLeft; -} - -bool RelativeParallelogram::operator!= (const RelativeParallelogram& other) const throw() -{ - return ! operator== (other); -} - -const Point RelativeParallelogram::getInternalCoordForPoint (const Point* const corners, Point target) throw() -{ - const Point tr (corners[1] - corners[0]); - const Point bl (corners[2] - corners[0]); - target -= corners[0]; - - return Point (Line (Point(), tr).getIntersection (Line (target, target - bl)).getDistanceFromOrigin(), - Line (Point(), bl).getIntersection (Line (target, target - tr)).getDistanceFromOrigin()); -} - -const Point RelativeParallelogram::getPointForInternalCoord (const Point* const corners, const Point& point) throw() -{ - return corners[0] - + Line (Point(), corners[1] - corners[0]).getPointAlongLine (point.getX()) - + Line (Point(), corners[2] - corners[0]).getPointAlongLine (point.getY()); -} - -END_JUCE_NAMESPACE -/*** End of inlined file: juce_RelativeCoordinate.cpp ***/ - - /*** Start of inlined file: juce_Image.cpp ***/ BEGIN_JUCE_NAMESPACE diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 66bf3d2a84..9d0b9e20f0 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 33 +#define JUCE_BUILDNUMBER 34 /** Current Juce version number. @@ -5870,6 +5870,10 @@ public: #elif JUCE_GCC #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics + #if JUCE_IPHONE + #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 // (on the iphone, the 64-bit ops will compile but not link) + #endif + #else #define JUCE_ATOMICS_WINDOWS 1 // Windows with intrinsics @@ -42704,7 +42708,6 @@ public: /** Creates an absolute position from the parent origin on either the X or Y axis. @param absoluteDistanceFromOrigin the distance from the origin - @param isHorizontal this must be true if this is an X coordinate, or false if it's on the Y axis. */ RelativeCoordinate (double absoluteDistanceFromOrigin); diff --git a/src/core/juce_Atomic.h b/src/core/juce_Atomic.h index 96d65385b9..e847415349 100644 --- a/src/core/juce_Atomic.h +++ b/src/core/juce_Atomic.h @@ -169,6 +169,11 @@ public: //============================================================================== #elif JUCE_GCC #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics + + #if JUCE_IPHONE + #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 // (on the iphone, the 64-bit ops will compile but not link) + #endif + //============================================================================== #else #define JUCE_ATOMICS_WINDOWS 1 // Windows with intrinsics diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index ec8a1c2c15..a35501b76c 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 33 +#define JUCE_BUILDNUMBER 34 /** Current Juce version number. diff --git a/src/events/juce_MessageManager.cpp b/src/events/juce_MessageManager.cpp index cced9ca31b..96b58de9cb 100644 --- a/src/events/juce_MessageManager.cpp +++ b/src/events/juce_MessageManager.cpp @@ -60,6 +60,10 @@ MessageManager::~MessageManager() throw() doPlatformSpecificShutdown(); + // If you hit this assertion, then you've probably leaked a Component or some other + // kind of MessageListener object... + jassert (messageListeners.size() == 0); + jassert (instance == this); instance = 0; // do this last in case this instance is still needed by doPlatformSpecificShutdown() } diff --git a/src/gui/graphics/geometry/juce_RelativeCoordinate.h b/src/gui/graphics/geometry/juce_RelativeCoordinate.h index cdae708cc2..062a549595 100644 --- a/src/gui/graphics/geometry/juce_RelativeCoordinate.h +++ b/src/gui/graphics/geometry/juce_RelativeCoordinate.h @@ -62,7 +62,6 @@ public: /** Creates an absolute position from the parent origin on either the X or Y axis. @param absoluteDistanceFromOrigin the distance from the origin - @param isHorizontal this must be true if this is an X coordinate, or false if it's on the Y axis. */ RelativeCoordinate (double absoluteDistanceFromOrigin);