mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-15 00:24:19 +00:00
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.
This commit is contained in:
parent
85c32498dc
commit
b80bb4bf38
15 changed files with 90 additions and 96 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -512,6 +512,28 @@ void ValueTree::SharedObject::moveChild (int currentIndex, int newIndex, UndoMan
|
|||
}
|
||||
}
|
||||
|
||||
void ValueTree::SharedObject::reorderChildren (const ReferenceCountedArray <SharedObject>& 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
|
||||
|
|
|
|||
|
|
@ -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 <typename ElementComparator>
|
||||
void sort (ElementComparator& comparator, const bool retainOrderOfEquivalentItems = false)
|
||||
void sort (ElementComparator& comparator, UndoManager* undoManager, bool retainOrderOfEquivalentItems)
|
||||
{
|
||||
if (object != 0)
|
||||
{
|
||||
ReferenceCountedArray <SharedObject> sortedList (object->children);
|
||||
ComparatorAdapter <ElementComparator> 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 <SharedObject>& newOrder, UndoManager*);
|
||||
bool isEquivalentTo (const SharedObject& other) const;
|
||||
XmlElement* createXml() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,13 +69,15 @@ void ToolbarButton::paintButtonArea (Graphics& g,
|
|||
if (getToggleState() && toggledOnImage != 0)
|
||||
d = toggledOnImage;
|
||||
|
||||
const Rectangle<float> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<int> 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<int>& screenPos, const int64 time, Component* const component) throw()
|
||||
void registerMouseDown (const Point<int>& 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<float>& source, const Rectangle<float>& 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<float>& source,
|
||||
const Rectangle<float>& destination) const throw();
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -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<float>& destArea,
|
||||
const RectanglePlacement& placement,
|
||||
float opacity) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<float> (vx, vy, vw, vh),
|
||||
Rectangle<float> (0.0f, 0.0f, newState.width, newState.height))
|
||||
.followedBy (newState.transform);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue