From b80bb4bf38d557a8b6696be63c2ac7cc09e49fc5 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Mon, 18 Oct 2010 16:04:32 +0100 Subject: [PATCH] Small change to method in RectanglePlacement and Drawable to use Rectangles instead of bare coordinates. Fix to make ValueTree::sort use an UndoManager, and to prevent different mouse buttons being interpreted as a double-click. --- .../Source/Project/jucer_Project.cpp | 2 +- src/containers/juce_ElementComparator.h | 21 +++--------- src/containers/juce_ValueTree.cpp | 22 +++++++++++++ src/containers/juce_ValueTree.h | 20 +++++------ src/core/juce_StandardHeader.h | 2 +- src/events/juce_CallbackMessage.h | 3 ++ .../buttons/juce_DrawableButton.cpp | 12 +------ .../components/buttons/juce_ToolbarButton.cpp | 6 ++-- .../mouse/juce_MouseInputSource.cpp | 23 ++++++++----- .../contexts/juce_RectanglePlacement.cpp | 33 +++++++++---------- .../contexts/juce_RectanglePlacement.h | 11 ++----- src/gui/graphics/drawables/juce_Drawable.h | 10 ++---- src/gui/graphics/drawables/juce_SVGParser.cpp | 4 +-- src/native/mac/juce_mac_AudioCDBurner.mm | 15 +++------ src/native/mac/juce_mac_Files.mm | 2 +- 15 files changed, 90 insertions(+), 96 deletions(-) diff --git a/extras/Jucer (experimental)/Source/Project/jucer_Project.cpp b/extras/Jucer (experimental)/Source/Project/jucer_Project.cpp index 109bf84159..b39f69e8e0 100644 --- a/extras/Jucer (experimental)/Source/Project/jucer_Project.cpp +++ b/extras/Jucer (experimental)/Source/Project/jucer_Project.cpp @@ -697,7 +697,7 @@ struct ItemSorter void Project::Item::sortAlphabetically() { ItemSorter sorter; - node.sort (sorter); + node.sort (sorter, getUndoManager(), true); } bool Project::Item::addFile (const File& file, int insertIndex) diff --git a/src/containers/juce_ElementComparator.h b/src/containers/juce_ElementComparator.h index 8e28417c81..65f6bd7e47 100644 --- a/src/containers/juce_ElementComparator.h +++ b/src/containers/juce_ElementComparator.h @@ -73,9 +73,7 @@ static void sortArray (ElementComparator& comparator, { if (comparator.compareElements (array[i], array [i + 1]) > 0) { - const ElementType temp = array [i]; - array [i] = array[i + 1]; - array [i + 1] = temp; + swapVariables (array[i], array[i + 1]); if (i > firstElement) i -= 2; @@ -103,19 +101,14 @@ static void sortArray (ElementComparator& comparator, if (comparator.compareElements (array[k], array [maxIndex]) > 0) maxIndex = k; - const ElementType temp = array [maxIndex]; - array [maxIndex] = array[j]; - array [j] = temp; - + swapVariables (array[j], array[maxIndex]); --j; } } else { const int mid = firstElement + (size >> 1); - ElementType temp = array [mid]; - array [mid] = array [firstElement]; - array [firstElement] = temp; + swapVariables (array[mid], array[firstElement]); int i = firstElement; int j = lastElement + 1; @@ -133,14 +126,10 @@ static void sortArray (ElementComparator& comparator, if (j < i) break; - temp = array[i]; - array[i] = array[j]; - array[j] = temp; + swapVariables (array[i], array[j]); } - temp = array [firstElement]; - array [firstElement] = array[j]; - array [j] = temp; + swapVariables (array[j], array[firstElement]); if (j - 1 - firstElement >= lastElement - i) { diff --git a/src/containers/juce_ValueTree.cpp b/src/containers/juce_ValueTree.cpp index 94110e9513..6607b7b9f6 100644 --- a/src/containers/juce_ValueTree.cpp +++ b/src/containers/juce_ValueTree.cpp @@ -512,6 +512,28 @@ void ValueTree::SharedObject::moveChild (int currentIndex, int newIndex, UndoMan } } +void ValueTree::SharedObject::reorderChildren (const ReferenceCountedArray & newOrder, UndoManager* undoManager) +{ + jassert (newOrder.size() == children.size()); + + if (undoManager == 0) + { + children = newOrder; + sendChildChangeMessage(); + } + else + { + for (int i = 0; i < children.size(); ++i) + { + if (children.getUnchecked(i) != newOrder.getUnchecked(i)) + { + jassert (children.contains (newOrder.getUnchecked(i))); + moveChild (children.indexOf (newOrder.getUnchecked(i)), i, undoManager); + } + } + } +} + bool ValueTree::SharedObject::isEquivalentTo (const SharedObject& other) const { if (type != other.type diff --git a/src/containers/juce_ValueTree.h b/src/containers/juce_ValueTree.h index 0a4900cd77..743d0cc50f 100644 --- a/src/containers/juce_ValueTree.h +++ b/src/containers/juce_ValueTree.h @@ -423,22 +423,21 @@ public: To improve performance, the compareElements() method can be declared as static or const. @param comparator the comparator to use for comparing elements. - @param retainOrderOfEquivalentItems if this is true, then items - which the comparator says are equivalent will be - kept in the order in which they currently appear - in the array. This is slower to perform, but may - be important in some cases. If it's false, a faster - algorithm is used, but equivalent elements may be - rearranged. + @param undoManager optional UndoManager for storing the changes + @param retainOrderOfEquivalentItems if this is true, then items which the comparator says are + equivalent will be kept in the order in which they currently appear in the array. + This is slower to perform, but may be important in some cases. If it's false, a + faster algorithm is used, but equivalent elements may be rearranged. */ template - void sort (ElementComparator& comparator, const bool retainOrderOfEquivalentItems = false) + void sort (ElementComparator& comparator, UndoManager* undoManager, bool retainOrderOfEquivalentItems) { if (object != 0) { + ReferenceCountedArray sortedList (object->children); ComparatorAdapter adapter (comparator); - object->children.sort (adapter, retainOrderOfEquivalentItems); - object->sendChildChangeMessage(); + sortedList.sort (adapter, retainOrderOfEquivalentItems); + object->reorderChildren (sortedList, undoManager); } } @@ -491,6 +490,7 @@ private: void removeChild (int childIndex, UndoManager*); void removeAllChildren (UndoManager*); void moveChild (int currentIndex, int newIndex, UndoManager*); + void reorderChildren (const ReferenceCountedArray & newOrder, UndoManager*); bool isEquivalentTo (const SharedObject& other) const; XmlElement* createXml() const; diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index b8942f2dd7..062762f8b3 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 77 +#define JUCE_BUILDNUMBER 78 /** Current Juce version number. diff --git a/src/events/juce_CallbackMessage.h b/src/events/juce_CallbackMessage.h index 7155e6f0f1..f0af431945 100644 --- a/src/events/juce_CallbackMessage.h +++ b/src/events/juce_CallbackMessage.h @@ -39,6 +39,9 @@ just call the post() method to send them, and when they arrive, your messageCallback() method will automatically be invoked. + Always create an instance of a CallbackMessage on the heap, as it will be + deleted automatically after the message has been delivered. + @see MessageListener, MessageManager, ActionListener, ChangeListener */ class JUCE_API CallbackMessage : public Message diff --git a/src/gui/components/buttons/juce_DrawableButton.cpp b/src/gui/components/buttons/juce_DrawableButton.cpp index ab157803cb..00835db3fc 100644 --- a/src/gui/components/buttons/juce_DrawableButton.cpp +++ b/src/gui/components/buttons/juce_DrawableButton.cpp @@ -207,19 +207,9 @@ void DrawableButton::paintButton (Graphics& g, if (imageToDraw != 0) { if (style == ImageRaw) - { imageToDraw->draw (g, 1.0f); - } else - { - imageToDraw->drawWithin (g, - imageSpace.getX(), - imageSpace.getY(), - imageSpace.getWidth(), - imageSpace.getHeight(), - RectanglePlacement::centred, - 1.0f); - } + imageToDraw->drawWithin (g, imageSpace.toFloat(), RectanglePlacement::centred, 1.0f); } } diff --git a/src/gui/components/buttons/juce_ToolbarButton.cpp b/src/gui/components/buttons/juce_ToolbarButton.cpp index 576e821d9e..df719490da 100644 --- a/src/gui/components/buttons/juce_ToolbarButton.cpp +++ b/src/gui/components/buttons/juce_ToolbarButton.cpp @@ -69,13 +69,15 @@ void ToolbarButton::paintButtonArea (Graphics& g, if (getToggleState() && toggledOnImage != 0) d = toggledOnImage; + const Rectangle area (0.0f, 0.0f, (float) width, (float) height); + if (! isEnabled()) { Image im (Image::ARGB, width, height, true); { Graphics g2 (im); - d->drawWithin (g2, 0, 0, width, height, RectanglePlacement::centred, 1.0f); + d->drawWithin (g2, area, RectanglePlacement::centred, 1.0f); } im.desaturate(); @@ -83,7 +85,7 @@ void ToolbarButton::paintButtonArea (Graphics& g, } else { - d->drawWithin (g, 0, 0, width, height, RectanglePlacement::centred, 1.0f); + d->drawWithin (g, area, RectanglePlacement::centred, 1.0f); } } diff --git a/src/gui/components/mouse/juce_MouseInputSource.cpp b/src/gui/components/mouse/juce_MouseInputSource.cpp index ff06dcae40..06bb3bab0f 100644 --- a/src/gui/components/mouse/juce_MouseInputSource.cpp +++ b/src/gui/components/mouse/juce_MouseInputSource.cpp @@ -179,7 +179,7 @@ public: if (current != 0) { - registerMouseDown (screenPos, time, current); + registerMouseDown (screenPos, time, current, buttonState); sendMouseDown (current, screenPos, time); } } @@ -328,16 +328,10 @@ public: for (int i = 1; i < numElementsInArray (mouseDowns); ++i) { - if (mouseDowns[0].time - mouseDowns[i].time < (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1))) - && abs (mouseDowns[0].position.getX() - mouseDowns[i].position.getX()) < 8 - && abs (mouseDowns[0].position.getY() - mouseDowns[i].position.getY()) < 8) - { + if (mouseDowns[0].canBePartOfMultipleClickWith (mouseDowns[1], (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1))))) ++numClicks; - } else - { break; - } } } @@ -457,13 +451,23 @@ private: Point position; int64 time; Component* component; + ModifierKeys buttons; + + bool canBePartOfMultipleClickWith (const RecentMouseDown& other, int maxTimeBetween) const + { + return time - other.time < maxTimeBetween + && abs (position.getX() - other.position.getX()) < 8 + && abs (position.getY() - other.position.getY()) < 8 + && buttons == other.buttons;; + } }; RecentMouseDown mouseDowns[4]; bool mouseMovedSignificantlySincePressed; int64 lastTime; - void registerMouseDown (const Point& screenPos, const int64 time, Component* const component) throw() + void registerMouseDown (const Point& screenPos, const int64 time, + Component* const component, const ModifierKeys& modifiers) throw() { for (int i = numElementsInArray (mouseDowns); --i > 0;) mouseDowns[i] = mouseDowns[i - 1]; @@ -471,6 +475,7 @@ private: mouseDowns[0].position = screenPos; mouseDowns[0].time = time; mouseDowns[0].component = component; + mouseDowns[0].buttons = modifiers.withOnlyMouseButtons(); mouseMovedSignificantlySincePressed = false; } diff --git a/src/gui/graphics/contexts/juce_RectanglePlacement.cpp b/src/gui/graphics/contexts/juce_RectanglePlacement.cpp index bc76c2f4cf..36695b219d 100644 --- a/src/gui/graphics/contexts/juce_RectanglePlacement.cpp +++ b/src/gui/graphics/contexts/juce_RectanglePlacement.cpp @@ -87,21 +87,21 @@ void RectanglePlacement::applyTo (double& x, double& y, } } -const AffineTransform RectanglePlacement::getTransformToFit (float x, float y, - float w, float h, - const float dx, const float dy, - const float dw, const float dh) const throw() +const AffineTransform RectanglePlacement::getTransformToFit (const Rectangle& source, const Rectangle& destination) const throw() { - if (w == 0 || h == 0) + if (source.isEmpty()) return AffineTransform::identity; - const float scaleX = dw / w; - const float scaleY = dh / h; + float w = source.getWidth(); + float h = source.getHeight(); + + const float scaleX = destination.getWidth() / w; + const float scaleY = destination.getHeight() / h; if ((flags & stretchToFit) != 0) - return AffineTransform::translation (-x, -y) + return AffineTransform::translation (-source.getX(), -source.getY()) .scaled (scaleX, scaleY) - .translated (dx, dy); + .translated (destination.getX(), destination.getY()); float scale = (flags & fillDestination) != 0 ? jmax (scaleX, scaleY) : jmin (scaleX, scaleY); @@ -115,21 +115,20 @@ const AffineTransform RectanglePlacement::getTransformToFit (float x, float y, w *= scale; h *= scale; - float newX = dx; + float newX = destination.getX(); + float newY = destination.getY(); if ((flags & xRight) != 0) - newX += dw - w; // right + newX += destination.getWidth() - w; // right else if ((flags & xLeft) == 0) - newX += (dw - w) / 2.0f; // centre - - float newY = dy; + newX += (destination.getWidth() - w) / 2.0f; // centre if ((flags & yBottom) != 0) - newY += dh - h; // bottom + newY += destination.getHeight() - h; // bottom else if ((flags & yTop) == 0) - newY += (dh - h) / 2.0f; // centre + newY += (destination.getHeight() - h) / 2.0f; // centre - return AffineTransform::translation (-x, -y) + return AffineTransform::translation (-source.getX(), -source.getY()) .scaled (scale, scale) .translated (newX, newY); } diff --git a/src/gui/graphics/contexts/juce_RectanglePlacement.h b/src/gui/graphics/contexts/juce_RectanglePlacement.h index 234253660d..33749c30ee 100644 --- a/src/gui/graphics/contexts/juce_RectanglePlacement.h +++ b/src/gui/graphics/contexts/juce_RectanglePlacement.h @@ -27,6 +27,7 @@ #define __JUCE_RECTANGLEPLACEMENT_JUCEHEADER__ #include "../geometry/juce_AffineTransform.h" +#include "../geometry/juce_Rectangle.h" //============================================================================== @@ -143,14 +144,8 @@ public: /** Returns the transform that should be applied to these source co-ordinates to fit them into the destination rectangle using the current flags. */ - const AffineTransform getTransformToFit (float sourceX, - float sourceY, - float sourceW, - float sourceH, - float destinationX, - float destinationY, - float destinationW, - float destinationH) const throw(); + const AffineTransform getTransformToFit (const Rectangle& source, + const Rectangle& destination) const throw(); private: //============================================================================== diff --git a/src/gui/graphics/drawables/juce_Drawable.h b/src/gui/graphics/drawables/juce_Drawable.h index 90dd302423..f159b13d84 100644 --- a/src/gui/graphics/drawables/juce_Drawable.h +++ b/src/gui/graphics/drawables/juce_Drawable.h @@ -87,19 +87,13 @@ public: and can either be made as big as possible, or just reduced to fit. @param g the graphics context to render onto - @param destX top-left of the target rectangle to fit it into - @param destY top-left of the target rectangle to fit it into - @param destWidth size of the target rectangle to fit the image into - @param destHeight size of the target rectangle to fit the image into + @param destArea the target rectangle to fit the drawable into @param placement defines the alignment and rescaling to use to fit this object within the target rectangle. @param opacity the opacity to use, in the range 0 to 1.0 */ void drawWithin (Graphics& g, - int destX, - int destY, - int destWidth, - int destHeight, + const Rectangle& destArea, const RectanglePlacement& placement, float opacity) const; diff --git a/src/gui/graphics/drawables/juce_SVGParser.cpp b/src/gui/graphics/drawables/juce_SVGParser.cpp index 3cafc83882..0b6339bf36 100644 --- a/src/gui/graphics/drawables/juce_SVGParser.cpp +++ b/src/gui/graphics/drawables/juce_SVGParser.cpp @@ -114,8 +114,8 @@ public: const RectanglePlacement placement (placementFlags); newState.transform - = placement.getTransformToFit (vx, vy, vw, vh, - 0.0f, 0.0f, newState.width, newState.height) + = placement.getTransformToFit (Rectangle (vx, vy, vw, vh), + Rectangle (0.0f, 0.0f, newState.width, newState.height)) .followedBy (newState.transform); } } diff --git a/src/native/mac/juce_mac_AudioCDBurner.mm b/src/native/mac/juce_mac_AudioCDBurner.mm index 55db48f5c3..09cb9c6d5e 100644 --- a/src/native/mac/juce_mac_AudioCDBurner.mm +++ b/src/native/mac/juce_mac_AudioCDBurner.mm @@ -452,17 +452,12 @@ static NSArray* findDiskBurnerDevices() NSMutableArray* results = [NSMutableArray array]; NSArray* devs = [DRDevice devices]; - if (devs != 0) + for (int i = 0; i < [devs count]; ++i) { - int num = [devs count]; - int i; - for (i = 0; i < num; ++i) - { - NSDictionary* dic = [[devs objectAtIndex: i] info]; - NSString* name = [dic valueForKey: DRDeviceProductNameKey]; - if (name != nil) - [results addObject: name]; - } + NSDictionary* dic = [[devs objectAtIndex: i] info]; + NSString* name = [dic valueForKey: DRDeviceProductNameKey]; + if (name != nil) + [results addObject: name]; } return results; diff --git a/src/native/mac/juce_mac_Files.mm b/src/native/mac/juce_mac_Files.mm index 8d199ed5ef..620ab167f5 100644 --- a/src/native/mac/juce_mac_Files.mm +++ b/src/native/mac/juce_mac_Files.mm @@ -140,7 +140,7 @@ bool File::isHidden() const static const String getIOSSystemLocation (NSSearchPathDirectory type) { return nsStringToJuce ([NSSearchPathForDirectoriesInDomains (type, NSUserDomainMask, YES) - objectAtIndex:0]); + objectAtIndex: 0]); } #endif