diff --git a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableTypeHandler.cpp b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableTypeHandler.cpp index 1f990442d0..a374700407 100644 --- a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableTypeHandler.cpp +++ b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableTypeHandler.cpp @@ -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(); } diff --git a/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorCanvas.h b/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorCanvas.h index 909d933ee5..647a2257a7 100644 --- a/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorCanvas.h +++ b/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorCanvas.h @@ -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); } diff --git a/extras/Jucer (experimental)/Source/utility/jucer_ColourPropertyComponent.h b/extras/Jucer (experimental)/Source/utility/jucer_ColourPropertyComponent.h index 1757d13b19..3c624a978e 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_ColourPropertyComponent.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_ColourPropertyComponent.h @@ -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() diff --git a/extras/Jucer (experimental)/Source/utility/jucer_FillTypePropertyComponent.h b/extras/Jucer (experimental)/Source/utility/jucer_FillTypePropertyComponent.h index 7be5da1027..b80adb6b24 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_FillTypePropertyComponent.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_FillTypePropertyComponent.h @@ -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 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 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(); } diff --git a/extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.cpp b/extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.cpp index 4fb15c2c33..aa52421d97 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.cpp +++ b/extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.cpp @@ -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()))); +} + +void PopupComponent::show (Component* content, Component* parent, + const Rectangle& availableAreaInParent, + const Rectangle& 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& newTargetArea, const Rectangle& newArea) +{ + targetArea = newTargetArea; + availableArea = newArea; + + Rectangle 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 centres[4]; + Point targets[4] = { Point (targetArea.getCentreX(), targetArea.getBottom()), + Point (targetArea.getRight(), targetArea.getCentreY()), + Point (targetArea.getX(), targetArea.getCentreY()), + Point (targetArea.getCentreX(), targetArea.getY()) }; + + Line lines[4] = { Line (targets[0] + Point (-hwReduced, hh), targets[0] + Point (hwReduced, hh)), + Line (targets[1] + Point (hw, -hhReduced), targets[1] + Point (hw, hhReduced)), + Line (targets[2] + Point (-hw, -hhReduced), targets[2] + Point (-hw, hhReduced)), + Line (targets[3] + Point (-hwReduced, -hh), targets[3] + Point (hwReduced, -hh)) }; + + int best = 0; + float bestDist = 1.0e9f; + + for (int i = 0; i < 4; ++i) + { + const Rectangle reducedArea (newArea.reduced (hw, hh).toFloat()); + + Line 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); +} diff --git a/extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.h b/extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.h index 8d13139140..617921cdfb 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.h @@ -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& targetPoint, - const Rectangle& area) - { - ScopedPointer p (new PopupComponent()); + static void show (Component* content, Component* parent, + const Rectangle& availableAreaInParent, + const Rectangle& targetAreaInParent); - parent->addAndMakeVisible (p); + void updatePosition (const Rectangle& newTargetArea, const Rectangle& 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 targetPoint; + Rectangle availableArea, targetArea; + Image background; + + void refreshPath(); }; diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index d875e96b48..b1b64f4d5b 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -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& area) const { - return context->clipRegionIntersects (Rectangle (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 (x, y, width, height))) { context->saveState(); @@ -81527,8 +81529,7 @@ public: p2.applyTransform (transform); p3.applyTransform (transform); - const Line l2 (p2, p3); - p2 = l2.getPointAlongLineProportionally (l2.findNearestPointTo (p1)); + p2 = Line (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 DrawableComposite::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) { - Rectangle damageRect; const ValueTreeWrapper wrapper (tree); setName (wrapper.getID()); - const RelativeParallelogram newBounds (wrapper.getBoundingBox()); + Rectangle 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 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 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 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 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 DrawableComposite::refreshFromValueTree (const ValueTree& { if (newDrawable.hasType (d->getValueTreeType())) { - damageRect = damageRect.getUnion (d->refreshFromValueTree (newDrawable, imageProvider)); + const Rectangle 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; } diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 6d7e324a60..eedb146dfb 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -20077,7 +20077,7 @@ public: @returns the point's distance from the line @see getPositionAlongLineOfNearestPoint */ - ValueType getDistanceFromLine (const Point& point) const throw() + ValueType getDistanceFromPoint (const Point& point) const throw() { const Point 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& point) const throw() + ValueType findNearestProportionalPositionTo (const Point& point) const throw() { const Point 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 findNearestPointTo (const Point& 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& area) const; /** Intersects the current clipping region with another region. diff --git a/src/gui/components/mouse/juce_MouseInputSource.cpp b/src/gui/components/mouse/juce_MouseInputSource.cpp index ba1fbd1e17..98a55c9314 100644 --- a/src/gui/components/mouse/juce_MouseInputSource.cpp +++ b/src/gui/components/mouse/juce_MouseInputSource.cpp @@ -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()) { diff --git a/src/gui/graphics/contexts/juce_Graphics.cpp b/src/gui/graphics/contexts/juce_Graphics.cpp index bc4fed65c9..5feee7a68a 100644 --- a/src/gui/graphics/contexts/juce_Graphics.cpp +++ b/src/gui/graphics/contexts/juce_Graphics.cpp @@ -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& area) const { - return context->clipRegionIntersects (Rectangle (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 (x, y, width, height))) { context->saveState(); diff --git a/src/gui/graphics/contexts/juce_Graphics.h b/src/gui/graphics/contexts/juce_Graphics.h index 6bac14d27a..080a982715 100644 --- a/src/gui/graphics/contexts/juce_Graphics.h +++ b/src/gui/graphics/contexts/juce_Graphics.h @@ -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& area) const; /** Intersects the current clipping region with another region. diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp index 76b8530c39..8b32b4855d 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp @@ -210,8 +210,7 @@ public: p2.applyTransform (transform); p3.applyTransform (transform); - const Line l2 (p2, p3); - p2 = l2.getPointAlongLineProportionally (l2.findNearestPointTo (p1)); + p2 = Line (p2, p3).findNearestPointTo (p1); } vertical = std::abs (p1.getX() - p2.getX()) < 0.001f; diff --git a/src/gui/graphics/drawables/juce_DrawableComposite.cpp b/src/gui/graphics/drawables/juce_DrawableComposite.cpp index 17c32d2c45..b2e1dd9235 100644 --- a/src/gui/graphics/drawables/juce_DrawableComposite.cpp +++ b/src/gui/graphics/drawables/juce_DrawableComposite.cpp @@ -564,17 +564,17 @@ void DrawableComposite::ValueTreeWrapper::removeMarker (bool xAxis, const ValueT //============================================================================== const Rectangle DrawableComposite::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) { - Rectangle damageRect; const ValueTreeWrapper wrapper (tree); setName (wrapper.getID()); - const RelativeParallelogram newBounds (wrapper.getBoundingBox()); + Rectangle 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 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 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 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 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 DrawableComposite::refreshFromValueTree (const ValueTree& { if (newDrawable.hasType (d->getValueTreeType())) { - damageRect = damageRect.getUnion (d->refreshFromValueTree (newDrawable, imageProvider)); + const Rectangle 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 diff --git a/src/gui/graphics/geometry/juce_Line.h b/src/gui/graphics/geometry/juce_Line.h index 24fe0cbaff..9c8ded755b 100644 --- a/src/gui/graphics/geometry/juce_Line.h +++ b/src/gui/graphics/geometry/juce_Line.h @@ -241,7 +241,7 @@ public: @returns the point's distance from the line @see getPositionAlongLineOfNearestPoint */ - ValueType getDistanceFromLine (const Point& point) const throw() + ValueType getDistanceFromPoint (const Point& point) const throw() { const Point 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& point) const throw() + ValueType findNearestProportionalPositionTo (const Point& point) const throw() { const Point 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 findNearestPointTo (const Point& 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 diff --git a/src/native/mac/juce_mac_NSViewComponentPeer.mm b/src/native/mac/juce_mac_NSViewComponentPeer.mm index 70279d33df..49ed93a214 100644 --- a/src/native/mac/juce_mac_NSViewComponentPeer.mm +++ b/src/native/mac/juce_mac_NSViewComponentPeer.mm @@ -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; }