| @@ -88,7 +88,7 @@ public: | |||
| if (owner.clipToImageToggle->getToggleState()) | |||
| clipToImage (g); | |||
| g.fillCheckerBoard (0, 0, getWidth(), getHeight(), 50, 50, | |||
| g.fillCheckerBoard (getLocalBounds(), 50, 50, | |||
| Colour (0xffdddddd), Colours::transparentBlack); | |||
| switch (owner.testTypeComboBox->getSelectedId()) | |||
| @@ -387,8 +387,7 @@ private: | |||
| { | |||
| if (getNumChildComponents() == 0) | |||
| { | |||
| g.fillCheckerBoard (0, 0, getWidth(), getHeight(), | |||
| 50, 50, | |||
| g.fillCheckerBoard (getLocalBounds(), 50, 50, | |||
| Colour::greyLevel (0.9f).withAlpha (0.4f), | |||
| Colour::greyLevel (0.8f).withAlpha (0.4f)); | |||
| } | |||
| @@ -297,8 +297,7 @@ private: | |||
| void paint (Graphics& g) | |||
| { | |||
| g.fillCheckerBoard (0, 0, getWidth(), getHeight(), | |||
| 50, 50, | |||
| g.fillCheckerBoard (getLocalBounds(), 50, 50, | |||
| Colours::lightgrey.withAlpha (0.5f), | |||
| Colours::darkgrey.withAlpha (0.5f)); | |||
| } | |||
| @@ -513,7 +513,7 @@ void PaintRoutine::fillWithBackground (Graphics& g, const bool drawOpaqueBackgro | |||
| { | |||
| if ((! backgroundColour.isOpaque()) && drawOpaqueBackground) | |||
| { | |||
| g.fillCheckerBoard (0, 0, g.getClipBounds().getRight(), g.getClipBounds().getBottom(), | |||
| g.fillCheckerBoard (Rectangle<int> (0, 0, g.getClipBounds().getRight(), g.getClipBounds().getBottom()), | |||
| 50, 50, | |||
| Colour (0xffdddddd).overlaidWith (backgroundColour), | |||
| Colour (0xffffffff).overlaidWith (backgroundColour)); | |||
| @@ -328,7 +328,7 @@ void JucerFillType::loadImage (JucerDocument* const document) | |||
| image = Image (Image::RGB, 100, 100, true); | |||
| Graphics g (image); | |||
| g.fillCheckerBoard (0, 0, image.getWidth(), image.getHeight(), | |||
| g.fillCheckerBoard (image.getBounds(), | |||
| image.getWidth() / 2, image.getHeight() / 2, | |||
| Colours::white, Colours::lightgrey); | |||
| @@ -49,7 +49,7 @@ public: | |||
| { | |||
| g.fillAll (Colours::grey); | |||
| g.fillCheckerBoard (2, 2, getWidth() - 4, getHeight() - 4, | |||
| g.fillCheckerBoard (getLocalBounds().reduced (2, 2), | |||
| 10, 10, | |||
| Colour (0xffdddddd).overlaidWith (colour), | |||
| Colour (0xffffffff).overlaidWith (colour)); | |||
| @@ -16643,6 +16643,15 @@ ValueTree ValueTree::getParent() const | |||
| return ValueTree (object != 0 ? object->parent : (SharedObject*) 0); | |||
| } | |||
| ValueTree ValueTree::getSibling (const int delta) const | |||
| { | |||
| if (object == 0 || object->parent == 0) | |||
| return invalid; | |||
| const int index = object->parent->indexOf (*this) + delta; | |||
| return ValueTree (static_cast <SharedObject*> (object->children [index])); | |||
| } | |||
| const var& ValueTree::operator[] (const Identifier& name) const | |||
| { | |||
| return object == 0 ? var::null : object->getProperty (name); | |||
| @@ -39263,7 +39272,7 @@ const Point<int> Component::relativePositionToOtherComponent (const Component* c | |||
| return p; | |||
| } | |||
| void Component::setBounds (int x, int y, int w, int h) | |||
| void Component::setBounds (const int x, const int y, int w, int h) | |||
| { | |||
| // if component methods are being called from threads other than the message | |||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | |||
| @@ -39397,18 +39406,16 @@ void Component::setCentreRelative (const float x, const float y) | |||
| void Component::centreWithSize (const int width, const int height) | |||
| { | |||
| setBounds ((getParentWidth() - width) / 2, | |||
| (getParentHeight() - height) / 2, | |||
| width, | |||
| height); | |||
| const Rectangle<int> parentArea (getParentOrMainMonitorBounds()); | |||
| setBounds (parentArea.getCentreX() - width / 2, | |||
| parentArea.getCentreY() - height / 2, | |||
| width, height); | |||
| } | |||
| void Component::setBoundsInset (const BorderSize& borders) | |||
| { | |||
| setBounds (borders.getLeft(), | |||
| borders.getTop(), | |||
| getParentWidth() - (borders.getLeftAndRight()), | |||
| getParentHeight() - (borders.getTopAndBottom())); | |||
| setBounds (borders.subtractedFrom (getParentOrMainMonitorBounds())); | |||
| } | |||
| void Component::setBoundsToFit (int x, int y, int width, int height, | |||
| @@ -40239,7 +40246,13 @@ void Component::colourChanged() | |||
| const Rectangle<int> Component::getLocalBounds() const throw() | |||
| { | |||
| return Rectangle<int> (0, 0, getWidth(), getHeight()); | |||
| return Rectangle<int> (getWidth(), getHeight()); | |||
| } | |||
| const Rectangle<int> Component::getParentOrMainMonitorBounds() const | |||
| { | |||
| return parentComponent_ != 0 ? parentComponent_->getLocalBounds() | |||
| : Desktop::getInstance().getMainMonitorArea(); | |||
| } | |||
| const Rectangle<int> Component::getUnclippedArea() const | |||
| @@ -41081,8 +41094,8 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point<int>& | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| BailOutChecker checker (this); | |||
| const float wheelIncrementX = amountX * (1.0f / 256.0f); | |||
| const float wheelIncrementY = amountY * (1.0f / 256.0f); | |||
| const float wheelIncrementX = amountX / 256.0f; | |||
| const float wheelIncrementY = amountY / 256.0f; | |||
| const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
| this, this, time, relativePos, time, 0, false); | |||
| @@ -41521,8 +41534,7 @@ const Point<int> Component::getMouseXYRelative() const | |||
| const Rectangle<int> Component::getParentMonitorArea() const | |||
| { | |||
| return Desktop::getInstance() | |||
| .getMonitorAreaContaining (relativePositionToGlobal (Point<int> (getWidth() / 2, | |||
| getHeight() / 2))); | |||
| .getMonitorAreaContaining (relativePositionToGlobal (getLocalBounds().getCentre())); | |||
| } | |||
| void Component::addKeyListener (KeyListener* const newListener) | |||
| @@ -73473,8 +73485,7 @@ public: | |||
| { | |||
| const Colour colour (owner->getSwatchColour (index)); | |||
| g.fillCheckerBoard (0, 0, getWidth(), getHeight(), | |||
| 6, 6, | |||
| g.fillCheckerBoard (getLocalBounds(), 6, 6, | |||
| Colour (0xffdddddd).overlaidWith (colour), | |||
| Colour (0xffffffff).overlaidWith (colour)); | |||
| } | |||
| @@ -73517,7 +73528,6 @@ ColourSelector::ColourSelector (const int flags_, | |||
| colourSpace (0), | |||
| hueSelector (0), | |||
| flags (flags_), | |||
| topSpace (0), | |||
| edgeGap (edgeGap_) | |||
| { | |||
| // not much point having a selector with no components in it! | |||
| @@ -73623,7 +73633,7 @@ void ColourSelector::update() | |||
| } | |||
| if ((flags & showColourAtTop) != 0) | |||
| repaint (0, edgeGap, getWidth(), topSpace - edgeGap); | |||
| repaint (previewArea); | |||
| sendChangeMessage (this); | |||
| } | |||
| @@ -73636,15 +73646,14 @@ void ColourSelector::paint (Graphics& g) | |||
| { | |||
| const Colour currentColour (getCurrentColour()); | |||
| g.fillCheckerBoard (edgeGap, edgeGap, getWidth() - edgeGap - edgeGap, topSpace - edgeGap - edgeGap, | |||
| 10, 10, | |||
| g.fillCheckerBoard (previewArea, 10, 10, | |||
| Colour (0xffdddddd).overlaidWith (currentColour), | |||
| Colour (0xffffffff).overlaidWith (currentColour)); | |||
| g.setColour (Colours::white.overlaidWith (currentColour).contrasting()); | |||
| g.setFont (14.0f, true); | |||
| g.drawText (currentColour.toDisplayString ((flags & showAlphaChannel) != 0), | |||
| 0, edgeGap, getWidth(), topSpace - edgeGap * 2, | |||
| previewArea.getX(), previewArea.getY(), previewArea.getWidth(), previewArea.getHeight(), | |||
| Justification::centred, false); | |||
| } | |||
| @@ -73674,7 +73683,9 @@ void ColourSelector::resized() | |||
| const int swatchSpace = numSwatches > 0 ? edgeGap + swatchHeight * ((numSwatches + 7) / swatchesPerRow) : 0; | |||
| const int sliderSpace = ((flags & showSliders) != 0) ? jmin (22 * numSliders + edgeGap, proportionOfHeight (0.3f)) : 0; | |||
| topSpace = ((flags & showColourAtTop) != 0) ? jmin (30 + edgeGap * 2, proportionOfHeight (0.2f)) : edgeGap; | |||
| const int topSpace = ((flags & showColourAtTop) != 0) ? jmin (30 + edgeGap * 2, proportionOfHeight (0.2f)) : edgeGap; | |||
| previewArea.setBounds (edgeGap, edgeGap, getWidth() - edgeGap * 2, topSpace - edgeGap * 2); | |||
| int y = topSpace; | |||
| @@ -77606,8 +77617,8 @@ ResizableWindow::~ResizableWindow() | |||
| { | |||
| resizableCorner = 0; | |||
| resizableBorder = 0; | |||
| deleteAndZero (contentComponent); // (avoid using a scoped pointer for this, so that it survives | |||
| // external deletion of the content comp) | |||
| delete static_cast <Component*> (contentComponent); | |||
| contentComponent = 0; | |||
| // have you been adding your own components directly to this window..? tut tut tut. | |||
| // Read the instructions for using a ResizableWindow! | |||
| @@ -77635,6 +77646,9 @@ void ResizableWindow::setContentComponent (Component* const newContentComponent, | |||
| if (deleteOldOne) | |||
| delete static_cast <Component*> (contentComponent); // (avoid using a scoped pointer for this, so that it survives | |||
| // external deletion of the content comp) | |||
| else | |||
| removeChildComponent (contentComponent); | |||
| contentComponent = newContentComponent; | |||
| Component::addAndMakeVisible (contentComponent); | |||
| @@ -77726,12 +77740,13 @@ void ResizableWindow::childBoundsChanged (Component* child) | |||
| void ResizableWindow::activeWindowStatusChanged() | |||
| { | |||
| const BorderSize borders (getContentComponentBorder()); | |||
| const BorderSize border (getContentComponentBorder()); | |||
| repaint (0, 0, getWidth(), borders.getTop()); | |||
| repaint (0, borders.getTop(), borders.getLeft(), getHeight() - borders.getBottom() - borders.getTop()); | |||
| repaint (0, getHeight() - borders.getBottom(), getWidth(), borders.getBottom()); | |||
| repaint (getWidth() - borders.getRight(), borders.getTop(), borders.getRight(), getHeight() - borders.getBottom() - borders.getTop()); | |||
| Rectangle<int> area (getLocalBounds()); | |||
| repaint (area.removeFromTop (border.getTop())); | |||
| repaint (area.removeFromLeft (border.getLeft())); | |||
| repaint (area.removeFromRight (border.getRight())); | |||
| repaint (area.removeFromBottom (border.getBottom())); | |||
| } | |||
| void ResizableWindow::setResizable (const bool shouldBeResizable, | |||
| @@ -80984,7 +80999,7 @@ void Graphics::drawArrow (const Line<float>& line, const float lineThickness, co | |||
| fillPath (p); | |||
| } | |||
| void Graphics::fillCheckerBoard (int x, int y, int width, int height, | |||
| void Graphics::fillCheckerBoard (const Rectangle<int>& area, | |||
| const int checkWidth, const int checkHeight, | |||
| const Colour& colour1, const Colour& colour2) const | |||
| { | |||
| @@ -80997,29 +81012,29 @@ void Graphics::fillCheckerBoard (int x, int y, int width, int height, | |||
| if (colour1 == colour2) | |||
| { | |||
| context->setFill (colour1); | |||
| context->fillRect (Rectangle<int> (x, y, width, height), false); | |||
| context->fillRect (area, false); | |||
| } | |||
| else | |||
| { | |||
| const Rectangle<int> clip (context->getClipBounds()); | |||
| const Rectangle<int> clipped (context->getClipBounds().getIntersection (area)); | |||
| const int right = jmin (x + width, clip.getRight()); | |||
| const int bottom = jmin (y + height, clip.getBottom()); | |||
| int cy = 0; | |||
| while (y < bottom) | |||
| if (! clipped.isEmpty()) | |||
| { | |||
| int cx = cy; | |||
| context->clipToRectangle (clipped); | |||
| const int startX = area.getX() + ((clipped.getX() - area.getX()) / checkWidth) * checkWidth; | |||
| const int startY = area.getY() + ((clipped.getY() - area.getY()) / checkHeight) * checkHeight; | |||
| const int right = clipped.getRight(); | |||
| const int bottom = clipped.getBottom(); | |||
| for (int xx = x; xx < right; xx += checkWidth) | |||
| for (int i = 0; i < 2; ++i) | |||
| { | |||
| context->setFill (((cx++ & 1) == 0) ? colour1 : colour2); | |||
| context->fillRect (Rectangle<int> (xx, y, jmin (checkWidth, right - xx), jmin (checkHeight, bottom - y)), | |||
| false); | |||
| } | |||
| context->setFill (i == 0 ? colour1 : colour2); | |||
| ++cy; | |||
| y += checkHeight; | |||
| int cy = i; | |||
| for (int y = startY; y < bottom; y += checkHeight) | |||
| for (int x = startX + (cy++ & 1) * checkWidth; x < right; x += checkWidth * 2) | |||
| context->fillRect (Rectangle<int> (x, y, checkWidth, checkHeight), false); | |||
| } | |||
| } | |||
| } | |||
| @@ -81272,7 +81287,7 @@ LowLevelGraphicsPostScriptRenderer::LowLevelGraphicsPostScriptRenderer (OutputSt | |||
| needToClip (true) | |||
| { | |||
| stateStack.add (new SavedState()); | |||
| stateStack.getLast()->clip = Rectangle<int> (0, 0, totalWidth_, totalHeight_); | |||
| stateStack.getLast()->clip = Rectangle<int> (totalWidth_, totalHeight_); | |||
| const float scale = jmin ((520.0f / totalWidth_), (750.0f / totalHeight)); | |||
| @@ -85575,6 +85590,7 @@ void DrawablePath::ValueTreeWrapper::setUsesNonZeroWinding (bool b, UndoManager* | |||
| state.setProperty (nonZeroWinding, b, undoManager); | |||
| } | |||
| const Identifier DrawablePath::ValueTreeWrapper::Element::mode ("mode"); | |||
| const Identifier DrawablePath::ValueTreeWrapper::Element::startSubPathElement ("Move"); | |||
| const Identifier DrawablePath::ValueTreeWrapper::Element::closeSubPathElement ("Close"); | |||
| const Identifier DrawablePath::ValueTreeWrapper::Element::lineToElement ("Line"); | |||
| @@ -85595,6 +85611,11 @@ DrawablePath::ValueTreeWrapper DrawablePath::ValueTreeWrapper::Element::getParen | |||
| return ValueTreeWrapper (state.getParent().getParent()); | |||
| } | |||
| DrawablePath::ValueTreeWrapper::Element DrawablePath::ValueTreeWrapper::Element::getPreviousElement() const | |||
| { | |||
| return Element (state.getSibling (-1)); | |||
| } | |||
| int DrawablePath::ValueTreeWrapper::Element::getNumControlPoints() const throw() | |||
| { | |||
| const Identifier i (state.getType()); | |||
| @@ -85622,6 +85643,18 @@ void DrawablePath::ValueTreeWrapper::Element::setControlPoint (const int index, | |||
| return state.setProperty (index == 0 ? point1 : (index == 1 ? point2 : point3), point.toString(), undoManager); | |||
| } | |||
| const RelativePoint DrawablePath::ValueTreeWrapper::Element::getStartPoint() const | |||
| { | |||
| const Identifier i (state.getType()); | |||
| if (i == startSubPathElement) | |||
| return getControlPoint (0); | |||
| jassert (i == lineToElement || i == quadraticToElement || i == cubicToElement || i == closeSubPathElement); | |||
| return getPreviousElement().getEndPoint(); | |||
| } | |||
| const RelativePoint DrawablePath::ValueTreeWrapper::Element::getEndPoint() const | |||
| { | |||
| const Identifier i (state.getType()); | |||
| @@ -85629,9 +85662,77 @@ const RelativePoint DrawablePath::ValueTreeWrapper::Element::getEndPoint() const | |||
| if (i == quadraticToElement) return getControlPoint (1); | |||
| if (i == cubicToElement) return getControlPoint (2); | |||
| jassert (i == closeSubPathElement); | |||
| return RelativePoint(); | |||
| } | |||
| const String DrawablePath::ValueTreeWrapper::Element::getModeOfEndPoint() const | |||
| { | |||
| return state [mode].toString(); | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::setModeOfEndPoint (const String& newMode, UndoManager* undoManager) | |||
| { | |||
| if (state.hasType (cubicToElement)) | |||
| state.setProperty (mode, newMode, undoManager); | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::convertToLine (UndoManager* undoManager) | |||
| { | |||
| const Identifier i (state.getType()); | |||
| if (i == quadraticToElement || i == cubicToElement) | |||
| { | |||
| ValueTree newState (lineToElement); | |||
| Element e (newState); | |||
| e.setControlPoint (0, getEndPoint(), undoManager); | |||
| state = newState; | |||
| } | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::convertToCubic (RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager) | |||
| { | |||
| const Identifier i (state.getType()); | |||
| if (i == lineToElement || i == quadraticToElement) | |||
| { | |||
| ValueTree newState (cubicToElement); | |||
| Element e (newState); | |||
| const RelativePoint start (getStartPoint()); | |||
| const RelativePoint end (getEndPoint()); | |||
| const Point<float> startResolved (start.resolve (nameFinder)); | |||
| const Point<float> endResolved (end.resolve (nameFinder)); | |||
| e.setControlPoint (0, startResolved + (endResolved - startResolved) * 0.3f, undoManager); | |||
| e.setControlPoint (1, startResolved + (endResolved - startResolved) * 0.7f, undoManager); | |||
| e.setControlPoint (2, end, undoManager); | |||
| state = newState; | |||
| } | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::convertToPathBreak (UndoManager* undoManager) | |||
| { | |||
| const Identifier i (state.getType()); | |||
| if (i != startSubPathElement) | |||
| { | |||
| ValueTree newState (startSubPathElement); | |||
| Element e (newState); | |||
| e.setControlPoint (0, getEndPoint(), undoManager); | |||
| state = newState; | |||
| } | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::insertPoint (double, RelativeCoordinate::NamedCoordinateFinder*, UndoManager*) | |||
| { | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::removePoint (UndoManager* undoManager) | |||
| { | |||
| state.getParent().removeChild (state, undoManager); | |||
| } | |||
| const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | |||
| { | |||
| Rectangle<float> damageRect; | |||
| @@ -85674,7 +85775,7 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree | |||
| needsRedraw = true; | |||
| } | |||
| relativePath = newRelativePath.release(); | |||
| relativePath = newRelativePath; | |||
| if (needsRedraw) | |||
| damageRect = damageRect.getUnion (getBounds()); | |||
| @@ -90602,6 +90703,61 @@ const Line<float> Path::getClippedLine (const Line<float>& line, const bool keep | |||
| return result; | |||
| } | |||
| float Path::getLength (const AffineTransform& transform) const | |||
| { | |||
| float length = 0; | |||
| PathFlatteningIterator i (*this, transform); | |||
| while (i.next()) | |||
| length += Line<float> (i.x1, i.y1, i.x2, i.y2).getLength(); | |||
| return length; | |||
| } | |||
| const Point<float> Path::getPointAlongPath (float distanceFromStart, const AffineTransform& transform) const | |||
| { | |||
| PathFlatteningIterator i (*this, transform); | |||
| while (i.next()) | |||
| { | |||
| const Line<float> line (i.x1, i.y1, i.x2, i.y2); | |||
| const float lineLength = line.getLength(); | |||
| if (distanceFromStart <= lineLength) | |||
| return line.getPointAlongLine (distanceFromStart); | |||
| distanceFromStart -= lineLength; | |||
| } | |||
| return Point<float> (i.x2, i.y2); | |||
| } | |||
| float Path::getNearestPoint (const Point<float>& targetPoint, Point<float>& pointOnPath, | |||
| const AffineTransform& transform) const | |||
| { | |||
| PathFlatteningIterator i (*this, transform); | |||
| float bestPosition = 0, bestDistance = std::numeric_limits<float>::max(); | |||
| float length = 0; | |||
| Point<float> pointOnLine; | |||
| while (i.next()) | |||
| { | |||
| const Line<float> line (i.x1, i.y1, i.x2, i.y2); | |||
| const float distance = line.getDistanceFromPoint (targetPoint, pointOnLine); | |||
| if (distance < bestDistance) | |||
| { | |||
| bestDistance = distance; | |||
| bestPosition = length + pointOnLine.getDistanceFrom (line.getStart()); | |||
| pointOnPath = pointOnLine; | |||
| } | |||
| length += line.getLength(); | |||
| } | |||
| return bestPosition; | |||
| } | |||
| const Path Path::createPathWithRoundedCorners (const float cornerRadius) const | |||
| { | |||
| if (cornerRadius <= 0.01f) | |||
| @@ -92194,7 +92350,7 @@ void PositionedRectangle::getRectangleDouble (const Rectangle<int>& target, | |||
| void PositionedRectangle::applyToComponent (Component& comp) const throw() | |||
| { | |||
| comp.setBounds (getRectangle (Rectangle<int> (0, 0, comp.getParentWidth(), comp.getParentHeight()))); | |||
| comp.setBounds (getRectangle (Rectangle<int> (comp.getParentWidth(), comp.getParentHeight()))); | |||
| } | |||
| void PositionedRectangle::updateFrom (const Rectangle<int>& rectangle, | |||
| @@ -92217,7 +92373,7 @@ void PositionedRectangle::updateFromComponent (const Component& comp) throw() | |||
| if (comp.getParentComponent() == 0 && ! comp.isOnDesktop()) | |||
| updateFrom (comp.getBounds(), Rectangle<int>()); | |||
| else | |||
| updateFrom (comp.getBounds(), Rectangle<int> (0, 0, comp.getParentWidth(), comp.getParentHeight())); | |||
| updateFrom (comp.getBounds(), Rectangle<int> (comp.getParentWidth(), comp.getParentHeight())); | |||
| } | |||
| PositionedRectangle::AnchorPoint PositionedRectangle::getAnchorPointX() const throw() | |||
| @@ -239971,7 +240127,7 @@ private: | |||
| if (needToPaintAll) | |||
| { | |||
| contextClip.clear(); | |||
| contextClip.addWithoutMerging (Rectangle<int> (0, 0, w, h)); | |||
| contextClip.addWithoutMerging (Rectangle<int> (w, h)); | |||
| } | |||
| if (transparent) | |||
| @@ -258345,8 +258501,7 @@ void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, const | |||
| if (monitorCoords.size() == 0) | |||
| { | |||
| monitorCoords.add (Rectangle<int> (0, 0, | |||
| DisplayWidth (display, DefaultScreen (display)), | |||
| monitorCoords.add (Rectangle<int> (DisplayWidth (display, DefaultScreen (display)), | |||
| DisplayHeight (display, DefaultScreen (display)))); | |||
| } | |||
| } | |||
| @@ -261764,7 +261919,7 @@ public: | |||
| - (void) createConnection | |||
| { | |||
| NSInteger oldRetainCount = [self retainCount]; | |||
| NSUInteger oldRetainCount = [self retainCount]; | |||
| connection = [[NSURLConnection alloc] initWithRequest: request | |||
| delegate: self]; | |||
| @@ -64,7 +64,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 29 | |||
| #define JUCE_BUILDNUMBER 30 | |||
| /** Current Juce version number. | |||
| @@ -13289,6 +13289,14 @@ public: | |||
| */ | |||
| ValueTree getParent() const; | |||
| /** Returns one of this node's siblings in its parent's child list. | |||
| The delta specifies how far to move through the list, so a value of 1 would return the node | |||
| that follows this one, -1 would return the node before it, 0 will return this node itself, etc. | |||
| If the requested position is beyond the range of available nodes, this will return ValueTree::invalid. | |||
| */ | |||
| ValueTree getSibling (int delta) const; | |||
| /** Creates an XmlElement that holds a complete image of this node and all its children. | |||
| If this node is invalid, this may return 0. Otherwise, the XML that is produced can | |||
| @@ -20174,25 +20182,42 @@ public: | |||
| distance from the line; if the point is a long way beyond one of the line's | |||
| end-point's, it'll return the straight-line distance to the nearest end-point. | |||
| pointOnLine receives the position of the point that is found. | |||
| @returns the point's distance from the line | |||
| @see getPositionAlongLineOfNearestPoint | |||
| */ | |||
| ValueType getDistanceFromPoint (const Point<ValueType>& point) const throw() | |||
| ValueType getDistanceFromPoint (const Point<ValueType>& targetPoint, | |||
| Point<ValueType>& pointOnLine) const throw() | |||
| { | |||
| const Point<ValueType> delta (end - start); | |||
| const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY(); | |||
| if (length > 0) | |||
| { | |||
| const double prop = ((point.getX() - start.getX()) * delta.getX() | |||
| + (point.getY() - start.getY()) * delta.getY()) / length; | |||
| const double prop = ((targetPoint.getX() - start.getX()) * delta.getX() | |||
| + (targetPoint.getY() - start.getY()) * delta.getY()) / length; | |||
| if (prop >= 0 && prop <= 1.0) | |||
| return point.getDistanceFrom (start + delta * (ValueType) prop); | |||
| { | |||
| pointOnLine = start + delta * (ValueType) prop; | |||
| return targetPoint.getDistanceFrom (pointOnLine); | |||
| } | |||
| } | |||
| return jmin (point.getDistanceFrom (start), | |||
| point.getDistanceFrom (end)); | |||
| const float fromStart = targetPoint.getDistanceFrom (start); | |||
| const float fromEnd = targetPoint.getDistanceFrom (end); | |||
| if (fromStart < fromEnd) | |||
| { | |||
| pointOnLine = start; | |||
| return fromStart; | |||
| } | |||
| else | |||
| { | |||
| pointOnLine = end; | |||
| return fromEnd; | |||
| } | |||
| } | |||
| /** Finds the point on this line which is nearest to a given point, and | |||
| @@ -21254,6 +21279,27 @@ public: | |||
| */ | |||
| const Line<float> getClippedLine (const Line<float>& line, bool keepSectionOutsidePath) const; | |||
| /** Returns the length of the path. | |||
| @see getPointAlongPath | |||
| */ | |||
| float getLength (const AffineTransform& transform = AffineTransform::identity) const; | |||
| /** Returns a point that is the specified distance along the path. | |||
| If the distance is greater than the total length of the path, this will return the | |||
| end point. | |||
| @see getLength | |||
| */ | |||
| const Point<float> getPointAlongPath (float distanceFromStart, | |||
| const AffineTransform& transform = AffineTransform::identity) const; | |||
| /** Finds the point along the path which is nearest to a given position. | |||
| This sets pointOnPath to the nearest point, and returns the distance of this point from the start | |||
| of the path. | |||
| */ | |||
| float getNearestPoint (const Point<float>& targetPoint, | |||
| Point<float>& pointOnPath, | |||
| const AffineTransform& transform = AffineTransform::identity) const; | |||
| /** Removes all lines and curves, resetting the path completely. */ | |||
| void clear() throw(); | |||
| @@ -23944,7 +23990,7 @@ public: | |||
| /** Fills a rectangle with a checkerboard pattern, alternating between two colours. | |||
| */ | |||
| void fillCheckerBoard (int x, int y, int width, int height, | |||
| void fillCheckerBoard (const Rectangle<int>& area, | |||
| int checkWidth, int checkHeight, | |||
| const Colour& colour1, const Colour& colour2) const; | |||
| @@ -24494,7 +24540,7 @@ public: | |||
| /** Returns a rectangle with the same size as this image. | |||
| The rectangle's origin is always (0, 0). | |||
| */ | |||
| const Rectangle<int> getBounds() const throw() { return image == 0 ? Rectangle<int>() : Rectangle<int> (0, 0, image->width, image->height); } | |||
| const Rectangle<int> getBounds() const throw() { return image == 0 ? Rectangle<int>() : Rectangle<int> (image->width, image->height); } | |||
| /** Returns the image's pixel format. */ | |||
| PixelFormat getFormat() const throw() { return image == 0 ? UnknownFormat : image->format; } | |||
| @@ -25648,7 +25694,8 @@ public: | |||
| /** Changes the component's size and centres it within its parent. | |||
| After changing the size, the component will be moved so that it's | |||
| centred within its parent. | |||
| centred within its parent. If the component is on the desktop (or has no | |||
| parent component), then it'll be centred within the main monitor area. | |||
| */ | |||
| void centreWithSize (int width, int height); | |||
| @@ -25809,7 +25856,7 @@ public: | |||
| /** Checks whether a component is anywhere inside this component or its children. | |||
| This will recursively check through this components children to see if the | |||
| This will recursively check through this component's children to see if the | |||
| given component is anywhere inside. | |||
| */ | |||
| bool isParentOf (const Component* possibleChild) const throw(); | |||
| @@ -27224,6 +27271,7 @@ private: | |||
| // how much of the component is not off the edges of its parents | |||
| const Rectangle<int> getUnclippedArea() const; | |||
| void sendVisibilityChangeMessage(); | |||
| const Rectangle<int> getParentOrMainMonitorBounds() const; | |||
| // This is included here just to cause a compile error if your code is still handling | |||
| // drag-and-drop with this method. If so, just update it to use the new FileDragAndDropTarget | |||
| @@ -56052,7 +56100,8 @@ private: | |||
| HueSelectorComp* hueSelector; | |||
| OwnedArray <SwatchComponent> swatchComponents; | |||
| const int flags; | |||
| int topSpace, edgeGap; | |||
| int edgeGap; | |||
| Rectangle<int> previewArea; | |||
| void setHue (float newH); | |||
| void setSV (float newS, float newV); | |||
| @@ -59340,13 +59389,27 @@ public: | |||
| const RelativePoint getControlPoint (int index) const; | |||
| Value getControlPointValue (int index, UndoManager* undoManager) const; | |||
| const RelativePoint getStartPoint() const; | |||
| const RelativePoint getEndPoint() const; | |||
| void setControlPoint (int index, const RelativePoint& point, UndoManager* undoManager); | |||
| ValueTreeWrapper getParent() const; | |||
| Element getPreviousElement() const; | |||
| const String getModeOfEndPoint() const; | |||
| void setModeOfEndPoint (const String& newMode, UndoManager* undoManager); | |||
| void convertToLine (UndoManager* undoManager); | |||
| void convertToCubic (RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager); | |||
| void convertToPathBreak (UndoManager* undoManager); | |||
| void insertPoint (double proportionOfLength, RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager); | |||
| void removePoint (UndoManager* undoManager); | |||
| static const Identifier startSubPathElement, closeSubPathElement, | |||
| static const Identifier mode, startSubPathElement, closeSubPathElement, | |||
| lineToElement, quadraticToElement, cubicToElement; | |||
| static const char* cornerMode; | |||
| static const char* roundedMode; | |||
| static const char* symmetricMode; | |||
| ValueTree state; | |||
| }; | |||
| @@ -610,6 +610,15 @@ ValueTree ValueTree::getParent() const | |||
| return ValueTree (object != 0 ? object->parent : (SharedObject*) 0); | |||
| } | |||
| ValueTree ValueTree::getSibling (const int delta) const | |||
| { | |||
| if (object == 0 || object->parent == 0) | |||
| return invalid; | |||
| const int index = object->parent->indexOf (*this) + delta; | |||
| return ValueTree (static_cast <SharedObject*> (object->children [index])); | |||
| } | |||
| const var& ValueTree::operator[] (const Identifier& name) const | |||
| { | |||
| return object == 0 ? var::null : object->getProperty (name); | |||
| @@ -302,6 +302,14 @@ public: | |||
| */ | |||
| ValueTree getParent() const; | |||
| /** Returns one of this node's siblings in its parent's child list. | |||
| The delta specifies how far to move through the list, so a value of 1 would return the node | |||
| that follows this one, -1 would return the node before it, 0 will return this node itself, etc. | |||
| If the requested position is beyond the range of available nodes, this will return ValueTree::invalid. | |||
| */ | |||
| ValueTree getSibling (int delta) const; | |||
| //============================================================================== | |||
| /** Creates an XmlElement that holds a complete image of this node and all its children. | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 29 | |||
| #define JUCE_BUILDNUMBER 30 | |||
| /** Current Juce version number. | |||
| @@ -791,7 +791,7 @@ const Point<int> Component::relativePositionToOtherComponent (const Component* c | |||
| } | |||
| //============================================================================== | |||
| void Component::setBounds (int x, int y, int w, int h) | |||
| void Component::setBounds (const int x, const int y, int w, int h) | |||
| { | |||
| // if component methods are being called from threads other than the message | |||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | |||
| @@ -925,18 +925,16 @@ void Component::setCentreRelative (const float x, const float y) | |||
| void Component::centreWithSize (const int width, const int height) | |||
| { | |||
| setBounds ((getParentWidth() - width) / 2, | |||
| (getParentHeight() - height) / 2, | |||
| width, | |||
| height); | |||
| const Rectangle<int> parentArea (getParentOrMainMonitorBounds()); | |||
| setBounds (parentArea.getCentreX() - width / 2, | |||
| parentArea.getCentreY() - height / 2, | |||
| width, height); | |||
| } | |||
| void Component::setBoundsInset (const BorderSize& borders) | |||
| { | |||
| setBounds (borders.getLeft(), | |||
| borders.getTop(), | |||
| getParentWidth() - (borders.getLeftAndRight()), | |||
| getParentHeight() - (borders.getTopAndBottom())); | |||
| setBounds (borders.subtractedFrom (getParentOrMainMonitorBounds())); | |||
| } | |||
| void Component::setBoundsToFit (int x, int y, int width, int height, | |||
| @@ -1781,7 +1779,13 @@ void Component::colourChanged() | |||
| //============================================================================== | |||
| const Rectangle<int> Component::getLocalBounds() const throw() | |||
| { | |||
| return Rectangle<int> (0, 0, getWidth(), getHeight()); | |||
| return Rectangle<int> (getWidth(), getHeight()); | |||
| } | |||
| const Rectangle<int> Component::getParentOrMainMonitorBounds() const | |||
| { | |||
| return parentComponent_ != 0 ? parentComponent_->getLocalBounds() | |||
| : Desktop::getInstance().getMainMonitorArea(); | |||
| } | |||
| const Rectangle<int> Component::getUnclippedArea() const | |||
| @@ -2637,8 +2641,8 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point<int>& | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| BailOutChecker checker (this); | |||
| const float wheelIncrementX = amountX * (1.0f / 256.0f); | |||
| const float wheelIncrementY = amountY * (1.0f / 256.0f); | |||
| const float wheelIncrementX = amountX / 256.0f; | |||
| const float wheelIncrementY = amountY / 256.0f; | |||
| const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
| this, this, time, relativePos, time, 0, false); | |||
| @@ -3081,8 +3085,7 @@ const Point<int> Component::getMouseXYRelative() const | |||
| const Rectangle<int> Component::getParentMonitorArea() const | |||
| { | |||
| return Desktop::getInstance() | |||
| .getMonitorAreaContaining (relativePositionToGlobal (Point<int> (getWidth() / 2, | |||
| getHeight() / 2))); | |||
| .getMonitorAreaContaining (relativePositionToGlobal (getLocalBounds().getCentre())); | |||
| } | |||
| //============================================================================== | |||
| @@ -481,7 +481,8 @@ public: | |||
| /** Changes the component's size and centres it within its parent. | |||
| After changing the size, the component will be moved so that it's | |||
| centred within its parent. | |||
| centred within its parent. If the component is on the desktop (or has no | |||
| parent component), then it'll be centred within the main monitor area. | |||
| */ | |||
| void centreWithSize (int width, int height); | |||
| @@ -644,7 +645,7 @@ public: | |||
| /** Checks whether a component is anywhere inside this component or its children. | |||
| This will recursively check through this components children to see if the | |||
| This will recursively check through this component's children to see if the | |||
| given component is anywhere inside. | |||
| */ | |||
| bool isParentOf (const Component* possibleChild) const throw(); | |||
| @@ -2095,6 +2096,7 @@ private: | |||
| // how much of the component is not off the edges of its parents | |||
| const Rectangle<int> getUnclippedArea() const; | |||
| void sendVisibilityChangeMessage(); | |||
| const Rectangle<int> getParentOrMainMonitorBounds() const; | |||
| //============================================================================== | |||
| // This is included here just to cause a compile error if your code is still handling | |||
| @@ -311,8 +311,7 @@ public: | |||
| { | |||
| const Colour colour (owner->getSwatchColour (index)); | |||
| g.fillCheckerBoard (0, 0, getWidth(), getHeight(), | |||
| 6, 6, | |||
| g.fillCheckerBoard (getLocalBounds(), 6, 6, | |||
| Colour (0xffdddddd).overlaidWith (colour), | |||
| Colour (0xffffffff).overlaidWith (colour)); | |||
| } | |||
| @@ -356,7 +355,6 @@ ColourSelector::ColourSelector (const int flags_, | |||
| colourSpace (0), | |||
| hueSelector (0), | |||
| flags (flags_), | |||
| topSpace (0), | |||
| edgeGap (edgeGap_) | |||
| { | |||
| // not much point having a selector with no components in it! | |||
| @@ -464,7 +462,7 @@ void ColourSelector::update() | |||
| } | |||
| if ((flags & showColourAtTop) != 0) | |||
| repaint (0, edgeGap, getWidth(), topSpace - edgeGap); | |||
| repaint (previewArea); | |||
| sendChangeMessage (this); | |||
| } | |||
| @@ -478,15 +476,14 @@ void ColourSelector::paint (Graphics& g) | |||
| { | |||
| const Colour currentColour (getCurrentColour()); | |||
| g.fillCheckerBoard (edgeGap, edgeGap, getWidth() - edgeGap - edgeGap, topSpace - edgeGap - edgeGap, | |||
| 10, 10, | |||
| g.fillCheckerBoard (previewArea, 10, 10, | |||
| Colour (0xffdddddd).overlaidWith (currentColour), | |||
| Colour (0xffffffff).overlaidWith (currentColour)); | |||
| g.setColour (Colours::white.overlaidWith (currentColour).contrasting()); | |||
| g.setFont (14.0f, true); | |||
| g.drawText (currentColour.toDisplayString ((flags & showAlphaChannel) != 0), | |||
| 0, edgeGap, getWidth(), topSpace - edgeGap * 2, | |||
| previewArea.getX(), previewArea.getY(), previewArea.getWidth(), previewArea.getHeight(), | |||
| Justification::centred, false); | |||
| } | |||
| @@ -516,7 +513,9 @@ void ColourSelector::resized() | |||
| const int swatchSpace = numSwatches > 0 ? edgeGap + swatchHeight * ((numSwatches + 7) / swatchesPerRow) : 0; | |||
| const int sliderSpace = ((flags & showSliders) != 0) ? jmin (22 * numSliders + edgeGap, proportionOfHeight (0.3f)) : 0; | |||
| topSpace = ((flags & showColourAtTop) != 0) ? jmin (30 + edgeGap * 2, proportionOfHeight (0.2f)) : edgeGap; | |||
| const int topSpace = ((flags & showColourAtTop) != 0) ? jmin (30 + edgeGap * 2, proportionOfHeight (0.2f)) : edgeGap; | |||
| previewArea.setBounds (edgeGap, edgeGap, getWidth() - edgeGap * 2, topSpace - edgeGap * 2); | |||
| int y = topSpace; | |||
| @@ -149,7 +149,8 @@ private: | |||
| HueSelectorComp* hueSelector; | |||
| OwnedArray <SwatchComponent> swatchComponents; | |||
| const int flags; | |||
| int topSpace, edgeGap; | |||
| int edgeGap; | |||
| Rectangle<int> previewArea; | |||
| void setHue (float newH); | |||
| void setSV (float newS, float newV); | |||
| @@ -78,8 +78,8 @@ ResizableWindow::~ResizableWindow() | |||
| { | |||
| resizableCorner = 0; | |||
| resizableBorder = 0; | |||
| deleteAndZero (contentComponent); // (avoid using a scoped pointer for this, so that it survives | |||
| // external deletion of the content comp) | |||
| delete static_cast <Component*> (contentComponent); | |||
| contentComponent = 0; | |||
| // have you been adding your own components directly to this window..? tut tut tut. | |||
| // Read the instructions for using a ResizableWindow! | |||
| @@ -108,6 +108,9 @@ void ResizableWindow::setContentComponent (Component* const newContentComponent, | |||
| if (deleteOldOne) | |||
| delete static_cast <Component*> (contentComponent); // (avoid using a scoped pointer for this, so that it survives | |||
| // external deletion of the content comp) | |||
| else | |||
| removeChildComponent (contentComponent); | |||
| contentComponent = newContentComponent; | |||
| Component::addAndMakeVisible (contentComponent); | |||
| @@ -201,12 +204,13 @@ void ResizableWindow::childBoundsChanged (Component* child) | |||
| //============================================================================== | |||
| void ResizableWindow::activeWindowStatusChanged() | |||
| { | |||
| const BorderSize borders (getContentComponentBorder()); | |||
| const BorderSize border (getContentComponentBorder()); | |||
| repaint (0, 0, getWidth(), borders.getTop()); | |||
| repaint (0, borders.getTop(), borders.getLeft(), getHeight() - borders.getBottom() - borders.getTop()); | |||
| repaint (0, getHeight() - borders.getBottom(), getWidth(), borders.getBottom()); | |||
| repaint (getWidth() - borders.getRight(), borders.getTop(), borders.getRight(), getHeight() - borders.getBottom() - borders.getTop()); | |||
| Rectangle<int> area (getLocalBounds()); | |||
| repaint (area.removeFromTop (border.getTop())); | |||
| repaint (area.removeFromLeft (border.getLeft())); | |||
| repaint (area.removeFromRight (border.getRight())); | |||
| repaint (area.removeFromBottom (border.getBottom())); | |||
| } | |||
| //============================================================================== | |||
| @@ -478,7 +478,7 @@ void Graphics::drawArrow (const Line<float>& line, const float lineThickness, co | |||
| fillPath (p); | |||
| } | |||
| void Graphics::fillCheckerBoard (int x, int y, int width, int height, | |||
| void Graphics::fillCheckerBoard (const Rectangle<int>& area, | |||
| const int checkWidth, const int checkHeight, | |||
| const Colour& colour1, const Colour& colour2) const | |||
| { | |||
| @@ -491,29 +491,29 @@ void Graphics::fillCheckerBoard (int x, int y, int width, int height, | |||
| if (colour1 == colour2) | |||
| { | |||
| context->setFill (colour1); | |||
| context->fillRect (Rectangle<int> (x, y, width, height), false); | |||
| context->fillRect (area, false); | |||
| } | |||
| else | |||
| { | |||
| const Rectangle<int> clip (context->getClipBounds()); | |||
| const Rectangle<int> clipped (context->getClipBounds().getIntersection (area)); | |||
| const int right = jmin (x + width, clip.getRight()); | |||
| const int bottom = jmin (y + height, clip.getBottom()); | |||
| int cy = 0; | |||
| while (y < bottom) | |||
| if (! clipped.isEmpty()) | |||
| { | |||
| int cx = cy; | |||
| context->clipToRectangle (clipped); | |||
| const int startX = area.getX() + ((clipped.getX() - area.getX()) / checkWidth) * checkWidth; | |||
| const int startY = area.getY() + ((clipped.getY() - area.getY()) / checkHeight) * checkHeight; | |||
| const int right = clipped.getRight(); | |||
| const int bottom = clipped.getBottom(); | |||
| for (int xx = x; xx < right; xx += checkWidth) | |||
| for (int i = 0; i < 2; ++i) | |||
| { | |||
| context->setFill (((cx++ & 1) == 0) ? colour1 : colour2); | |||
| context->fillRect (Rectangle<int> (xx, y, jmin (checkWidth, right - xx), jmin (checkHeight, bottom - y)), | |||
| false); | |||
| } | |||
| context->setFill (i == 0 ? colour1 : colour2); | |||
| ++cy; | |||
| y += checkHeight; | |||
| int cy = i; | |||
| for (int y = startY; y < bottom; y += checkHeight) | |||
| for (int x = startX + (cy++ & 1) * checkWidth; x < right; x += checkWidth * 2) | |||
| context->fillRect (Rectangle<int> (x, y, checkWidth, checkHeight), false); | |||
| } | |||
| } | |||
| } | |||
| @@ -256,7 +256,7 @@ public: | |||
| /** Fills a rectangle with a checkerboard pattern, alternating between two colours. | |||
| */ | |||
| void fillCheckerBoard (int x, int y, int width, int height, | |||
| void fillCheckerBoard (const Rectangle<int>& area, | |||
| int checkWidth, int checkHeight, | |||
| const Colour& colour1, const Colour& colour2) const; | |||
| @@ -57,7 +57,7 @@ LowLevelGraphicsPostScriptRenderer::LowLevelGraphicsPostScriptRenderer (OutputSt | |||
| needToClip (true) | |||
| { | |||
| stateStack.add (new SavedState()); | |||
| stateStack.getLast()->clip = Rectangle<int> (0, 0, totalWidth_, totalHeight_); | |||
| stateStack.getLast()->clip = Rectangle<int> (totalWidth_, totalHeight_); | |||
| const float scale = jmin ((520.0f / totalWidth_), (750.0f / totalHeight)); | |||
| @@ -288,6 +288,7 @@ void DrawablePath::ValueTreeWrapper::setUsesNonZeroWinding (bool b, UndoManager* | |||
| } | |||
| //============================================================================== | |||
| const Identifier DrawablePath::ValueTreeWrapper::Element::mode ("mode"); | |||
| const Identifier DrawablePath::ValueTreeWrapper::Element::startSubPathElement ("Move"); | |||
| const Identifier DrawablePath::ValueTreeWrapper::Element::closeSubPathElement ("Close"); | |||
| const Identifier DrawablePath::ValueTreeWrapper::Element::lineToElement ("Line"); | |||
| @@ -308,6 +309,11 @@ DrawablePath::ValueTreeWrapper DrawablePath::ValueTreeWrapper::Element::getParen | |||
| return ValueTreeWrapper (state.getParent().getParent()); | |||
| } | |||
| DrawablePath::ValueTreeWrapper::Element DrawablePath::ValueTreeWrapper::Element::getPreviousElement() const | |||
| { | |||
| return Element (state.getSibling (-1)); | |||
| } | |||
| int DrawablePath::ValueTreeWrapper::Element::getNumControlPoints() const throw() | |||
| { | |||
| const Identifier i (state.getType()); | |||
| @@ -335,6 +341,18 @@ void DrawablePath::ValueTreeWrapper::Element::setControlPoint (const int index, | |||
| return state.setProperty (index == 0 ? point1 : (index == 1 ? point2 : point3), point.toString(), undoManager); | |||
| } | |||
| const RelativePoint DrawablePath::ValueTreeWrapper::Element::getStartPoint() const | |||
| { | |||
| const Identifier i (state.getType()); | |||
| if (i == startSubPathElement) | |||
| return getControlPoint (0); | |||
| jassert (i == lineToElement || i == quadraticToElement || i == cubicToElement || i == closeSubPathElement); | |||
| return getPreviousElement().getEndPoint(); | |||
| } | |||
| const RelativePoint DrawablePath::ValueTreeWrapper::Element::getEndPoint() const | |||
| { | |||
| const Identifier i (state.getType()); | |||
| @@ -342,9 +360,76 @@ const RelativePoint DrawablePath::ValueTreeWrapper::Element::getEndPoint() const | |||
| if (i == quadraticToElement) return getControlPoint (1); | |||
| if (i == cubicToElement) return getControlPoint (2); | |||
| jassert (i == closeSubPathElement); | |||
| return RelativePoint(); | |||
| } | |||
| const String DrawablePath::ValueTreeWrapper::Element::getModeOfEndPoint() const | |||
| { | |||
| return state [mode].toString(); | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::setModeOfEndPoint (const String& newMode, UndoManager* undoManager) | |||
| { | |||
| if (state.hasType (cubicToElement)) | |||
| state.setProperty (mode, newMode, undoManager); | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::convertToLine (UndoManager* undoManager) | |||
| { | |||
| const Identifier i (state.getType()); | |||
| if (i == quadraticToElement || i == cubicToElement) | |||
| { | |||
| ValueTree newState (lineToElement); | |||
| Element e (newState); | |||
| e.setControlPoint (0, getEndPoint(), undoManager); | |||
| state = newState; | |||
| } | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::convertToCubic (RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager) | |||
| { | |||
| const Identifier i (state.getType()); | |||
| if (i == lineToElement || i == quadraticToElement) | |||
| { | |||
| ValueTree newState (cubicToElement); | |||
| Element e (newState); | |||
| const RelativePoint start (getStartPoint()); | |||
| const RelativePoint end (getEndPoint()); | |||
| const Point<float> startResolved (start.resolve (nameFinder)); | |||
| const Point<float> endResolved (end.resolve (nameFinder)); | |||
| e.setControlPoint (0, startResolved + (endResolved - startResolved) * 0.3f, undoManager); | |||
| e.setControlPoint (1, startResolved + (endResolved - startResolved) * 0.7f, undoManager); | |||
| e.setControlPoint (2, end, undoManager); | |||
| state = newState; | |||
| } | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::convertToPathBreak (UndoManager* undoManager) | |||
| { | |||
| const Identifier i (state.getType()); | |||
| if (i != startSubPathElement) | |||
| { | |||
| ValueTree newState (startSubPathElement); | |||
| Element e (newState); | |||
| e.setControlPoint (0, getEndPoint(), undoManager); | |||
| state = newState; | |||
| } | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::insertPoint (double, RelativeCoordinate::NamedCoordinateFinder*, UndoManager*) | |||
| { | |||
| } | |||
| void DrawablePath::ValueTreeWrapper::Element::removePoint (UndoManager* undoManager) | |||
| { | |||
| state.getParent().removeChild (state, undoManager); | |||
| } | |||
| //============================================================================== | |||
| const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | |||
| @@ -389,7 +474,7 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree | |||
| needsRedraw = true; | |||
| } | |||
| relativePath = newRelativePath.release(); | |||
| relativePath = newRelativePath; | |||
| if (needsRedraw) | |||
| damageRect = damageRect.getUnion (getBounds()); | |||
| @@ -160,13 +160,27 @@ public: | |||
| const RelativePoint getControlPoint (int index) const; | |||
| Value getControlPointValue (int index, UndoManager* undoManager) const; | |||
| const RelativePoint getStartPoint() const; | |||
| const RelativePoint getEndPoint() const; | |||
| void setControlPoint (int index, const RelativePoint& point, UndoManager* undoManager); | |||
| ValueTreeWrapper getParent() const; | |||
| Element getPreviousElement() const; | |||
| static const Identifier startSubPathElement, closeSubPathElement, | |||
| const String getModeOfEndPoint() const; | |||
| void setModeOfEndPoint (const String& newMode, UndoManager* undoManager); | |||
| void convertToLine (UndoManager* undoManager); | |||
| void convertToCubic (RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager); | |||
| void convertToPathBreak (UndoManager* undoManager); | |||
| void insertPoint (double proportionOfLength, RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager); | |||
| void removePoint (UndoManager* undoManager); | |||
| static const Identifier mode, startSubPathElement, closeSubPathElement, | |||
| lineToElement, quadraticToElement, cubicToElement; | |||
| static const char* cornerMode; | |||
| static const char* roundedMode; | |||
| static const char* symmetricMode; | |||
| ValueTree state; | |||
| }; | |||
| @@ -238,25 +238,42 @@ public: | |||
| distance from the line; if the point is a long way beyond one of the line's | |||
| end-point's, it'll return the straight-line distance to the nearest end-point. | |||
| pointOnLine receives the position of the point that is found. | |||
| @returns the point's distance from the line | |||
| @see getPositionAlongLineOfNearestPoint | |||
| */ | |||
| ValueType getDistanceFromPoint (const Point<ValueType>& point) const throw() | |||
| ValueType getDistanceFromPoint (const Point<ValueType>& targetPoint, | |||
| Point<ValueType>& pointOnLine) const throw() | |||
| { | |||
| const Point<ValueType> delta (end - start); | |||
| const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY(); | |||
| if (length > 0) | |||
| { | |||
| const double prop = ((point.getX() - start.getX()) * delta.getX() | |||
| + (point.getY() - start.getY()) * delta.getY()) / length; | |||
| const double prop = ((targetPoint.getX() - start.getX()) * delta.getX() | |||
| + (targetPoint.getY() - start.getY()) * delta.getY()) / length; | |||
| if (prop >= 0 && prop <= 1.0) | |||
| return point.getDistanceFrom (start + delta * (ValueType) prop); | |||
| { | |||
| pointOnLine = start + delta * (ValueType) prop; | |||
| return targetPoint.getDistanceFrom (pointOnLine); | |||
| } | |||
| } | |||
| return jmin (point.getDistanceFrom (start), | |||
| point.getDistanceFrom (end)); | |||
| const float fromStart = targetPoint.getDistanceFrom (start); | |||
| const float fromEnd = targetPoint.getDistanceFrom (end); | |||
| if (fromStart < fromEnd) | |||
| { | |||
| pointOnLine = start; | |||
| return fromStart; | |||
| } | |||
| else | |||
| { | |||
| pointOnLine = end; | |||
| return fromEnd; | |||
| } | |||
| } | |||
| /** Finds the point on this line which is nearest to a given point, and | |||
| @@ -1051,6 +1051,61 @@ const Line<float> Path::getClippedLine (const Line<float>& line, const bool keep | |||
| return result; | |||
| } | |||
| float Path::getLength (const AffineTransform& transform) const | |||
| { | |||
| float length = 0; | |||
| PathFlatteningIterator i (*this, transform); | |||
| while (i.next()) | |||
| length += Line<float> (i.x1, i.y1, i.x2, i.y2).getLength(); | |||
| return length; | |||
| } | |||
| const Point<float> Path::getPointAlongPath (float distanceFromStart, const AffineTransform& transform) const | |||
| { | |||
| PathFlatteningIterator i (*this, transform); | |||
| while (i.next()) | |||
| { | |||
| const Line<float> line (i.x1, i.y1, i.x2, i.y2); | |||
| const float lineLength = line.getLength(); | |||
| if (distanceFromStart <= lineLength) | |||
| return line.getPointAlongLine (distanceFromStart); | |||
| distanceFromStart -= lineLength; | |||
| } | |||
| return Point<float> (i.x2, i.y2); | |||
| } | |||
| float Path::getNearestPoint (const Point<float>& targetPoint, Point<float>& pointOnPath, | |||
| const AffineTransform& transform) const | |||
| { | |||
| PathFlatteningIterator i (*this, transform); | |||
| float bestPosition = 0, bestDistance = std::numeric_limits<float>::max(); | |||
| float length = 0; | |||
| Point<float> pointOnLine; | |||
| while (i.next()) | |||
| { | |||
| const Line<float> line (i.x1, i.y1, i.x2, i.y2); | |||
| const float distance = line.getDistanceFromPoint (targetPoint, pointOnLine); | |||
| if (distance < bestDistance) | |||
| { | |||
| bestDistance = distance; | |||
| bestPosition = length + pointOnLine.getDistanceFrom (line.getStart()); | |||
| pointOnPath = pointOnLine; | |||
| } | |||
| length += line.getLength(); | |||
| } | |||
| return bestPosition; | |||
| } | |||
| //============================================================================== | |||
| const Path Path::createPathWithRoundedCorners (const float cornerRadius) const | |||
| { | |||
| @@ -159,6 +159,27 @@ public: | |||
| */ | |||
| const Line<float> getClippedLine (const Line<float>& line, bool keepSectionOutsidePath) const; | |||
| /** Returns the length of the path. | |||
| @see getPointAlongPath | |||
| */ | |||
| float getLength (const AffineTransform& transform = AffineTransform::identity) const; | |||
| /** Returns a point that is the specified distance along the path. | |||
| If the distance is greater than the total length of the path, this will return the | |||
| end point. | |||
| @see getLength | |||
| */ | |||
| const Point<float> getPointAlongPath (float distanceFromStart, | |||
| const AffineTransform& transform = AffineTransform::identity) const; | |||
| /** Finds the point along the path which is nearest to a given position. | |||
| This sets pointOnPath to the nearest point, and returns the distance of this point from the start | |||
| of the path. | |||
| */ | |||
| float getNearestPoint (const Point<float>& targetPoint, | |||
| Point<float>& pointOnPath, | |||
| const AffineTransform& transform = AffineTransform::identity) const; | |||
| //============================================================================== | |||
| /** Removes all lines and curves, resetting the path completely. */ | |||
| void clear() throw(); | |||
| @@ -143,7 +143,7 @@ void PositionedRectangle::getRectangleDouble (const Rectangle<int>& target, | |||
| void PositionedRectangle::applyToComponent (Component& comp) const throw() | |||
| { | |||
| comp.setBounds (getRectangle (Rectangle<int> (0, 0, comp.getParentWidth(), comp.getParentHeight()))); | |||
| comp.setBounds (getRectangle (Rectangle<int> (comp.getParentWidth(), comp.getParentHeight()))); | |||
| } | |||
| //============================================================================== | |||
| @@ -167,7 +167,7 @@ void PositionedRectangle::updateFromComponent (const Component& comp) throw() | |||
| if (comp.getParentComponent() == 0 && ! comp.isOnDesktop()) | |||
| updateFrom (comp.getBounds(), Rectangle<int>()); | |||
| else | |||
| updateFrom (comp.getBounds(), Rectangle<int> (0, 0, comp.getParentWidth(), comp.getParentHeight())); | |||
| updateFrom (comp.getBounds(), Rectangle<int> (comp.getParentWidth(), comp.getParentHeight())); | |||
| } | |||
| //============================================================================== | |||
| @@ -149,7 +149,7 @@ public: | |||
| /** Returns a rectangle with the same size as this image. | |||
| The rectangle's origin is always (0, 0). | |||
| */ | |||
| const Rectangle<int> getBounds() const throw() { return image == 0 ? Rectangle<int>() : Rectangle<int> (0, 0, image->width, image->height); } | |||
| const Rectangle<int> getBounds() const throw() { return image == 0 ? Rectangle<int>() : Rectangle<int> (image->width, image->height); } | |||
| /** Returns the image's pixel format. */ | |||
| PixelFormat getFormat() const throw() { return image == 0 ? UnknownFormat : image->format; } | |||
| @@ -2851,8 +2851,7 @@ void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, const | |||
| if (monitorCoords.size() == 0) | |||
| { | |||
| monitorCoords.add (Rectangle<int> (0, 0, | |||
| DisplayWidth (display, DefaultScreen (display)), | |||
| monitorCoords.add (Rectangle<int> (DisplayWidth (display, DefaultScreen (display)), | |||
| DisplayHeight (display, DefaultScreen (display)))); | |||
| } | |||
| } | |||
| @@ -232,7 +232,7 @@ public: | |||
| - (void) createConnection | |||
| { | |||
| NSInteger oldRetainCount = [self retainCount]; | |||
| NSUInteger oldRetainCount = [self retainCount]; | |||
| connection = [[NSURLConnection alloc] initWithRequest: request | |||
| delegate: self]; | |||
| @@ -1185,7 +1185,7 @@ private: | |||
| if (needToPaintAll) | |||
| { | |||
| contextClip.clear(); | |||
| contextClip.addWithoutMerging (Rectangle<int> (0, 0, w, h)); | |||
| contextClip.addWithoutMerging (Rectangle<int> (w, h)); | |||
| } | |||
| if (transparent) | |||