@@ -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; | |||
} | |||