| @@ -766,7 +766,13 @@ public: | |||
| const Value getPositionValue (UndoManager* undoManager) | |||
| { | |||
| jassertfalse | |||
| switch (cpNum) | |||
| { | |||
| case 0: return item.getPropertyAsValue (DrawableImage::ValueTreeWrapper::topLeft, undoManager); | |||
| case 1: return item.getPropertyAsValue (DrawableImage::ValueTreeWrapper::topRight, undoManager); | |||
| case 2: return item.getPropertyAsValue (DrawableImage::ValueTreeWrapper::bottomLeft, undoManager); | |||
| default: jassertfalse; break; | |||
| } | |||
| return Value(); | |||
| } | |||
| @@ -136,7 +136,8 @@ public: | |||
| { | |||
| if (state.hasType (DrawablePath::valueTreeType) | |||
| || state.hasType (DrawableImage::valueTreeType) | |||
| || state.hasType (DrawableText::valueTreeType)) | |||
| || state.hasType (DrawableText::valueTreeType) | |||
| || state.hasType (DrawableComposite::valueTreeType)) | |||
| { | |||
| enableControlPointMode (state); | |||
| } | |||
| @@ -59,14 +59,13 @@ public: | |||
| { | |||
| } | |||
| static void showAt (Component* comp, const Value& colourValue, | |||
| static void showAt (Component* targetComp, const Value& colourValue, | |||
| const Colour& defaultColour, const bool canResetToDefault) | |||
| { | |||
| PopupColourSelector colourSelector (colourValue, defaultColour, canResetToDefault); | |||
| colourSelector.setSize (300, 400); | |||
| PopupMenu m; | |||
| m.addCustomItem (1234, &colourSelector, 300, 400, false); | |||
| m.showAt (comp); | |||
| PopupComponent::show (&colourSelector, targetComp, 0 /*targetComp->getTopLevelComponent()*/); | |||
| } | |||
| void resized() | |||
| @@ -59,14 +59,17 @@ public: | |||
| addAndMakeVisible (&imageButton); | |||
| addChildComponent (&colourPicker); | |||
| colourPicker.setSize (300, 410); | |||
| colourPicker.setCurrentColour (Colours::green); | |||
| colourPicker.setName ("Colour"); | |||
| colourPicker.addChangeListener (this); | |||
| addChildComponent (&gradientPicker); | |||
| gradientPicker.setSize (300, 500); | |||
| gradientPicker.addChangeListener (this); | |||
| addChildComponent (&tilePicker); | |||
| tilePicker.setSize (300, 170); | |||
| tilePicker.addChangeListener (this); | |||
| fillState.addListener (this); | |||
| @@ -79,6 +82,7 @@ public: | |||
| gradientButton.addButtonListener (this); | |||
| imageButton.addButtonListener (this); | |||
| setSize (300, 200); | |||
| refresh(); | |||
| } | |||
| @@ -96,10 +100,9 @@ public: | |||
| colourButton.setBounds (gradientButton.getX() - w, y, w, h); | |||
| imageButton.setBounds (gradientButton.getRight(), y, w, h); | |||
| const Rectangle<int> content (2, y + h + 4, getWidth() - 4, getHeight() - (y + h + 6)); | |||
| colourPicker.setBounds (content); | |||
| gradientPicker.setBounds (content); | |||
| tilePicker.setBounds (content); | |||
| colourPicker.setTopLeftPosition (2, y + h + 4); | |||
| gradientPicker.setTopLeftPosition (2, y + h + 4); | |||
| tilePicker.setTopLeftPosition (2, y + h + 4); | |||
| } | |||
| void buttonClicked (Button* b) | |||
| @@ -187,11 +190,15 @@ public: | |||
| if (newFill.isColour()) | |||
| { | |||
| setSize (getWidth(), colourPicker.getBottom() + 4); | |||
| colourButton.setToggleState (true, false); | |||
| colourPicker.setCurrentColour (newFill.colour); | |||
| } | |||
| else if (newFill.isGradient()) | |||
| { | |||
| setSize (getWidth(), gradientPicker.getBottom() + 4); | |||
| if (newFill.gradient->getNumColours() <= 1) | |||
| { | |||
| newFill = FillType (defaultGradient); | |||
| @@ -203,6 +210,7 @@ public: | |||
| } | |||
| else | |||
| { | |||
| setSize (getWidth(), tilePicker.getBottom() + 4); | |||
| tilePicker.setFill (newFill); | |||
| imageButton.setToggleState (true, false); | |||
| } | |||
| @@ -463,6 +471,7 @@ private: | |||
| opacitySlider.setRange (0.0, 1.0, 0.001); | |||
| sliderLabel.setText ("Opacity:", false); | |||
| sliderLabel.setColour (Label::textColourId, Colours::white); | |||
| sliderLabel.attachToComponent (&opacitySlider, false); | |||
| OwnedArray<Project::Item> images; | |||
| @@ -641,10 +650,7 @@ public: | |||
| undoManager->beginNewTransaction(); | |||
| PopupFillSelector popup (fillState, getDefaultGradient(), imageProvider, project, undoManager); | |||
| PopupMenu m; | |||
| m.addCustomItem (1234, &popup, 300, 450, false); | |||
| m.showAt (this); | |||
| PopupComponent::show (&popup, this, 0 /*getTopLevelComponent()*/); | |||
| } | |||
| void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const Identifier& property) { refresh(); } | |||
| @@ -415,3 +415,208 @@ const ColourGradient FillTypeEditorComponent::getDefaultGradient() const | |||
| jassert (p != 0); | |||
| return p->getDefaultGradient(); | |||
| } | |||
| //============================================================================== | |||
| PopupComponent::PopupComponent (Component* const content_) | |||
| : edge (20), content (content_) | |||
| { | |||
| addAndMakeVisible (content); | |||
| } | |||
| PopupComponent::~PopupComponent() | |||
| { | |||
| } | |||
| void PopupComponent::show (Component* content, Component* targetComp, Component* parentComp) | |||
| { | |||
| show (content, | |||
| parentComp, | |||
| parentComp == 0 ? targetComp->getParentMonitorArea() | |||
| : parentComp->getLocalBounds(), | |||
| parentComp == 0 ? targetComp->getScreenBounds() | |||
| : (targetComp->getLocalBounds() + targetComp->relativePositionToOtherComponent (parentComp, Point<int>()))); | |||
| } | |||
| void PopupComponent::show (Component* content, Component* parent, | |||
| const Rectangle<int>& availableAreaInParent, | |||
| const Rectangle<int>& targetAreaInParent) | |||
| { | |||
| PopupComponent p (content); | |||
| p.updatePosition (targetAreaInParent, availableAreaInParent); | |||
| if (parent != 0) | |||
| parent->addAndMakeVisible (&p); | |||
| else | |||
| p.addToDesktop (ComponentPeer::windowIsTemporary); | |||
| p.runModalLoop(); | |||
| } | |||
| void PopupComponent::inputAttemptWhenModal() | |||
| { | |||
| exitModalState (0); | |||
| setVisible (false); | |||
| } | |||
| void PopupComponent::paint (Graphics& g) | |||
| { | |||
| if (background.isNull()) | |||
| { | |||
| DropShadowEffect shadow; | |||
| shadow.setShadowProperties (5.0f, 0.4f, 0.0f, 2.0f); | |||
| Image im (Image::ARGB, getWidth(), getHeight(), true); | |||
| { | |||
| Graphics g (im); | |||
| g.setColour (Colour::greyLevel (0.23f).withAlpha (0.9f)); | |||
| g.fillPath (outline); | |||
| g.setColour (Colours::white.withAlpha (0.6f)); | |||
| g.strokePath (outline, PathStrokeType (2.0f)); | |||
| } | |||
| background = Image (Image::ARGB, getWidth(), getHeight(), true); | |||
| Graphics g (background); | |||
| shadow.applyEffect (im, g); | |||
| } | |||
| g.setColour (Colours::black); | |||
| g.drawImageAt (background, 0, 0); | |||
| } | |||
| void PopupComponent::resized() | |||
| { | |||
| content->setTopLeftPosition (edge, edge); | |||
| refreshPath(); | |||
| } | |||
| void PopupComponent::moved() | |||
| { | |||
| refreshPath(); | |||
| } | |||
| void PopupComponent::childBoundsChanged (Component*) | |||
| { | |||
| updatePosition (targetArea, availableArea); | |||
| } | |||
| bool PopupComponent::hitTest (int x, int y) | |||
| { | |||
| return outline.contains (x, y); | |||
| } | |||
| void PopupComponent::refreshPath() | |||
| { | |||
| background = Image(); | |||
| outline.clear(); | |||
| const float gap = 4.0f; | |||
| const float x = content->getX() - gap, y = content->getY() - gap, r = content->getRight() + gap, b = content->getBottom() + gap; | |||
| const float targetX = targetPoint.getX() - getX(), targetY = targetPoint.getY() - getY(); | |||
| const float cs = 8.0f; | |||
| const float cs2 = 2.0f * cs; | |||
| const float arrowWidth = edge * 0.8f; | |||
| outline.startNewSubPath (x + cs, y); | |||
| if (targetY < edge) | |||
| { | |||
| outline.lineTo (targetX - arrowWidth, y); | |||
| outline.lineTo (targetX, targetY); | |||
| outline.lineTo (targetX + arrowWidth, y); | |||
| } | |||
| outline.lineTo (r - cs, y); | |||
| outline.addArc (r - cs2, y, cs2, cs2, 0, float_Pi * 0.5f); | |||
| if (targetX > r) | |||
| { | |||
| outline.lineTo (r, targetY - arrowWidth); | |||
| outline.lineTo (targetX, targetY); | |||
| outline.lineTo (r, targetY + arrowWidth); | |||
| } | |||
| outline.lineTo (r, b - cs); | |||
| outline.addArc (r - cs2, b - cs2, cs2, cs2, float_Pi * 0.5f, float_Pi); | |||
| if (targetY > b) | |||
| { | |||
| outline.lineTo (targetX + arrowWidth, b); | |||
| outline.lineTo (targetX, targetY); | |||
| outline.lineTo (targetX - arrowWidth, b); | |||
| } | |||
| outline.lineTo (x + cs, b); | |||
| outline.addArc (x, b - cs2, cs2, cs2, float_Pi, float_Pi * 1.5f); | |||
| if (targetX < x) | |||
| { | |||
| outline.lineTo (x, targetY + arrowWidth); | |||
| outline.lineTo (targetX, targetY); | |||
| outline.lineTo (x, targetY - arrowWidth); | |||
| } | |||
| outline.lineTo (x, y + cs); | |||
| outline.addArc (x, y, cs2, cs2, float_Pi * 1.5f, float_Pi * 2.0f - 0.05f); | |||
| outline.closeSubPath(); | |||
| repaint(); | |||
| } | |||
| void PopupComponent::updatePosition (const Rectangle<int>& newTargetArea, const Rectangle<int>& newArea) | |||
| { | |||
| targetArea = newTargetArea; | |||
| availableArea = newArea; | |||
| Rectangle<int> r (0, 0, | |||
| content->getWidth() + edge * 2, | |||
| content->getHeight() + edge * 2); | |||
| const float hw = r.getWidth() / 2.0f; | |||
| const float hh = r.getHeight() / 2.0f; | |||
| const float hwReduced = hw - edge * 3; | |||
| const float hhReduced = hh - edge * 3; | |||
| Point<float> centres[4]; | |||
| Point<float> targets[4] = { Point<float> (targetArea.getCentreX(), targetArea.getBottom()), | |||
| Point<float> (targetArea.getRight(), targetArea.getCentreY()), | |||
| Point<float> (targetArea.getX(), targetArea.getCentreY()), | |||
| Point<float> (targetArea.getCentreX(), targetArea.getY()) }; | |||
| Line<float> lines[4] = { Line<float> (targets[0] + Point<float> (-hwReduced, hh), targets[0] + Point<float> (hwReduced, hh)), | |||
| Line<float> (targets[1] + Point<float> (hw, -hhReduced), targets[1] + Point<float> (hw, hhReduced)), | |||
| Line<float> (targets[2] + Point<float> (-hw, -hhReduced), targets[2] + Point<float> (-hw, hhReduced)), | |||
| Line<float> (targets[3] + Point<float> (-hwReduced, -hh), targets[3] + Point<float> (hwReduced, -hh)) }; | |||
| int best = 0; | |||
| float bestDist = 1.0e9f; | |||
| for (int i = 0; i < 4; ++i) | |||
| { | |||
| const Rectangle<float> reducedArea (newArea.reduced (hw, hh).toFloat()); | |||
| Line<float> constrainedLine (reducedArea.getConstrainedPoint (lines[i].getStart()), | |||
| reducedArea.getConstrainedPoint (lines[i].getEnd())); | |||
| centres[i] = constrainedLine.findNearestPointTo (reducedArea.getCentre()); | |||
| float dist = centres[i].getDistanceFrom (reducedArea.getCentre()); | |||
| if (! (reducedArea.contains (lines[i].getStart()) || reducedArea.contains (lines[i].getEnd()))) | |||
| dist *= 2.0f; | |||
| if (dist < bestDist) | |||
| { | |||
| bestDist = dist; | |||
| best = i; | |||
| } | |||
| } | |||
| targetPoint = targets[best]; | |||
| r.setPosition (centres[best].getX() - hw, centres[best].getY() - hh); | |||
| setBounds (r); | |||
| } | |||
| @@ -85,24 +85,33 @@ private: | |||
| class PopupComponent : public Component | |||
| { | |||
| public: | |||
| PopupComponent() | |||
| { | |||
| } | |||
| PopupComponent (Component* const content); | |||
| ~PopupComponent(); | |||
| ~PopupComponent() | |||
| { | |||
| } | |||
| static void show (Component* content, Component* targetComp, Component* parentComp); | |||
| static PopupComponent* create (Component* parent, Component* content, | |||
| const Point<int>& targetPoint, | |||
| const Rectangle<int>& area) | |||
| { | |||
| ScopedPointer<PopupComponent> p (new PopupComponent()); | |||
| static void show (Component* content, Component* parent, | |||
| const Rectangle<int>& availableAreaInParent, | |||
| const Rectangle<int>& targetAreaInParent); | |||
| parent->addAndMakeVisible (p); | |||
| void updatePosition (const Rectangle<int>& newTargetArea, const Rectangle<int>& newArea); | |||
| return p.release(); | |||
| } | |||
| void inputAttemptWhenModal(); | |||
| void paint (Graphics& g); | |||
| void resized(); | |||
| void moved(); | |||
| void childBoundsChanged (Component*); | |||
| bool hitTest (int x, int y); | |||
| private: | |||
| const int edge; | |||
| Component* content; | |||
| Path outline; | |||
| Point<float> targetPoint; | |||
| Rectangle<int> availableArea, targetArea; | |||
| Image background; | |||
| void refreshPath(); | |||
| }; | |||
| @@ -70230,6 +70230,8 @@ public: | |||
| if (buttonState == newButtonState) | |||
| return false; | |||
| setScreenPos (screenPos, time, false); | |||
| // (ignore secondary clicks when there's already a button down) | |||
| if (buttonState.isAnyMouseButtonDown() == newButtonState.isAnyMouseButtonDown()) | |||
| { | |||
| @@ -80280,9 +80282,9 @@ void Graphics::setOrigin (const int newOriginX, const int newOriginY) | |||
| context->setOrigin (newOriginX, newOriginY); | |||
| } | |||
| bool Graphics::clipRegionIntersects (const int x, const int y, const int w, const int h) const | |||
| bool Graphics::clipRegionIntersects (const Rectangle<int>& area) const | |||
| { | |||
| return context->clipRegionIntersects (Rectangle<int> (x, y, w, h)); | |||
| return context->clipRegionIntersects (area); | |||
| } | |||
| void Graphics::setColour (const Colour& newColour) | |||
| @@ -80508,7 +80510,7 @@ void Graphics::drawBevel (const int x, const int y, const int width, const int h | |||
| // passing in a silly number can cause maths problems in rendering! | |||
| jassert (areCoordsSensibleNumbers (x, y, width, height)); | |||
| if (clipRegionIntersects (x, y, width, height)) | |||
| if (clipRegionIntersects (Rectangle<int> (x, y, width, height))) | |||
| { | |||
| context->saveState(); | |||
| @@ -81527,8 +81529,7 @@ public: | |||
| p2.applyTransform (transform); | |||
| p3.applyTransform (transform); | |||
| const Line<float> l2 (p2, p3); | |||
| p2 = l2.getPointAlongLineProportionally (l2.findNearestPointTo (p1)); | |||
| p2 = Line<float> (p2, p3).findNearestPointTo (p1); | |||
| } | |||
| vertical = std::abs (p1.getX() - p2.getX()) < 0.001f; | |||
| @@ -84492,17 +84493,17 @@ void DrawableComposite::ValueTreeWrapper::removeMarker (bool xAxis, const ValueT | |||
| const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | |||
| { | |||
| Rectangle<float> damageRect; | |||
| const ValueTreeWrapper wrapper (tree); | |||
| setName (wrapper.getID()); | |||
| const RelativeParallelogram newBounds (wrapper.getBoundingBox()); | |||
| Rectangle<float> damage; | |||
| bool redrawAll = false; | |||
| const RelativeParallelogram newBounds (wrapper.getBoundingBox()); | |||
| if (bounds != newBounds) | |||
| { | |||
| redrawAll = true; | |||
| damageRect = getUntransformedBounds(); | |||
| damage = getBounds(); | |||
| bounds = newBounds; | |||
| } | |||
| @@ -84512,8 +84513,11 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| // Remove deleted markers... | |||
| if (markersX.size() > numMarkersX || markersY.size() > numMarkersY) | |||
| { | |||
| if (damageRect.isEmpty()) | |||
| damageRect = getUntransformedBounds(); | |||
| if (! redrawAll) | |||
| { | |||
| redrawAll = true; | |||
| damage = getBounds(); | |||
| } | |||
| markersX.removeRange (jmax (2, numMarkersX), markersX.size()); | |||
| markersY.removeRange (jmax (2, numMarkersY), markersY.size()); | |||
| @@ -84528,9 +84532,11 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| if (m == 0 || newMarker != *m) | |||
| { | |||
| redrawAll = true; | |||
| if (damageRect.isEmpty()) | |||
| damageRect = getUntransformedBounds(); | |||
| if (! redrawAll) | |||
| { | |||
| redrawAll = true; | |||
| damage = getBounds(); | |||
| } | |||
| if (m == 0) | |||
| markersX.add (new Marker (newMarker)); | |||
| @@ -84546,9 +84552,11 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| if (m == 0 || newMarker != *m) | |||
| { | |||
| redrawAll = true; | |||
| if (damageRect.isEmpty()) | |||
| damageRect = getUntransformedBounds(); | |||
| if (! redrawAll) | |||
| { | |||
| redrawAll = true; | |||
| damage = getBounds(); | |||
| } | |||
| if (m == 0) | |||
| markersY.add (new Marker (newMarker)); | |||
| @@ -84561,7 +84569,10 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| for (i = drawables.size(); --i >= wrapper.getNumDrawables();) | |||
| { | |||
| Drawable* const d = drawables.getUnchecked(i); | |||
| damageRect = damageRect.getUnion (d->getBounds()); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (d->getBounds()); | |||
| d->parent = 0; | |||
| drawables.remove (i); | |||
| } | |||
| @@ -84576,28 +84587,39 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| { | |||
| if (newDrawable.hasType (d->getValueTreeType())) | |||
| { | |||
| damageRect = damageRect.getUnion (d->refreshFromValueTree (newDrawable, imageProvider)); | |||
| const Rectangle<float> area (d->refreshFromValueTree (newDrawable, imageProvider)); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (area); | |||
| } | |||
| else | |||
| { | |||
| damageRect = damageRect.getUnion (d->getBounds()); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (d->getBounds()); | |||
| d = createChildFromValueTree (this, newDrawable, imageProvider); | |||
| drawables.set (i, d); | |||
| damageRect = damageRect.getUnion (d->getBounds()); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (d->getBounds()); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| d = createChildFromValueTree (this, newDrawable, imageProvider); | |||
| drawables.set (i, d); | |||
| damageRect = damageRect.getUnion (d->getBounds()); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (d->getBounds()); | |||
| } | |||
| } | |||
| if (redrawAll) | |||
| damageRect = damageRect.getUnion (getUntransformedBounds()); | |||
| damage = damage.getUnion (getBounds()); | |||
| else if (! damage.isEmpty()) | |||
| damage = damage.transformed (calculateTransform()); | |||
| return damageRect.transformed (calculateTransform()); | |||
| return damage; | |||
| } | |||
| const ValueTree DrawableComposite::createValueTree (ImageProvider* imageProvider) const | |||
| @@ -270049,6 +270071,11 @@ END_JUCE_NAMESPACE | |||
| if (owner != 0) | |||
| frameRect = owner->constrainRect (frameRect); | |||
| if (JUCE_NAMESPACE::Component::getCurrentlyModalComponent() != 0 | |||
| && owner->getComponent()->isCurrentlyBlockedByAnotherModalComponent() | |||
| && (owner->getStyleFlags() & JUCE_NAMESPACE::ComponentPeer::windowHasTitleBar) != 0) | |||
| JUCE_NAMESPACE::Component::getCurrentlyModalComponent()->inputAttemptWhenModal(); | |||
| return frameRect.size; | |||
| } | |||
| @@ -20077,7 +20077,7 @@ public: | |||
| @returns the point's distance from the line | |||
| @see getPositionAlongLineOfNearestPoint | |||
| */ | |||
| ValueType getDistanceFromLine (const Point<ValueType>& point) const throw() | |||
| ValueType getDistanceFromPoint (const Point<ValueType>& point) const throw() | |||
| { | |||
| const Point<ValueType> delta (end - start); | |||
| const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY(); | |||
| @@ -20101,9 +20101,9 @@ public: | |||
| @returns a value 0 to 1.0 which is the distance along this line from the | |||
| line's start to the point which is nearest to the point passed-in. To | |||
| turn this number into a position, use getPointAlongLineProportionally(). | |||
| @see getDistanceFromLine, getPointAlongLineProportionally | |||
| @see getDistanceFromPoint, getPointAlongLineProportionally | |||
| */ | |||
| ValueType findNearestPointTo (const Point<ValueType>& point) const throw() | |||
| ValueType findNearestProportionalPositionTo (const Point<ValueType>& point) const throw() | |||
| { | |||
| const Point<ValueType> delta (end - start); | |||
| const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY(); | |||
| @@ -20114,6 +20114,14 @@ public: | |||
| + (point.getY() - start.getY()) * delta.getY()) / length)); | |||
| } | |||
| /** Finds the point on this line which is nearest to a given point. | |||
| @see getDistanceFromPoint, findNearestProportionalPositionTo | |||
| */ | |||
| const Point<ValueType> findNearestPointTo (const Point<ValueType>& point) const throw() | |||
| { | |||
| return getPointAlongLineProportionally (findNearestProportionalPositionTo (point)); | |||
| } | |||
| /** Returns true if the given point lies above this line. | |||
| The return value is true if the point's y coordinate is less than the y | |||
| @@ -24064,7 +24072,7 @@ public: | |||
| method can be used to optimise a component's paint() method, by letting it | |||
| avoid drawing complex objects that aren't within the region being repainted. | |||
| */ | |||
| bool clipRegionIntersects (int x, int y, int width, int height) const; | |||
| bool clipRegionIntersects (const Rectangle<int>& area) const; | |||
| /** Intersects the current clipping region with another region. | |||
| @@ -148,6 +148,8 @@ public: | |||
| if (buttonState == newButtonState) | |||
| return false; | |||
| setScreenPos (screenPos, time, false); | |||
| // (ignore secondary clicks when there's already a button down) | |||
| if (buttonState.isAnyMouseButtonDown() == newButtonState.isAnyMouseButtonDown()) | |||
| { | |||
| @@ -159,9 +159,9 @@ void Graphics::setOrigin (const int newOriginX, const int newOriginY) | |||
| context->setOrigin (newOriginX, newOriginY); | |||
| } | |||
| bool Graphics::clipRegionIntersects (const int x, const int y, const int w, const int h) const | |||
| bool Graphics::clipRegionIntersects (const Rectangle<int>& area) const | |||
| { | |||
| return context->clipRegionIntersects (Rectangle<int> (x, y, w, h)); | |||
| return context->clipRegionIntersects (area); | |||
| } | |||
| //============================================================================== | |||
| @@ -394,7 +394,7 @@ void Graphics::drawBevel (const int x, const int y, const int width, const int h | |||
| // passing in a silly number can cause maths problems in rendering! | |||
| jassert (areCoordsSensibleNumbers (x, y, width, height)); | |||
| if (clipRegionIntersects (x, y, width, height)) | |||
| if (clipRegionIntersects (Rectangle<int> (x, y, width, height))) | |||
| { | |||
| context->saveState(); | |||
| @@ -558,7 +558,7 @@ public: | |||
| method can be used to optimise a component's paint() method, by letting it | |||
| avoid drawing complex objects that aren't within the region being repainted. | |||
| */ | |||
| bool clipRegionIntersects (int x, int y, int width, int height) const; | |||
| bool clipRegionIntersects (const Rectangle<int>& area) const; | |||
| /** Intersects the current clipping region with another region. | |||
| @@ -210,8 +210,7 @@ public: | |||
| p2.applyTransform (transform); | |||
| p3.applyTransform (transform); | |||
| const Line<float> l2 (p2, p3); | |||
| p2 = l2.getPointAlongLineProportionally (l2.findNearestPointTo (p1)); | |||
| p2 = Line<float> (p2, p3).findNearestPointTo (p1); | |||
| } | |||
| vertical = std::abs (p1.getX() - p2.getX()) < 0.001f; | |||
| @@ -564,17 +564,17 @@ void DrawableComposite::ValueTreeWrapper::removeMarker (bool xAxis, const ValueT | |||
| //============================================================================== | |||
| const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | |||
| { | |||
| Rectangle<float> damageRect; | |||
| const ValueTreeWrapper wrapper (tree); | |||
| setName (wrapper.getID()); | |||
| const RelativeParallelogram newBounds (wrapper.getBoundingBox()); | |||
| Rectangle<float> damage; | |||
| bool redrawAll = false; | |||
| const RelativeParallelogram newBounds (wrapper.getBoundingBox()); | |||
| if (bounds != newBounds) | |||
| { | |||
| redrawAll = true; | |||
| damageRect = getUntransformedBounds(); | |||
| damage = getBounds(); | |||
| bounds = newBounds; | |||
| } | |||
| @@ -584,8 +584,11 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| // Remove deleted markers... | |||
| if (markersX.size() > numMarkersX || markersY.size() > numMarkersY) | |||
| { | |||
| if (damageRect.isEmpty()) | |||
| damageRect = getUntransformedBounds(); | |||
| if (! redrawAll) | |||
| { | |||
| redrawAll = true; | |||
| damage = getBounds(); | |||
| } | |||
| markersX.removeRange (jmax (2, numMarkersX), markersX.size()); | |||
| markersY.removeRange (jmax (2, numMarkersY), markersY.size()); | |||
| @@ -600,9 +603,11 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| if (m == 0 || newMarker != *m) | |||
| { | |||
| redrawAll = true; | |||
| if (damageRect.isEmpty()) | |||
| damageRect = getUntransformedBounds(); | |||
| if (! redrawAll) | |||
| { | |||
| redrawAll = true; | |||
| damage = getBounds(); | |||
| } | |||
| if (m == 0) | |||
| markersX.add (new Marker (newMarker)); | |||
| @@ -618,9 +623,11 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| if (m == 0 || newMarker != *m) | |||
| { | |||
| redrawAll = true; | |||
| if (damageRect.isEmpty()) | |||
| damageRect = getUntransformedBounds(); | |||
| if (! redrawAll) | |||
| { | |||
| redrawAll = true; | |||
| damage = getBounds(); | |||
| } | |||
| if (m == 0) | |||
| markersY.add (new Marker (newMarker)); | |||
| @@ -633,7 +640,10 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| for (i = drawables.size(); --i >= wrapper.getNumDrawables();) | |||
| { | |||
| Drawable* const d = drawables.getUnchecked(i); | |||
| damageRect = damageRect.getUnion (d->getBounds()); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (d->getBounds()); | |||
| d->parent = 0; | |||
| drawables.remove (i); | |||
| } | |||
| @@ -648,28 +658,39 @@ const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& | |||
| { | |||
| if (newDrawable.hasType (d->getValueTreeType())) | |||
| { | |||
| damageRect = damageRect.getUnion (d->refreshFromValueTree (newDrawable, imageProvider)); | |||
| const Rectangle<float> area (d->refreshFromValueTree (newDrawable, imageProvider)); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (area); | |||
| } | |||
| else | |||
| { | |||
| damageRect = damageRect.getUnion (d->getBounds()); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (d->getBounds()); | |||
| d = createChildFromValueTree (this, newDrawable, imageProvider); | |||
| drawables.set (i, d); | |||
| damageRect = damageRect.getUnion (d->getBounds()); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (d->getBounds()); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| d = createChildFromValueTree (this, newDrawable, imageProvider); | |||
| drawables.set (i, d); | |||
| damageRect = damageRect.getUnion (d->getBounds()); | |||
| if (! redrawAll) | |||
| damage = damage.getUnion (d->getBounds()); | |||
| } | |||
| } | |||
| if (redrawAll) | |||
| damageRect = damageRect.getUnion (getUntransformedBounds()); | |||
| damage = damage.getUnion (getBounds()); | |||
| else if (! damage.isEmpty()) | |||
| damage = damage.transformed (calculateTransform()); | |||
| return damageRect.transformed (calculateTransform()); | |||
| return damage; | |||
| } | |||
| const ValueTree DrawableComposite::createValueTree (ImageProvider* imageProvider) const | |||
| @@ -241,7 +241,7 @@ public: | |||
| @returns the point's distance from the line | |||
| @see getPositionAlongLineOfNearestPoint | |||
| */ | |||
| ValueType getDistanceFromLine (const Point<ValueType>& point) const throw() | |||
| ValueType getDistanceFromPoint (const Point<ValueType>& point) const throw() | |||
| { | |||
| const Point<ValueType> delta (end - start); | |||
| const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY(); | |||
| @@ -265,9 +265,9 @@ public: | |||
| @returns a value 0 to 1.0 which is the distance along this line from the | |||
| line's start to the point which is nearest to the point passed-in. To | |||
| turn this number into a position, use getPointAlongLineProportionally(). | |||
| @see getDistanceFromLine, getPointAlongLineProportionally | |||
| @see getDistanceFromPoint, getPointAlongLineProportionally | |||
| */ | |||
| ValueType findNearestPointTo (const Point<ValueType>& point) const throw() | |||
| ValueType findNearestProportionalPositionTo (const Point<ValueType>& point) const throw() | |||
| { | |||
| const Point<ValueType> delta (end - start); | |||
| const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY(); | |||
| @@ -278,6 +278,14 @@ public: | |||
| + (point.getY() - start.getY()) * delta.getY()) / length)); | |||
| } | |||
| /** Finds the point on this line which is nearest to a given point. | |||
| @see getDistanceFromPoint, findNearestProportionalPositionTo | |||
| */ | |||
| const Point<ValueType> findNearestPointTo (const Point<ValueType>& point) const throw() | |||
| { | |||
| return getPointAlongLineProportionally (findNearestProportionalPositionTo (point)); | |||
| } | |||
| /** Returns true if the given point lies above this line. | |||
| The return value is true if the point's y coordinate is less than the y | |||
| @@ -740,6 +740,11 @@ END_JUCE_NAMESPACE | |||
| if (owner != 0) | |||
| frameRect = owner->constrainRect (frameRect); | |||
| if (JUCE_NAMESPACE::Component::getCurrentlyModalComponent() != 0 | |||
| && owner->getComponent()->isCurrentlyBlockedByAnotherModalComponent() | |||
| && (owner->getStyleFlags() & JUCE_NAMESPACE::ComponentPeer::windowHasTitleBar) != 0) | |||
| JUCE_NAMESPACE::Component::getCurrentlyModalComponent()->inputAttemptWhenModal(); | |||
| return frameRect.size; | |||
| } | |||