diff --git a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp index 4ecef58d75..2c4c6efb0c 100644 --- a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp +++ b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp @@ -499,8 +499,15 @@ bool DrawableDocument::MarkerList::createProperties (Array & if (marker.isValid()) { - props.add (new TextPropertyComponent (marker.getPropertyAsValue (DrawableComposite::ValueTreeWrapper::nameProperty, getUndoManager()), - "Marker Name", 256, false)); + const String markerName (marker [DrawableComposite::ValueTreeWrapper::nameProperty].toString()); + + TextPropertyComponent* nameProp = new TextPropertyComponent (Value (new MarkerListBase::MarkerNameValueSource (this, marker.getPropertyAsValue (DrawableComposite::ValueTreeWrapper::nameProperty, getUndoManager()))), + "Marker Name", 256, false); + nameProp->setEnabled (markerName != DrawableComposite::contentLeftMarkerName + && markerName != DrawableComposite::contentRightMarkerName + && markerName != DrawableComposite::contentTopMarkerName + && markerName != DrawableComposite::contentBottomMarkerName); + props.add (nameProp); props.add (new MarkerListBase::PositionPropertyComponent (*this, "Position", marker, marker.getPropertyAsValue (DrawableComposite::ValueTreeWrapper::posProperty, getUndoManager()))); @@ -575,4 +582,27 @@ void DrawableDocument::MarkerList::renameAnchor (const String& oldName, const St void DrawableDocument::renameAnchor (const String& oldName, const String& newName) { + markersX->renameAnchorInMarkers (oldName, newName); + markersY->renameAnchorInMarkers (oldName, newName); + + DrawableComposite::ValueTreeWrapper root (getRootDrawableNode()); + DrawableTypeInstance rootItem (*this, root.getState()); + + for (int i = root.getNumDrawables(); --i >= 0;) + { + DrawableTypeInstance item (*this, root.getDrawableState(i)); + + OwnedArray points; + item.getAllControlPoints (points); + + for (int j = points.size(); --j >= 0;) + { + const RelativePoint oldPoint (points.getUnchecked(j)->getPosition()); + RelativePoint newPoint (oldPoint); + newPoint.renameAnchorIfUsed (oldName, newName, &rootItem); + + if (newPoint != oldPoint) + points.getUnchecked(j)->setPosition (newPoint, getUndoManager()); + } + } } diff --git a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorCanvas.h b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorCanvas.h index 52f02cd76c..dc878aa09b 100644 --- a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorCanvas.h +++ b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorCanvas.h @@ -36,6 +36,8 @@ public: ComponentEditorCanvas (ComponentEditor& editor_) : editor (editor_) { + background = ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, BinaryData::brushed_aluminium_pngSize); + initialise(); getDocument().getRoot().addListener (this); } @@ -68,6 +70,12 @@ public: startTimer (500); } + void fillBackground (Graphics& g) + { + g.setTiledImageFill (background, 0, 0, 1.0f); + g.fillAll(); + } + const Rectangle getCanvasBounds() { return Rectangle (0, 0, getDocument().getCanvasWidth().getValue(), @@ -298,6 +306,7 @@ public: private: //============================================================================== ComponentEditor& editor; + Image background; class ComponentHolder : public Component, public Value::Listener 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 9bac07319b..fcf90d029d 100644 --- a/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorCanvas.h +++ b/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorCanvas.h @@ -38,7 +38,9 @@ class DrawableEditorCanvas : public EditorCanvasBase, public: //============================================================================== DrawableEditorCanvas (DrawableEditor& editor_) - : editor (editor_) + : editor (editor_), + backgroundColour (Colour::greyLevel (0.95f)), + contentAreaColour (Colours::white) { initialise(); getDocument().getRoot().addListener (this); @@ -83,6 +85,11 @@ public: startTimer (500); } + void fillBackground (Graphics& g) + { + g.fillAll (backgroundColour); + } + const Rectangle getCanvasBounds() { return drawable->getBounds().getSmallestIntegerContainer(); @@ -91,6 +98,11 @@ public: void setCanvasBounds (const Rectangle& newBounds) {} bool canResizeCanvas() const { return false; } + const Rectangle getContentArea() const + { + return drawable->getContentArea().resolve (drawable->getParent()); + } + //============================================================================== const ValueTree getObjectState (const String& objectId) { @@ -705,27 +717,23 @@ public: DrawableComponent (DrawableEditorCanvas* canvas_) : canvas (canvas_) { - setOpaque (true); } ~DrawableComponent() { } - void updateDrawable() - { - repaint(); - } - void paint (Graphics& g) { - canvas->handleUpdateNowIfNeeded(); - g.fillAll (Colours::white); + // do not call canvas->handleUpdateNowIfNeeded() here! It resizes the component while we're painting it! const Point origin (canvas->getScale().origin); g.setOrigin (origin.getX(), origin.getY()); - if (origin.getX() > 0) + g.setColour (canvas->contentAreaColour); + g.fillRect (canvas->getContentArea().getSmallestIntegerContainer()); + +/* if (origin.getX() > 0) { g.setColour (Colour::greyLevel (0.87f)); g.drawVerticalLine (0, -10000.0f, 10000.0f); @@ -736,7 +744,7 @@ public: g.setColour (Colour::greyLevel (0.87f)); g.drawHorizontalLine (0, -10000.0f, 10000.0f); } - +*/ canvas->drawable->draw (g, 1.0f); } @@ -746,6 +754,7 @@ public: }; ScopedPointer drawable; + Colour backgroundColour, contentAreaColour; private: //============================================================================== diff --git a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp index cc9b74d46b..fa4a5ec076 100644 --- a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp +++ b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp @@ -597,6 +597,7 @@ EditorCanvasBase::EditorCanvasBase() : border (8, 8, 14, 14) { //setOpaque (true); + trimCanvasTimer.owner = this; addChildComponent (&spacebarDragOverlay); } @@ -609,7 +610,9 @@ void EditorCanvasBase::initialise() { addAndMakeVisible (componentHolder = createComponentHolder()); addAndMakeVisible (overlay = new OverlayComponent (this)); - overlay->addAndMakeVisible (resizeFrame = new DocumentResizeFrame (this)); + + if (canResizeCanvas()) + overlay->addAndMakeVisible (resizeFrame = new DocumentResizeFrame (this)); handleAsyncUpdate(); } @@ -706,50 +709,79 @@ const Rectangle EditorCanvasBase::getContentArea() const void EditorCanvasBase::handleAsyncUpdate() { documentChanged(); + updateCanvasArea (false, false); - const Rectangle canvasBounds (getCanvasBounds()); + EditorPanelBase* panel = getPanel(); + if (panel != 0) + panel->updateRulers(); // also updates markers + + overlay->update(); +} - const Point newOrigin (jmax (0, -canvasBounds.getX()), jmax (0, -canvasBounds.getY())); - const int newWidth = jmax (canvasBounds.getWidth(), canvasBounds.getRight()) + border.getLeftAndRight(); - const int newHeight = jmax (canvasBounds.getHeight(), canvasBounds.getBottom()) + border.getTopAndBottom(); +void EditorCanvasBase::updateCanvasArea (bool trimIfPossible, bool updateOverlay) +{ + const Rectangle canvasBounds (getCanvasBounds()); - if (scale.origin != newOrigin) + if (lastCanvasBounds != canvasBounds || trimIfPossible) { - repaint(); + lastCanvasBounds = canvasBounds; - const Point oldOrigin (scale.origin); - scale.origin = newOrigin; + if (! canResizeCanvas()) + { + Rectangle bounds (getBounds()); + const Point originInParent (scale.origin + componentHolder->getPosition() + bounds.getPosition()); + bounds = border.addedTo (canvasBounds) + originInParent; + + if (getParentComponent() != 0) + bounds = bounds.getUnion (getParentComponent()->getLocalBounds()); - setBounds (jmin (0, getX() + oldOrigin.getX() - scale.origin.getX()), - jmin (0, getY() + oldOrigin.getY() - scale.origin.getY()), - newWidth, newHeight); + const Point newOrigin (originInParent - bounds.getPosition() - componentHolder->getPosition()); + + if (scale.origin != newOrigin) + { + repaint(); + scale.origin = newOrigin; + } + + if (getBounds() != bounds) + { + setBounds (bounds); - EditorPanelBase* panel = getPanel(); - if (panel != 0) - panel->updateRulers(); + if (updateOverlay) + overlay->update(); + } + } + else if (getWidth() != canvasBounds.getWidth() || getHeight() != canvasBounds.getHeight()) + { + setBounds (canvasBounds); + } } - else if (getWidth() != newWidth || getHeight() != newHeight) +} + +void EditorCanvasBase::TrimCanvasTimer::timerCallback() +{ + if (! isMouseButtonDownAnywhere()) { - setSize (newWidth, newHeight); + stopTimer(); + owner->updateCanvasArea (true, true); } - else - { - overlay->update(); +} - EditorPanelBase* panel = getPanel(); - if (panel != 0) - panel->updateMarkers(); - } +void EditorCanvasBase::moved() +{ + trimCanvasTimer.startTimer (500); } void EditorCanvasBase::resized() { componentHolder->setBounds (getContentArea()); overlay->setBounds (getLocalBounds()); - resizeFrame->setBounds (getLocalBounds()); + + if (resizeFrame != 0) + resizeFrame->setBounds (getLocalBounds()); + spacebarDragOverlay.setBounds (getLocalBounds()); - overlay->update(); - handleUpdateNowIfNeeded(); + trimCanvasTimer.startTimer (500); } //============================================================================== diff --git a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.h b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.h index 1a7b3b728c..567e1ea7de 100644 --- a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.h +++ b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.h @@ -49,6 +49,7 @@ public: //============================================================================== void paint (Graphics& g); void resized(); + void moved(); bool keyStateChanged (bool isKeyDown); bool keyPressed (const KeyPress& key); @@ -79,6 +80,7 @@ public: virtual void documentChanged() = 0; virtual Component* createComponentHolder() = 0; + virtual void fillBackground (Graphics& g) = 0; virtual const Rectangle getCanvasBounds() = 0; virtual void setCanvasBounds (const Rectangle& newBounds) = 0; virtual bool canResizeCanvas() const = 0; @@ -164,6 +166,7 @@ protected: const BorderSize border; Scale scale; ValueTree controlPointEditingTarget; + Rectangle lastCanvasBounds; friend class OverlayItemComponent; class ResizeFrame; @@ -196,7 +199,21 @@ protected: SpacebarDragOverlay spacebarDragOverlay; ScopedPointer dragger; + class TrimCanvasTimer : public Timer + { + public: + TrimCanvasTimer() {} + ~TrimCanvasTimer() {} + + void timerCallback(); + + EditorCanvasBase* owner; + }; + + friend class TrimCanvasTimer; + TrimCanvasTimer trimCanvasTimer; void handleAsyncUpdate(); + void updateCanvasArea (bool trimIfPossible, bool updateOverlay); }; diff --git a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorDragOperation.h b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorDragOperation.h index eac4bbd96a..e91e36c651 100644 --- a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorDragOperation.h +++ b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorDragOperation.h @@ -235,6 +235,8 @@ public: for (int i = 0; i < updateList.size(); ++i) dragItem (updateList.getReference(i), distance, originalPositions.getReference(i)); } + + canvas->handleUpdateNowIfNeeded(); } protected: diff --git a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorPanel.h b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorPanel.h index be960f63de..d74b8edc47 100644 --- a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorPanel.h +++ b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorPanel.h @@ -38,6 +38,7 @@ public: : rulerX (true), rulerY (false), markersVisible (true), snappingEnabled (true), canvas (0) { setOpaque (true); + background = ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, BinaryData::brushed_aluminium_pngSize); addAndMakeVisible (&toolbar); @@ -525,8 +526,8 @@ private: { public: CanvasViewport() + : canvas (0) { - background = ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, BinaryData::brushed_aluminium_pngSize); setOpaque (true); } @@ -536,8 +537,11 @@ private: void paint (Graphics& g) { - g.setTiledImageFill (background, 0, 0, 1.0f); - g.fillAll(); + if (canvas == 0) + canvas = dynamic_cast (getViewedComponent()); + + if (canvas != 0) + canvas->fillBackground (g); } void paintOverChildren (Graphics& g) @@ -554,7 +558,7 @@ private: } private: - Image background; + EditorCanvasBase* canvas; }; //============================================================================== diff --git a/extras/the jucer/src/model/paintelements/jucer_PaintElementPath.cpp b/extras/the jucer/src/model/paintelements/jucer_PaintElementPath.cpp index dca2a4c16e..a17ccd21c7 100644 --- a/extras/the jucer/src/model/paintelements/jucer_PaintElementPath.cpp +++ b/extras/the jucer/src/model/paintelements/jucer_PaintElementPath.cpp @@ -235,7 +235,7 @@ void PaintElementPath::rescalePoint (RelativePositionedRectangle& pos, int dx, i //============================================================================== static void drawArrow (Graphics& g, float x1, float y1, float x2, float y2) { - g.drawArrow (x1, y1, (x1 + x2) * 0.5f, (y1 + y2) * 0.5f, 1.0f, 8.0f, 10.0f); + g.drawArrow (Line (x1, y1, (x1 + x2) * 0.5f, (y1 + y2) * 0.5f), 1.0f, 8.0f, 10.0f); g.drawLine (x1 + (x2 - x1) * 0.49f, y1 + (y2 - y1) * 0.49f, x2, y2); } @@ -1052,7 +1052,7 @@ int PaintElementPath::findSegmentAtXY (int x, int y) const case Path::Iterator::lineTo: positionToXY (p->pos [0], x1, y1, area, layout); - segmentPath.addLineSegment ((float) lastX, (float) lastY, (float) x1, (float) y1, thickness); + segmentPath.addLineSegment (Line ((float) lastX, (float) lastY, (float) x1, (float) y1), thickness); if (segmentPath.contains ((float) x, (float) y)) return i; @@ -1092,7 +1092,7 @@ int PaintElementPath::findSegmentAtXY (int x, int y) const break; case Path::Iterator::closePath: - segmentPath.addLineSegment ((float) lastX, (float) lastY, (float) subPathStartX, (float) subPathStartY, thickness); + segmentPath.addLineSegment (Line ((float) lastX, (float) lastY, (float) subPathStartX, (float) subPathStartY), thickness); if (segmentPath.contains ((float) x, (float) y)) return subpathStartIndex; diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 6da4a33e59..75831d04f6 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -63710,6 +63710,7 @@ void Viewport::updateVisibleArea() horizontalScrollBar.setRangeLimits (0.0, contentBounds.getWidth()); horizontalScrollBar.setCurrentRange (visibleOrigin.getX(), contentArea.getWidth()); horizontalScrollBar.setSingleStepSize (singleStepX); + horizontalScrollBar.cancelPendingUpdate(); } if (vBarVisible) @@ -63718,6 +63719,7 @@ void Viewport::updateVisibleArea() verticalScrollBar.setRangeLimits (0.0, contentBounds.getHeight()); verticalScrollBar.setCurrentRange (visibleOrigin.getY(), contentArea.getHeight()); verticalScrollBar.setSingleStepSize (singleStepY); + verticalScrollBar.cancelPendingUpdate(); } // Force the visibility *after* setting the ranges to avoid flicker caused by edge conditions in the numbers. @@ -63808,20 +63810,46 @@ bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, float wheelIncrem const bool hasVertBar = verticalScrollBar.isVisible(); const bool hasHorzBar = horizontalScrollBar.isVisible(); - if (hasHorzBar && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! hasVertBar)) + if (hasHorzBar || hasVertBar) { - if (wheelIncrementX == 0 && ! hasVertBar) - wheelIncrementX = wheelIncrementY; + if (wheelIncrementX != 0) + { + wheelIncrementX *= 14.0f * singleStepX; + wheelIncrementX = (wheelIncrementX < 0) ? jmin (wheelIncrementX, -1.0f) + : jmax (wheelIncrementX, 1.0f); + } - horizontalScrollBar.mouseWheelMove (e.getEventRelativeTo (&horizontalScrollBar), - wheelIncrementX, wheelIncrementY); - return true; - } - else if (hasVertBar && wheelIncrementY != 0) - { - verticalScrollBar.mouseWheelMove (e.getEventRelativeTo (&verticalScrollBar), - wheelIncrementX, wheelIncrementY); - return true; + if (wheelIncrementY != 0) + { + wheelIncrementY *= 14.0f * singleStepY; + wheelIncrementY = (wheelIncrementY < 0) ? jmin (wheelIncrementY, -1.0f) + : jmax (wheelIncrementY, 1.0f); + } + + Point pos (getViewPosition()); + + if (wheelIncrementX != 0 && wheelIncrementY != 0 && hasHorzBar && hasVertBar) + { + pos.setX (pos.getX() - roundToInt (wheelIncrementX)); + pos.setY (pos.getY() - roundToInt (wheelIncrementY)); + } + else if (hasHorzBar && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! hasVertBar)) + { + if (wheelIncrementX == 0 && ! hasVertBar) + wheelIncrementX = wheelIncrementY; + + pos.setX (pos.getX() - roundToInt (wheelIncrementX)); + } + else if (hasVertBar && wheelIncrementY != 0) + { + pos.setY (pos.getY() - roundToInt (wheelIncrementY)); + } + + if (pos != getViewPosition()) + { + setViewPosition (pos); + return true; + } } } @@ -69297,7 +69325,7 @@ int PopupMenu::showMenu (const Rectangle& target, callback->component = Window::create (*this, ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown(), 0, target, minimumWidth, maximumNumColumns > 0 ? maximumNumColumns : 7, - standardItemHeight, alignToRectangle, 0, + standardItemHeight, alignToRectangle, itemIdThatMustBeVisible, &callback->managerOfChosenCommand, componentAttachedTo); if (callback->component == 0) @@ -76449,10 +76477,35 @@ bool CallOutBox::hitTest (int x, int y) return outline.contains ((float) x, (float) y); } +enum { callOutBoxDismissCommandId = 0x4f83a04b }; + void CallOutBox::inputAttemptWhenModal() { - exitModalState (0); - setVisible (false); + const Point mousePos (getMouseXYRelative() + getBounds().getPosition()); + + if (targetArea.contains (mousePos)) + { + // if you click on the area that originally popped-up the callout, you expect it + // to get rid of the box, but deleting the box here allows the click to pass through and + // probably re-trigger it, so we need to dismiss the box asynchronously to consume the click.. + postCommandMessage (callOutBoxDismissCommandId); + } + else + { + exitModalState (0); + setVisible (false); + } +} + +void CallOutBox::handleCommandMessage (int commandId) +{ + Component::handleCommandMessage (commandId); + + if (commandId == callOutBoxDismissCommandId) + { + exitModalState (0); + setVisible (false); + } } bool CallOutBox::keyPressed (const KeyPress& key) @@ -82541,9 +82594,8 @@ private: void setStartOfLine (float x, float y, const int numPixels) throw() { float x1 = x, y1 = y; - inverseTransform.transformPoint (x1, y1); x += numPixels; - inverseTransform.transformPoint (x, y); + inverseTransform.transformPoints (x1, y1, x, y); xBresenham.set ((int) (x1 * 256.0f), (int) (x * 256.0f), numPixels); yBresenham.set ((int) (y1 * 256.0f), (int) (y * 256.0f), numPixels); @@ -85261,7 +85313,7 @@ BEGIN_JUCE_NAMESPACE DrawablePath::DrawablePath() : mainFill (Colours::black), - strokeFill (Colours::transparentBlack), + strokeFill (Colours::black), strokeType (0.0f), pathNeedsUpdating (true), strokeNeedsUpdating (true) @@ -86659,9 +86711,8 @@ private: capStyle = PathStrokeType::square; float ox = 0.0f, oy = 0.0f; - transform.transformPoint (ox, oy); float x = getCoordLength (strokeWidth, viewBoxW), y = 0.0f; - transform.transformPoint (x, y); + transform.transformPoints (ox, oy, x, y); return PathStrokeType (strokeWidth.isNotEmpty() ? juce_hypotf (x - ox, y - oy) : 1.0f, joinStyle, capStyle); @@ -89412,22 +89463,6 @@ bool AffineTransform::isOnlyTranslation() const throw() && (mat11 == 1.0f); } -void AffineTransform::transformPoint (float& x, - float& y) const throw() -{ - const float oldX = x; - x = mat00 * oldX + mat01 * y + mat02; - y = mat10 * oldX + mat11 * y + mat12; -} - -void AffineTransform::transformPoint (double& x, - double& y) const throw() -{ - const double oldX = x; - x = mat00 * oldX + mat01 * y + mat02; - y = mat10 * oldX + mat11 * y + mat12; -} - END_JUCE_NAMESPACE /*** End of inlined file: juce_AffineTransform.cpp ***/ @@ -90333,8 +90368,7 @@ void Path::addPath (const Path& other, float y2 = other.data.elements [i++]; float x3 = other.data.elements [i++]; float y3 = other.data.elements [i++]; - transformToApply.transformPoint (x2, y2); - transformToApply.transformPoint (x3, y3); + transformToApply.transformPoints (x2, y2, x3, y3); cubicTo (x, y, x2, y2, x3, y3); } @@ -90360,8 +90394,7 @@ void Path::applyTransform (const AffineTransform& transform) throw() if (type == moveMarker) { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); + transform.transformPoint (data.elements [i], data.elements [i + 1]); if (setMaxMin) { @@ -90381,8 +90414,7 @@ void Path::applyTransform (const AffineTransform& transform) throw() } else if (type == lineMarker) { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); + transform.transformPoint (data.elements [i], data.elements [i + 1]); pathXMin = jmin (pathXMin, data.elements [i]); pathXMax = jmax (pathXMax, data.elements [i]); @@ -90393,11 +90425,8 @@ void Path::applyTransform (const AffineTransform& transform) throw() } else if (type == quadMarker) { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); - - transform.transformPoint (data.elements [i + 2], - data.elements [i + 3]); + transform.transformPoints (data.elements [i], data.elements [i + 1], + data.elements [i + 2], data.elements [i + 3]); pathXMin = jmin (pathXMin, data.elements [i], data.elements [i + 2]); pathXMax = jmax (pathXMax, data.elements [i], data.elements [i + 2]); @@ -90408,14 +90437,9 @@ void Path::applyTransform (const AffineTransform& transform) throw() } else if (type == cubicMarker) { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); - - transform.transformPoint (data.elements [i + 2], - data.elements [i + 3]); - - transform.transformPoint (data.elements [i + 4], - data.elements [i + 5]); + transform.transformPoints (data.elements [i], data.elements [i + 1], + data.elements [i + 2], data.elements [i + 3], + data.elements [i + 4], data.elements [i + 5]); pathXMin = jmin (pathXMin, data.elements [i], data.elements [i + 2], data.elements [i + 4]); pathXMax = jmax (pathXMax, data.elements [i], data.elements [i + 2], data.elements [i + 4]); @@ -91115,16 +91139,13 @@ bool PathFlatteningIterator::next() x2 = points [index++]; y2 = points [index++]; - if (! isIdentityTransform) - transform.transformPoint (x2, y2); - if (type == Path::quadMarker) { x3 = points [index++]; y3 = points [index++]; if (! isIdentityTransform) - transform.transformPoint (x3, y3); + transform.transformPoints (x2, y2, x3, y3); } else if (type == Path::cubicMarker) { @@ -91134,10 +91155,12 @@ bool PathFlatteningIterator::next() y4 = points [index++]; if (! isIdentityTransform) - { - transform.transformPoint (x3, y3); - transform.transformPoint (x4, y4); - } + transform.transformPoints (x2, y2, x3, y3, x4, y4); + } + else + { + if (! isIdentityTransform) + transform.transformPoint (x2, y2); } } } @@ -241238,7 +241261,7 @@ void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorT { static const unsigned char dragHandData[] = { 71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0,0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0, - 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39, 132,117,151,116,132,146,248,60,209,138, + 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39,132,117,151,116,132,146,248,60,209,138, 98,22,203,114,34,236,37,52,77,217,247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; dragHandCursor = createMouseCursorFromImage (ImageFileFormat::loadFrom (dragHandData, sizeof (dragHandData)), 8, 7); @@ -241372,13 +241395,6 @@ private: class JuceDataObject : public ComBaseClassHelper { - JuceDropSource* const dropSource; - const FORMATETC* const format; - const STGMEDIUM* const medium; - - JuceDataObject (const JuceDataObject&); - JuceDataObject& operator= (const JuceDataObject&); - public: JuceDataObject (JuceDropSource* const dropSource_, const FORMATETC* const format_, @@ -241460,6 +241476,14 @@ public: HRESULT __stdcall DAdvise (FORMATETC __RPC_FAR*, DWORD, IAdviseSink __RPC_FAR*, DWORD __RPC_FAR*) { return OLE_E_ADVISENOTSUPPORTED; } HRESULT __stdcall DUnadvise (DWORD) { return E_NOTIMPL; } HRESULT __stdcall EnumDAdvise (IEnumSTATDATA __RPC_FAR *__RPC_FAR *) { return OLE_E_ADVISENOTSUPPORTED; } + +private: + JuceDropSource* const dropSource; + const FORMATETC* const format; + const STGMEDIUM* const medium; + + JuceDataObject (const JuceDataObject&); + JuceDataObject& operator= (const JuceDataObject&); }; static HDROP createHDrop (const StringArray& fileNames) throw() @@ -249004,60 +249028,24 @@ static const String getDSErrorMessage (HRESULT hr) switch (hr) { - case MAKE_HRESULT(1, 0x878, 10): - result = "Device already allocated"; - break; - case MAKE_HRESULT(1, 0x878, 30): - result = "Control unavailable"; - break; - case E_INVALIDARG: - result = "Invalid parameter"; - break; - case MAKE_HRESULT(1, 0x878, 50): - result = "Invalid call"; - break; - case E_FAIL: - result = "Generic error"; - break; - case MAKE_HRESULT(1, 0x878, 70): - result = "Priority level error"; - break; - case E_OUTOFMEMORY: - result = "Out of memory"; - break; - case MAKE_HRESULT(1, 0x878, 100): - result = "Bad format"; - break; - case E_NOTIMPL: - result = "Unsupported function"; - break; - case MAKE_HRESULT(1, 0x878, 120): - result = "No driver"; - break; - case MAKE_HRESULT(1, 0x878, 130): - result = "Already initialised"; - break; - case CLASS_E_NOAGGREGATION: - result = "No aggregation"; - break; - case MAKE_HRESULT(1, 0x878, 150): - result = "Buffer lost"; - break; - case MAKE_HRESULT(1, 0x878, 160): - result = "Another app has priority"; - break; - case MAKE_HRESULT(1, 0x878, 170): - result = "Uninitialised"; - break; - case E_NOINTERFACE: - result = "No interface"; - break; - case S_OK: - result = "No error"; - break; - - default: - return "Unknown error: " + String ((int) hr); + case MAKE_HRESULT(1, 0x878, 10): result = "Device already allocated"; break; + case MAKE_HRESULT(1, 0x878, 30): result = "Control unavailable"; break; + case E_INVALIDARG: result = "Invalid parameter"; break; + case MAKE_HRESULT(1, 0x878, 50): result = "Invalid call"; break; + case E_FAIL: result = "Generic error"; break; + case MAKE_HRESULT(1, 0x878, 70): result = "Priority level error"; break; + case E_OUTOFMEMORY: result = "Out of memory"; break; + case MAKE_HRESULT(1, 0x878, 100): result = "Bad format"; break; + case E_NOTIMPL: result = "Unsupported function"; break; + case MAKE_HRESULT(1, 0x878, 120): result = "No driver"; break; + case MAKE_HRESULT(1, 0x878, 130): result = "Already initialised"; break; + case CLASS_E_NOAGGREGATION: result = "No aggregation"; break; + case MAKE_HRESULT(1, 0x878, 150): result = "Buffer lost"; break; + case MAKE_HRESULT(1, 0x878, 160): result = "Another app has priority"; break; + case MAKE_HRESULT(1, 0x878, 170): result = "Uninitialised"; break; + case E_NOINTERFACE: result = "No interface"; break; + case S_OK: result = "No error"; break; + default: return "Unknown error: " + String ((int) hr); } return result; @@ -258647,7 +258635,8 @@ public: GLXContext sharedContext) : renderContext (0), embeddedWindow (0), - pixelFormat (pixelFormat_) + pixelFormat (pixelFormat_), + swapInterval (0) { jassert (component != 0); LinuxComponentPeer* const peer = dynamic_cast (component->getTopLevelComponent()->getPeer()); @@ -258775,14 +258764,21 @@ public: bool setSwapInterval (const int numFramesPerSwap) { - // xxx needs doing.. + static PFNGLXSWAPINTERVALSGIPROC GLXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddress ((const GLubyte*) "glXSwapIntervalSGI"); + + if (GLXSwapIntervalSGI != 0) + { + swapInterval = numFramesPerSwap; + GLXSwapIntervalSGI (numFramesPerSwap); + return true; + } + return false; } int getSwapInterval() const { - // xxx needs doing.. - return 0; + return swapInterval; } void repaint() @@ -258796,6 +258792,7 @@ public: private: Window embeddedWindow; OpenGLPixelFormat pixelFormat; + int swapInterval; WindowedGLContext (const WindowedGLContext&); WindowedGLContext& operator= (const WindowedGLContext&); @@ -264943,14 +264940,11 @@ private: CGContextAddLineToPoint (context, i.x1, flipHeight - i.y1); break; case Path::Iterator::quadraticTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); + transform.transformPoints (i.x1, i.y1, i.x2, i.y2); CGContextAddQuadCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2); break; case Path::Iterator::cubicTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); - transform.transformPoint (i.x3, i.y3); + transform.transformPoints (i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); CGContextAddCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2, i.x3, flipHeight - i.y3); break; case Path::Iterator::closePath: @@ -269590,14 +269584,11 @@ private: CGContextAddLineToPoint (context, i.x1, flipHeight - i.y1); break; case Path::Iterator::quadraticTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); + transform.transformPoints (i.x1, i.y1, i.x2, i.y2); CGContextAddQuadCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2); break; case Path::Iterator::cubicTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); - transform.transformPoint (i.x3, i.y3); + transform.transformPoints (i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); CGContextAddCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2, i.x3, flipHeight - i.y3); break; case Path::Iterator::closePath: @@ -269649,6 +269640,11 @@ class NSViewComponentPeer; END_JUCE_NAMESPACE +@interface NSEvent (JuceDeviceDelta) + - (float) deviceDeltaX; + - (float) deviceDeltaY; +@end + #define JuceNSView MakeObjCClassName(JuceNSView) @interface JuceNSView : NSView @@ -271019,8 +271015,20 @@ void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev) { updateModifiers (ev); - handleMouseWheel (0, getMousePos (ev, view), getMouseTime (ev), - [ev deltaX] * 10.0f, [ev deltaY] * 10.0f); + float x = 0, y = 0; + + @try + { + x = [ev deviceDeltaX] * 0.5f; + y = [ev deviceDeltaY] * 0.5f; + } + @catch (...) + { + x = [ev deltaX] * 10.0f; + y = [ev deltaY] * 10.0f; + } + + handleMouseWheel (0, getMousePos (ev, view), getMouseTime (ev), x, y); } void NSViewComponentPeer::showArrowCursorIfNeeded() diff --git a/juce_amalgamated.h b/juce_amalgamated.h index f1201449e0..7cceb5681e 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 21 +#define JUCE_BUILDNUMBER 22 /** Current Juce version number. @@ -18900,12 +18900,48 @@ public: static const AffineTransform identity; /** Transforms a 2D co-ordinate using this matrix. */ - void transformPoint (float& x, - float& y) const throw(); + template + void transformPoint (ValueType& x, ValueType& y) const throw() + { + const ValueType oldX = x; + x = static_cast (mat00 * oldX + mat01 * y + mat02); + y = static_cast (mat10 * oldX + mat11 * y + mat12); + } - /** Transforms a 2D co-ordinate using this matrix. */ - void transformPoint (double& x, - double& y) const throw(); + /** Transforms two 2D co-ordinates using this matrix. + This is just a shortcut for calling transformPoint() on each of these pairs of + coordinates in turn. (And putting all the calculations into one function hopefully + also gives the compiler a bit more scope for pipelining it). + */ + template + void transformPoints (ValueType& x1, ValueType& y1, + ValueType& x2, ValueType& y2) const throw() + { + const ValueType oldX1 = x1, oldX2 = x2; + x1 = static_cast (mat00 * oldX1 + mat01 * y1 + mat02); + y1 = static_cast (mat10 * oldX1 + mat11 * y1 + mat12); + x2 = static_cast (mat00 * oldX2 + mat01 * y2 + mat02); + y2 = static_cast (mat10 * oldX2 + mat11 * y2 + mat12); + } + + /** Transforms three 2D co-ordinates using this matrix. + This is just a shortcut for calling transformPoint() on each of these pairs of + coordinates in turn. (And putting all the calculations into one function hopefully + also gives the compiler a bit more scope for pipelining it). + */ + template + void transformPoints (ValueType& x1, ValueType& y1, + ValueType& x2, ValueType& y2, + ValueType& x3, ValueType& y3) const throw() + { + const ValueType oldX1 = x1, oldX2 = x2, oldX3 = x3; + x1 = static_cast (mat00 * oldX1 + mat01 * y1 + mat02); + y1 = static_cast (mat10 * oldX1 + mat11 * y1 + mat12); + x2 = static_cast (mat00 * oldX2 + mat01 * y2 + mat02); + y2 = static_cast (mat10 * oldX2 + mat11 * y2 + mat12); + x3 = static_cast (mat00 * oldX3 + mat01 * y3 + mat02); + y3 = static_cast (mat10 * oldX3 + mat11 * y3 + mat12); + } /** Returns a new transform which is the same as this one followed by a translation. */ const AffineTransform translated (float deltaX, @@ -19145,7 +19181,8 @@ public: void applyTransform (const AffineTransform& transform) throw() { transform.transformPoint (x, y); } /** Returns the position of this point, if it is transformed by a given AffineTransform. */ - const Point transformedBy (const AffineTransform& transform) const throw() { ValueType x2 (x), y2 (y); transform.transformPoint (x2, y2); return Point (x2, y2); } + const Point transformedBy (const AffineTransform& transform) const throw() { return Point (transform.mat00 * x + transform.mat01 * y + transform.mat02, + transform.mat10 * x + transform.mat11 * y + transform.mat12); } /** Casts this point to a Point object. */ const Point toFloat() const throw() { return Point (static_cast (x), static_cast (y)); } @@ -20720,10 +20757,8 @@ public: float x3 = x, y3 = y + h; float x4 = x2, y4 = y3; - transform.transformPoint (x1, y1); - transform.transformPoint (x2, y2); - transform.transformPoint (x3, y3); - transform.transformPoint (x4, y4); + transform.transformPoints (x1, y1, x2, y2); + transform.transformPoints (x3, y3, x4, y4); const float rx = jmin (x1, x2, x3, x4); const float ry = jmin (y1, y2, y3, y4); @@ -57394,6 +57429,8 @@ public: void inputAttemptWhenModal(); /** @internal */ bool keyPressed (const KeyPress& key); + /** @internal */ + void handleCommandMessage (int commandId); juce_UseDebuggingNewOperator diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 1a1eaccfb1..d236de2a92 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 21 +#define JUCE_BUILDNUMBER 22 /** Current Juce version number. diff --git a/src/gui/components/layout/juce_Viewport.cpp b/src/gui/components/layout/juce_Viewport.cpp index 533a5abdbe..17ef2844dc 100644 --- a/src/gui/components/layout/juce_Viewport.cpp +++ b/src/gui/components/layout/juce_Viewport.cpp @@ -223,6 +223,7 @@ void Viewport::updateVisibleArea() horizontalScrollBar.setRangeLimits (0.0, contentBounds.getWidth()); horizontalScrollBar.setCurrentRange (visibleOrigin.getX(), contentArea.getWidth()); horizontalScrollBar.setSingleStepSize (singleStepX); + horizontalScrollBar.cancelPendingUpdate(); } if (vBarVisible) @@ -231,6 +232,7 @@ void Viewport::updateVisibleArea() verticalScrollBar.setRangeLimits (0.0, contentBounds.getHeight()); verticalScrollBar.setCurrentRange (visibleOrigin.getY(), contentArea.getHeight()); verticalScrollBar.setSingleStepSize (singleStepY); + verticalScrollBar.cancelPendingUpdate(); } // Force the visibility *after* setting the ranges to avoid flicker caused by edge conditions in the numbers. @@ -322,20 +324,46 @@ bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, float wheelIncrem const bool hasVertBar = verticalScrollBar.isVisible(); const bool hasHorzBar = horizontalScrollBar.isVisible(); - if (hasHorzBar && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! hasVertBar)) + if (hasHorzBar || hasVertBar) { - if (wheelIncrementX == 0 && ! hasVertBar) - wheelIncrementX = wheelIncrementY; - - horizontalScrollBar.mouseWheelMove (e.getEventRelativeTo (&horizontalScrollBar), - wheelIncrementX, wheelIncrementY); - return true; - } - else if (hasVertBar && wheelIncrementY != 0) - { - verticalScrollBar.mouseWheelMove (e.getEventRelativeTo (&verticalScrollBar), - wheelIncrementX, wheelIncrementY); - return true; + if (wheelIncrementX != 0) + { + wheelIncrementX *= 14.0f * singleStepX; + wheelIncrementX = (wheelIncrementX < 0) ? jmin (wheelIncrementX, -1.0f) + : jmax (wheelIncrementX, 1.0f); + } + + if (wheelIncrementY != 0) + { + wheelIncrementY *= 14.0f * singleStepY; + wheelIncrementY = (wheelIncrementY < 0) ? jmin (wheelIncrementY, -1.0f) + : jmax (wheelIncrementY, 1.0f); + } + + Point pos (getViewPosition()); + + if (wheelIncrementX != 0 && wheelIncrementY != 0 && hasHorzBar && hasVertBar) + { + pos.setX (pos.getX() - roundToInt (wheelIncrementX)); + pos.setY (pos.getY() - roundToInt (wheelIncrementY)); + } + else if (hasHorzBar && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! hasVertBar)) + { + if (wheelIncrementX == 0 && ! hasVertBar) + wheelIncrementX = wheelIncrementY; + + pos.setX (pos.getX() - roundToInt (wheelIncrementX)); + } + else if (hasVertBar && wheelIncrementY != 0) + { + pos.setY (pos.getY() - roundToInt (wheelIncrementY)); + } + + if (pos != getViewPosition()) + { + setViewPosition (pos); + return true; + } } } diff --git a/src/gui/components/menus/juce_PopupMenu.cpp b/src/gui/components/menus/juce_PopupMenu.cpp index 1c01554446..4b5d03004e 100644 --- a/src/gui/components/menus/juce_PopupMenu.cpp +++ b/src/gui/components/menus/juce_PopupMenu.cpp @@ -1533,7 +1533,7 @@ int PopupMenu::showMenu (const Rectangle& target, callback->component = Window::create (*this, ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown(), 0, target, minimumWidth, maximumNumColumns > 0 ? maximumNumColumns : 7, - standardItemHeight, alignToRectangle, 0, + standardItemHeight, alignToRectangle, itemIdThatMustBeVisible, &callback->managerOfChosenCommand, componentAttachedTo); if (callback->component == 0) diff --git a/src/gui/components/windows/juce_CallOutBox.cpp b/src/gui/components/windows/juce_CallOutBox.cpp index edd81ac92d..0342f71da2 100644 --- a/src/gui/components/windows/juce_CallOutBox.cpp +++ b/src/gui/components/windows/juce_CallOutBox.cpp @@ -103,10 +103,35 @@ bool CallOutBox::hitTest (int x, int y) return outline.contains ((float) x, (float) y); } +enum { callOutBoxDismissCommandId = 0x4f83a04b }; + void CallOutBox::inputAttemptWhenModal() { - exitModalState (0); - setVisible (false); + const Point mousePos (getMouseXYRelative() + getBounds().getPosition()); + + if (targetArea.contains (mousePos)) + { + // if you click on the area that originally popped-up the callout, you expect it + // to get rid of the box, but deleting the box here allows the click to pass through and + // probably re-trigger it, so we need to dismiss the box asynchronously to consume the click.. + postCommandMessage (callOutBoxDismissCommandId); + } + else + { + exitModalState (0); + setVisible (false); + } +} + +void CallOutBox::handleCommandMessage (int commandId) +{ + Component::handleCommandMessage (commandId); + + if (commandId == callOutBoxDismissCommandId) + { + exitModalState (0); + setVisible (false); + } } bool CallOutBox::keyPressed (const KeyPress& key) diff --git a/src/gui/components/windows/juce_CallOutBox.h b/src/gui/components/windows/juce_CallOutBox.h index 718eebd841..cd99f8e7a9 100644 --- a/src/gui/components/windows/juce_CallOutBox.h +++ b/src/gui/components/windows/juce_CallOutBox.h @@ -105,6 +105,8 @@ public: void inputAttemptWhenModal(); /** @internal */ bool keyPressed (const KeyPress& key); + /** @internal */ + void handleCommandMessage (int commandId); juce_UseDebuggingNewOperator diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp index 8b32b4855d..77c9c2af40 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp @@ -889,9 +889,8 @@ private: void setStartOfLine (float x, float y, const int numPixels) throw() { float x1 = x, y1 = y; - inverseTransform.transformPoint (x1, y1); x += numPixels; - inverseTransform.transformPoint (x, y); + inverseTransform.transformPoints (x1, y1, x, y); xBresenham.set ((int) (x1 * 256.0f), (int) (x * 256.0f), numPixels); yBresenham.set ((int) (y1 * 256.0f), (int) (y * 256.0f), numPixels); diff --git a/src/gui/graphics/drawables/juce_DrawablePath.cpp b/src/gui/graphics/drawables/juce_DrawablePath.cpp index 481ee649d1..82fdf03947 100644 --- a/src/gui/graphics/drawables/juce_DrawablePath.cpp +++ b/src/gui/graphics/drawables/juce_DrawablePath.cpp @@ -35,7 +35,7 @@ BEGIN_JUCE_NAMESPACE //============================================================================== DrawablePath::DrawablePath() : mainFill (Colours::black), - strokeFill (Colours::transparentBlack), + strokeFill (Colours::black), strokeType (0.0f), pathNeedsUpdating (true), strokeNeedsUpdating (true) diff --git a/src/gui/graphics/drawables/juce_SVGParser.cpp b/src/gui/graphics/drawables/juce_SVGParser.cpp index c7dc1bbf8b..bf481dc7f6 100644 --- a/src/gui/graphics/drawables/juce_SVGParser.cpp +++ b/src/gui/graphics/drawables/juce_SVGParser.cpp @@ -801,9 +801,8 @@ private: capStyle = PathStrokeType::square; float ox = 0.0f, oy = 0.0f; - transform.transformPoint (ox, oy); float x = getCoordLength (strokeWidth, viewBoxW), y = 0.0f; - transform.transformPoint (x, y); + transform.transformPoints (ox, oy, x, y); return PathStrokeType (strokeWidth.isNotEmpty() ? juce_hypotf (x - ox, y - oy) : 1.0f, joinStyle, capStyle); diff --git a/src/gui/graphics/geometry/juce_AffineTransform.cpp b/src/gui/graphics/geometry/juce_AffineTransform.cpp index d6cf64398f..02eb57c281 100644 --- a/src/gui/graphics/geometry/juce_AffineTransform.cpp +++ b/src/gui/graphics/geometry/juce_AffineTransform.cpp @@ -257,22 +257,5 @@ bool AffineTransform::isOnlyTranslation() const throw() && (mat11 == 1.0f); } -//============================================================================== -void AffineTransform::transformPoint (float& x, - float& y) const throw() -{ - const float oldX = x; - x = mat00 * oldX + mat01 * y + mat02; - y = mat10 * oldX + mat11 * y + mat12; -} - -void AffineTransform::transformPoint (double& x, - double& y) const throw() -{ - const double oldX = x; - x = mat00 * oldX + mat01 * y + mat02; - y = mat10 * oldX + mat11 * y + mat12; -} - END_JUCE_NAMESPACE diff --git a/src/gui/graphics/geometry/juce_AffineTransform.h b/src/gui/graphics/geometry/juce_AffineTransform.h index 65147acbb4..702beaf180 100644 --- a/src/gui/graphics/geometry/juce_AffineTransform.h +++ b/src/gui/graphics/geometry/juce_AffineTransform.h @@ -81,12 +81,48 @@ public: //============================================================================== /** Transforms a 2D co-ordinate using this matrix. */ - void transformPoint (float& x, - float& y) const throw(); - - /** Transforms a 2D co-ordinate using this matrix. */ - void transformPoint (double& x, - double& y) const throw(); + template + void transformPoint (ValueType& x, ValueType& y) const throw() + { + const ValueType oldX = x; + x = static_cast (mat00 * oldX + mat01 * y + mat02); + y = static_cast (mat10 * oldX + mat11 * y + mat12); + } + + /** Transforms two 2D co-ordinates using this matrix. + This is just a shortcut for calling transformPoint() on each of these pairs of + coordinates in turn. (And putting all the calculations into one function hopefully + also gives the compiler a bit more scope for pipelining it). + */ + template + void transformPoints (ValueType& x1, ValueType& y1, + ValueType& x2, ValueType& y2) const throw() + { + const ValueType oldX1 = x1, oldX2 = x2; + x1 = static_cast (mat00 * oldX1 + mat01 * y1 + mat02); + y1 = static_cast (mat10 * oldX1 + mat11 * y1 + mat12); + x2 = static_cast (mat00 * oldX2 + mat01 * y2 + mat02); + y2 = static_cast (mat10 * oldX2 + mat11 * y2 + mat12); + } + + /** Transforms three 2D co-ordinates using this matrix. + This is just a shortcut for calling transformPoint() on each of these pairs of + coordinates in turn. (And putting all the calculations into one function hopefully + also gives the compiler a bit more scope for pipelining it). + */ + template + void transformPoints (ValueType& x1, ValueType& y1, + ValueType& x2, ValueType& y2, + ValueType& x3, ValueType& y3) const throw() + { + const ValueType oldX1 = x1, oldX2 = x2, oldX3 = x3; + x1 = static_cast (mat00 * oldX1 + mat01 * y1 + mat02); + y1 = static_cast (mat10 * oldX1 + mat11 * y1 + mat12); + x2 = static_cast (mat00 * oldX2 + mat01 * y2 + mat02); + y2 = static_cast (mat10 * oldX2 + mat11 * y2 + mat12); + x3 = static_cast (mat00 * oldX3 + mat01 * y3 + mat02); + y3 = static_cast (mat10 * oldX3 + mat11 * y3 + mat12); + } //============================================================================== /** Returns a new transform which is the same as this one followed by a translation. */ diff --git a/src/gui/graphics/geometry/juce_Path.cpp b/src/gui/graphics/geometry/juce_Path.cpp index 85b45112c6..7dba9b6ddb 100644 --- a/src/gui/graphics/geometry/juce_Path.cpp +++ b/src/gui/graphics/geometry/juce_Path.cpp @@ -829,8 +829,7 @@ void Path::addPath (const Path& other, float y2 = other.data.elements [i++]; float x3 = other.data.elements [i++]; float y3 = other.data.elements [i++]; - transformToApply.transformPoint (x2, y2); - transformToApply.transformPoint (x3, y3); + transformToApply.transformPoints (x2, y2, x3, y3); cubicTo (x, y, x2, y2, x3, y3); } @@ -857,8 +856,7 @@ void Path::applyTransform (const AffineTransform& transform) throw() if (type == moveMarker) { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); + transform.transformPoint (data.elements [i], data.elements [i + 1]); if (setMaxMin) { @@ -878,8 +876,7 @@ void Path::applyTransform (const AffineTransform& transform) throw() } else if (type == lineMarker) { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); + transform.transformPoint (data.elements [i], data.elements [i + 1]); pathXMin = jmin (pathXMin, data.elements [i]); pathXMax = jmax (pathXMax, data.elements [i]); @@ -890,11 +887,8 @@ void Path::applyTransform (const AffineTransform& transform) throw() } else if (type == quadMarker) { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); - - transform.transformPoint (data.elements [i + 2], - data.elements [i + 3]); + transform.transformPoints (data.elements [i], data.elements [i + 1], + data.elements [i + 2], data.elements [i + 3]); pathXMin = jmin (pathXMin, data.elements [i], data.elements [i + 2]); pathXMax = jmax (pathXMax, data.elements [i], data.elements [i + 2]); @@ -905,14 +899,9 @@ void Path::applyTransform (const AffineTransform& transform) throw() } else if (type == cubicMarker) { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); - - transform.transformPoint (data.elements [i + 2], - data.elements [i + 3]); - - transform.transformPoint (data.elements [i + 4], - data.elements [i + 5]); + transform.transformPoints (data.elements [i], data.elements [i + 1], + data.elements [i + 2], data.elements [i + 3], + data.elements [i + 4], data.elements [i + 5]); pathXMin = jmin (pathXMin, data.elements [i], data.elements [i + 2], data.elements [i + 4]); pathXMax = jmax (pathXMax, data.elements [i], data.elements [i + 2], data.elements [i + 4]); diff --git a/src/gui/graphics/geometry/juce_PathIterator.cpp b/src/gui/graphics/geometry/juce_PathIterator.cpp index a276c25d52..e7d2a7456b 100644 --- a/src/gui/graphics/geometry/juce_PathIterator.cpp +++ b/src/gui/graphics/geometry/juce_PathIterator.cpp @@ -87,16 +87,13 @@ bool PathFlatteningIterator::next() x2 = points [index++]; y2 = points [index++]; - if (! isIdentityTransform) - transform.transformPoint (x2, y2); - if (type == Path::quadMarker) { x3 = points [index++]; y3 = points [index++]; if (! isIdentityTransform) - transform.transformPoint (x3, y3); + transform.transformPoints (x2, y2, x3, y3); } else if (type == Path::cubicMarker) { @@ -106,10 +103,12 @@ bool PathFlatteningIterator::next() y4 = points [index++]; if (! isIdentityTransform) - { - transform.transformPoint (x3, y3); - transform.transformPoint (x4, y4); - } + transform.transformPoints (x2, y2, x3, y3, x4, y4); + } + else + { + if (! isIdentityTransform) + transform.transformPoint (x2, y2); } } } diff --git a/src/gui/graphics/geometry/juce_Point.h b/src/gui/graphics/geometry/juce_Point.h index b8654dd17c..91af8e34be 100644 --- a/src/gui/graphics/geometry/juce_Point.h +++ b/src/gui/graphics/geometry/juce_Point.h @@ -153,7 +153,8 @@ public: void applyTransform (const AffineTransform& transform) throw() { transform.transformPoint (x, y); } /** Returns the position of this point, if it is transformed by a given AffineTransform. */ - const Point transformedBy (const AffineTransform& transform) const throw() { ValueType x2 (x), y2 (y); transform.transformPoint (x2, y2); return Point (x2, y2); } + const Point transformedBy (const AffineTransform& transform) const throw() { return Point (transform.mat00 * x + transform.mat01 * y + transform.mat02, + transform.mat10 * x + transform.mat11 * y + transform.mat12); } /** Casts this point to a Point object. */ const Point toFloat() const throw() { return Point (static_cast (x), static_cast (y)); } diff --git a/src/gui/graphics/geometry/juce_Rectangle.h b/src/gui/graphics/geometry/juce_Rectangle.h index 5882d59b8c..ffcee6934d 100644 --- a/src/gui/graphics/geometry/juce_Rectangle.h +++ b/src/gui/graphics/geometry/juce_Rectangle.h @@ -494,10 +494,8 @@ public: float x3 = x, y3 = y + h; float x4 = x2, y4 = y3; - transform.transformPoint (x1, y1); - transform.transformPoint (x2, y2); - transform.transformPoint (x3, y3); - transform.transformPoint (x4, y4); + transform.transformPoints (x1, y1, x2, y2); + transform.transformPoints (x3, y3, x4, y4); const float rx = jmin (x1, x2, x3, x4); const float ry = jmin (y1, y2, y3, y4); diff --git a/src/native/linux/juce_linux_Windowing.cpp b/src/native/linux/juce_linux_Windowing.cpp index 2d5bb9bd16..92c68f47a2 100644 --- a/src/native/linux/juce_linux_Windowing.cpp +++ b/src/native/linux/juce_linux_Windowing.cpp @@ -3160,7 +3160,8 @@ public: GLXContext sharedContext) : renderContext (0), embeddedWindow (0), - pixelFormat (pixelFormat_) + pixelFormat (pixelFormat_), + swapInterval (0) { jassert (component != 0); LinuxComponentPeer* const peer = dynamic_cast (component->getTopLevelComponent()->getPeer()); @@ -3288,14 +3289,21 @@ public: bool setSwapInterval (const int numFramesPerSwap) { - // xxx needs doing.. + static PFNGLXSWAPINTERVALSGIPROC GLXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddress ((const GLubyte*) "glXSwapIntervalSGI"); + + if (GLXSwapIntervalSGI != 0) + { + swapInterval = numFramesPerSwap; + GLXSwapIntervalSGI (numFramesPerSwap); + return true; + } + return false; } int getSwapInterval() const { - // xxx needs doing.. - return 0; + return swapInterval; } void repaint() @@ -3310,6 +3318,7 @@ public: private: Window embeddedWindow; OpenGLPixelFormat pixelFormat; + int swapInterval; //============================================================================== WindowedGLContext (const WindowedGLContext&); diff --git a/src/native/mac/juce_mac_CoreGraphicsContext.mm b/src/native/mac/juce_mac_CoreGraphicsContext.mm index c470fa40e9..6afeb45f79 100644 --- a/src/native/mac/juce_mac_CoreGraphicsContext.mm +++ b/src/native/mac/juce_mac_CoreGraphicsContext.mm @@ -717,14 +717,11 @@ private: CGContextAddLineToPoint (context, i.x1, flipHeight - i.y1); break; case Path::Iterator::quadraticTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); + transform.transformPoints (i.x1, i.y1, i.x2, i.y2); CGContextAddQuadCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2); break; case Path::Iterator::cubicTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); - transform.transformPoint (i.x3, i.y3); + transform.transformPoints (i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); CGContextAddCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2, i.x3, flipHeight - i.y3); break; case Path::Iterator::closePath: diff --git a/src/native/mac/juce_mac_NSViewComponentPeer.mm b/src/native/mac/juce_mac_NSViewComponentPeer.mm index 49ed93a214..01cea59f1b 100644 --- a/src/native/mac/juce_mac_NSViewComponentPeer.mm +++ b/src/native/mac/juce_mac_NSViewComponentPeer.mm @@ -32,6 +32,11 @@ class NSViewComponentPeer; //============================================================================== END_JUCE_NAMESPACE +@interface NSEvent (JuceDeviceDelta) + - (float) deviceDeltaX; + - (float) deviceDeltaY; +@end + #define JuceNSView MakeObjCClassName(JuceNSView) @interface JuceNSView : NSView @@ -1424,8 +1429,20 @@ void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev) { updateModifiers (ev); - handleMouseWheel (0, getMousePos (ev, view), getMouseTime (ev), - [ev deltaX] * 10.0f, [ev deltaY] * 10.0f); + float x = 0, y = 0; + + @try + { + x = [ev deviceDeltaX] * 0.5f; + y = [ev deviceDeltaY] * 0.5f; + } + @catch (...) + { + x = [ev deltaX] * 10.0f; + y = [ev deltaY] * 10.0f; + } + + handleMouseWheel (0, getMousePos (ev, view), getMouseTime (ev), x, y); } void NSViewComponentPeer::showArrowCursorIfNeeded() diff --git a/src/native/windows/juce_win32_DirectSound.cpp b/src/native/windows/juce_win32_DirectSound.cpp index 727740df3a..8872efdd46 100644 --- a/src/native/windows/juce_win32_DirectSound.cpp +++ b/src/native/windows/juce_win32_DirectSound.cpp @@ -143,60 +143,24 @@ static const String getDSErrorMessage (HRESULT hr) switch (hr) { - case MAKE_HRESULT(1, 0x878, 10): - result = "Device already allocated"; - break; - case MAKE_HRESULT(1, 0x878, 30): - result = "Control unavailable"; - break; - case E_INVALIDARG: - result = "Invalid parameter"; - break; - case MAKE_HRESULT(1, 0x878, 50): - result = "Invalid call"; - break; - case E_FAIL: - result = "Generic error"; - break; - case MAKE_HRESULT(1, 0x878, 70): - result = "Priority level error"; - break; - case E_OUTOFMEMORY: - result = "Out of memory"; - break; - case MAKE_HRESULT(1, 0x878, 100): - result = "Bad format"; - break; - case E_NOTIMPL: - result = "Unsupported function"; - break; - case MAKE_HRESULT(1, 0x878, 120): - result = "No driver"; - break; - case MAKE_HRESULT(1, 0x878, 130): - result = "Already initialised"; - break; - case CLASS_E_NOAGGREGATION: - result = "No aggregation"; - break; - case MAKE_HRESULT(1, 0x878, 150): - result = "Buffer lost"; - break; - case MAKE_HRESULT(1, 0x878, 160): - result = "Another app has priority"; - break; - case MAKE_HRESULT(1, 0x878, 170): - result = "Uninitialised"; - break; - case E_NOINTERFACE: - result = "No interface"; - break; - case S_OK: - result = "No error"; - break; - - default: - return "Unknown error: " + String ((int) hr); + case MAKE_HRESULT(1, 0x878, 10): result = "Device already allocated"; break; + case MAKE_HRESULT(1, 0x878, 30): result = "Control unavailable"; break; + case E_INVALIDARG: result = "Invalid parameter"; break; + case MAKE_HRESULT(1, 0x878, 50): result = "Invalid call"; break; + case E_FAIL: result = "Generic error"; break; + case MAKE_HRESULT(1, 0x878, 70): result = "Priority level error"; break; + case E_OUTOFMEMORY: result = "Out of memory"; break; + case MAKE_HRESULT(1, 0x878, 100): result = "Bad format"; break; + case E_NOTIMPL: result = "Unsupported function"; break; + case MAKE_HRESULT(1, 0x878, 120): result = "No driver"; break; + case MAKE_HRESULT(1, 0x878, 130): result = "Already initialised"; break; + case CLASS_E_NOAGGREGATION: result = "No aggregation"; break; + case MAKE_HRESULT(1, 0x878, 150): result = "Buffer lost"; break; + case MAKE_HRESULT(1, 0x878, 160): result = "Another app has priority"; break; + case MAKE_HRESULT(1, 0x878, 170): result = "Uninitialised"; break; + case E_NOINTERFACE: result = "No interface"; break; + case S_OK: result = "No error"; break; + default: return "Unknown error: " + String ((int) hr); } return result; diff --git a/src/native/windows/juce_win32_Windowing.cpp b/src/native/windows/juce_win32_Windowing.cpp index e840802df7..bc1900c917 100644 --- a/src/native/windows/juce_win32_Windowing.cpp +++ b/src/native/windows/juce_win32_Windowing.cpp @@ -2513,7 +2513,7 @@ void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorT { static const unsigned char dragHandData[] = { 71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0,0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0, - 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39, 132,117,151,116,132,146,248,60,209,138, + 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39,132,117,151,116,132,146,248,60,209,138, 98,22,203,114,34,236,37,52,77,217,247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; dragHandCursor = createMouseCursorFromImage (ImageFileFormat::loadFrom (dragHandData, sizeof (dragHandData)), 8, 7); @@ -2651,13 +2651,6 @@ private: class JuceDataObject : public ComBaseClassHelper { - JuceDropSource* const dropSource; - const FORMATETC* const format; - const STGMEDIUM* const medium; - - JuceDataObject (const JuceDataObject&); - JuceDataObject& operator= (const JuceDataObject&); - public: JuceDataObject (JuceDropSource* const dropSource_, const FORMATETC* const format_, @@ -2739,6 +2732,14 @@ public: HRESULT __stdcall DAdvise (FORMATETC __RPC_FAR*, DWORD, IAdviseSink __RPC_FAR*, DWORD __RPC_FAR*) { return OLE_E_ADVISENOTSUPPORTED; } HRESULT __stdcall DUnadvise (DWORD) { return E_NOTIMPL; } HRESULT __stdcall EnumDAdvise (IEnumSTATDATA __RPC_FAR *__RPC_FAR *) { return OLE_E_ADVISENOTSUPPORTED; } + +private: + JuceDropSource* const dropSource; + const FORMATETC* const format; + const STGMEDIUM* const medium; + + JuceDataObject (const JuceDataObject&); + JuceDataObject& operator= (const JuceDataObject&); }; static HDROP createHDrop (const StringArray& fileNames) throw()