1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-02-07 04:10:08 +00:00

Added some assertions, fixed a win32 mouse mouse cursor problem, tweaked PopupMenu::showAt().

This commit is contained in:
Julian Storer 2010-11-26 12:57:24 +00:00
parent 081744b177
commit 645637ab09
14 changed files with 135 additions and 119 deletions

View file

@ -337,8 +337,7 @@ private:
if (svgDrawable != 0)
{
// to make our icon the right size, we'll put it inside a DrawableComposite, and
// set its bounding box to the size and position that we want.
// to make our icon the right size, we'll set its bounding box to the size and position that we want.
svgDrawable->setBoundingBox (RelativeParallelogram (Point<float> (-100, -100),
Point<float> (100, -100),
Point<float> (-100, 100)));

View file

@ -1408,7 +1408,7 @@ public:
void sliderValueChanged (Slider*)
{
// When you move the roation slider, we'll apply a rotaion transform to the whole tabs component..
// When you move the rotation slider, we'll apply a rotaion transform to the whole tabs component..
tabs.setTransform (AffineTransform::rotation ((float) (transformSlider.getValue() / (180.0 / double_Pi)),
getWidth() * 0.5f, getHeight() * 0.5f));
}

View file

@ -62,7 +62,7 @@ AsyncUpdater::~AsyncUpdater()
// pending on the main event thread - that's pretty dodgy threading, as the callback could
// happen after this destructor has finished. You should either use a MessageManagerLock while
// deleting this object, or find some other way to avoid such a race condition.
jassert (/*(! isUpdatePending()) ||*/ MessageManager::getInstance()->currentThreadHasLockedMessageManager());
jassert ((! isUpdatePending()) || MessageManager::getInstance()->currentThreadHasLockedMessageManager());
pendingMessage = 0;
}

View file

@ -60,10 +60,7 @@ MessageManager::~MessageManager() throw()
doPlatformSpecificShutdown();
/* If you hit this assertion, then you've probably leaked some kind of MessageListener object.
This could also be caused by leaking AsyncUpdaters, ChangeBroadcasters, and various other types
of event class.
*/
// If you hit this assertion, then you've probably leaked some kind of MessageListener object..
jassert (messageListeners.size() == 0);
jassert (instance == this);

View file

@ -1197,6 +1197,10 @@ bool Component::isTransformed() const throw()
void Component::setTransform (const AffineTransform& newTransform)
{
// If you pass in a transform with no inverse, the component will have no dimensions,
// and there will be all sorts of maths errors when converting coordinates.
jassert (! newTransform.isSingularity());
if (newTransform.isIdentity())
{
if (affineTransform_ != 0)
@ -1204,6 +1208,8 @@ void Component::setTransform (const AffineTransform& newTransform)
repaint();
affineTransform_ = 0;
repaint();
sendMovedResizedMessages (false, false);
}
}
else if (affineTransform_ == 0)
@ -1211,12 +1217,14 @@ void Component::setTransform (const AffineTransform& newTransform)
repaint();
affineTransform_ = new AffineTransform (newTransform);
repaint();
sendMovedResizedMessages (false, false);
}
else if (*affineTransform_ != newTransform)
{
repaint();
*affineTransform_ = newTransform;
repaint();
sendMovedResizedMessages (false, false);
}
}
@ -2064,6 +2072,12 @@ const Rectangle<int> Component::getLocalBounds() const throw()
return Rectangle<int> (getWidth(), getHeight());
}
const Rectangle<int> Component::getBoundsInParent() const throw()
{
return affineTransform_ == 0 ? bounds_
: bounds_.toFloat().transformed (*affineTransform_).getSmallestIntegerContainer();
}
void Component::getVisibleArea (RectangleList& result, const bool includeSiblings) const
{
result.clear();

View file

@ -318,6 +318,15 @@ public:
*/
const Rectangle<int> getLocalBounds() const throw();
/** Returns the area of this component's parent which this component covers.
The returned area is relative to the parent's coordinate space.
If the component has an affine transform specified, then the resulting area will be
the smallest rectangle that fully covers the component's transformed bounding box.
If this component has no parent, the return value will simply be the same as getBounds().
*/
const Rectangle<int> getBoundsInParent() const throw();
/** Returns the region of this component that's not obscured by other, opaque components.
The RectangleList that is returned represents the area of this component
@ -1291,7 +1300,18 @@ public:
*/
virtual void enablementChanged();
/** Changes the transparency of this component.
When painted, the entire component and all its children will be rendered
with this as the overall opacity level, where 0 is completely invisible, and
1.0 is fully opaque (i.e. normal).
@see getAlpha
*/
void setAlpha (float newAlpha);
/** Returns the component's current transparancy level.
See setAlpha() for more details.
*/
float getAlpha() const;
//==============================================================================

View file

@ -215,8 +215,8 @@ void MenuBarComponent::showMenu (int index)
const Rectangle<int> itemPos (xPositions [index], 0, xPositions [index + 1] - xPositions [index], getHeight());
m.showMenu (itemPos + getScreenPosition(),
0, itemPos.getWidth(), 0, 0, true, this,
m.showMenu (localAreaToGlobal (itemPos),
0, itemPos.getWidth(), 0, 0, this,
new AsyncCallback (this, index));
}
}

View file

@ -1467,7 +1467,6 @@ int PopupMenu::showMenu (const Rectangle<int>& target,
const int minimumWidth,
const int maximumNumColumns,
const int standardItemHeight,
const bool alignToRectangle,
Component* const componentAttachedTo,
ModalComponentManager::Callback* userCallback)
{
@ -1482,7 +1481,7 @@ int PopupMenu::showMenu (const Rectangle<int>& target,
callback->component = Window::create (*this, ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown(),
0, target, minimumWidth, maximumNumColumns > 0 ? maximumNumColumns : 7,
standardItemHeight, alignToRectangle, itemIdThatMustBeVisible,
standardItemHeight, ! target.isEmpty(), itemIdThatMustBeVisible,
&callback->managerOfChosenCommand, componentAttachedTo);
if (callback->component == 0)
@ -1518,23 +1517,20 @@ int PopupMenu::show (const int itemIdThatMustBeVisible,
const int standardItemHeight,
ModalComponentManager::Callback* callback)
{
const Point<int> mousePos (Desktop::getMousePosition());
return showAt (mousePos.getX(), mousePos.getY(),
itemIdThatMustBeVisible,
minimumWidth, maximumNumColumns,
standardItemHeight, callback);
return showMenu (Rectangle<int>().withPosition (Desktop::getMousePosition()),
itemIdThatMustBeVisible, minimumWidth, maximumNumColumns,
standardItemHeight, 0, callback);
}
int PopupMenu::showAt (const int screenX, const int screenY,
int PopupMenu::showAt (const Rectangle<int>& screenAreaToAttachTo,
const int itemIdThatMustBeVisible,
const int minimumWidth, const int maximumNumColumns,
const int standardItemHeight,
ModalComponentManager::Callback* callback)
{
return showMenu (Rectangle<int> (screenX, screenY, 1, 1),
return showMenu (screenAreaToAttachTo,
itemIdThatMustBeVisible, minimumWidth, maximumNumColumns,
standardItemHeight, false, 0, callback);
standardItemHeight, 0, callback);
}
int PopupMenu::showAt (Component* componentToAttachTo,
@ -1546,16 +1542,12 @@ int PopupMenu::showAt (Component* componentToAttachTo,
if (componentToAttachTo != 0)
{
return showMenu (componentToAttachTo->getScreenBounds(),
itemIdThatMustBeVisible,
minimumWidth,
maximumNumColumns,
standardItemHeight,
true, componentToAttachTo, callback);
itemIdThatMustBeVisible, minimumWidth, maximumNumColumns,
standardItemHeight, componentToAttachTo, callback);
}
else
{
return show (itemIdThatMustBeVisible,
minimumWidth, maximumNumColumns,
return show (itemIdThatMustBeVisible, minimumWidth, maximumNumColumns,
standardItemHeight, callback);
}
}

View file

@ -260,14 +260,15 @@ public:
This is the same as show(), but uses a specific location (in global screen
co-ordinates) rather than the current mouse position.
Note that the co-ordinates don't specify the top-left of the menu - they
indicate a point of interest, and the menu will position itself nearby to
this point, trying to keep it fully on-screen.
The screenAreaToAttachTo parameter indicates a screen area to which the menu
will be adjacent. Depending on where this is, the menu will decide which edge to
attach itself to, in order to fit itself fully on-screen. If you just want to
trigger a menu at a specific point, you can pass in a rectangle of size (0, 0)
with the position that you want.
@see show()
*/
int showAt (int screenX,
int screenY,
int showAt (const Rectangle<int>& screenAreaToAttachTo,
int itemIdThatMustBeVisible = 0,
int minimumWidth = 0,
int maximumNumColumns = 0,
@ -403,14 +404,9 @@ private:
void addSeparatorIfPending();
int showMenu (const Rectangle<int>& target,
int itemIdThatMustBeVisible,
int minimumWidth,
int maximumNumColumns,
int standardItemHeight,
bool alignToRectangle,
Component* componentAttachedTo,
ModalComponentManager::Callback* callback);
int showMenu (const Rectangle<int>& target, int itemIdThatMustBeVisible,
int minimumWidth, int maximumNumColumns, int standardItemHeight,
Component* componentAttachedTo, ModalComponentManager::Callback* callback);
};
#endif // __JUCE_POPUPMENU_JUCEHEADER__

View file

@ -76,6 +76,12 @@ ResizableWindow::ResizableWindow (const String& name,
ResizableWindow::~ResizableWindow()
{
// Don't delete or remove the resizer components yourself! They're managed by the
// ResizableWindow, and you should leave them alone! You may have deleted them
// accidentally by careless use of deleteAllChildren()..?
jassert (resizableCorner == 0 || getIndexOfChildComponent (resizableCorner) >= 0);
jassert (resizableBorder == 0 || getIndexOfChildComponent (resizableBorder) >= 0);
resizableCorner = 0;
resizableBorder = 0;
contentComponent.deleteAndZero();

View file

@ -32,37 +32,21 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
AffineTransform::AffineTransform() throw()
: mat00 (1.0f),
mat01 (0),
mat02 (0),
mat10 (0),
mat11 (1.0f),
mat12 (0)
: mat00 (1.0f), mat01 (0), mat02 (0),
mat10 (0), mat11 (1.0f), mat12 (0)
{
}
AffineTransform::AffineTransform (const AffineTransform& other) throw()
: mat00 (other.mat00),
mat01 (other.mat01),
mat02 (other.mat02),
mat10 (other.mat10),
mat11 (other.mat11),
mat12 (other.mat12)
: mat00 (other.mat00), mat01 (other.mat01), mat02 (other.mat02),
mat10 (other.mat10), mat11 (other.mat11), mat12 (other.mat12)
{
}
AffineTransform::AffineTransform (const float mat00_,
const float mat01_,
const float mat02_,
const float mat10_,
const float mat11_,
const float mat12_) throw()
: mat00 (mat00_),
mat01 (mat01_),
mat02 (mat02_),
mat10 (mat10_),
mat11 (mat11_),
mat12 (mat12_)
AffineTransform::AffineTransform (const float mat00_, const float mat01_, const float mat02_,
const float mat10_, const float mat11_, const float mat12_) throw()
: mat00 (mat00_), mat01 (mat01_), mat02 (mat02_),
mat10 (mat10_), mat11 (mat11_), mat12 (mat12_)
{
}
@ -117,31 +101,13 @@ const AffineTransform AffineTransform::followedBy (const AffineTransform& other)
other.mat10 * mat02 + other.mat11 * mat12 + other.mat12);
}
const AffineTransform AffineTransform::followedBy (const float omat00,
const float omat01,
const float omat02,
const float omat10,
const float omat11,
const float omat12) const throw()
{
return AffineTransform (omat00 * mat00 + omat01 * mat10,
omat00 * mat01 + omat01 * mat11,
omat00 * mat02 + omat01 * mat12 + omat02,
omat10 * mat00 + omat11 * mat10,
omat10 * mat01 + omat11 * mat11,
omat10 * mat02 + omat11 * mat12 + omat12);
}
//==============================================================================
const AffineTransform AffineTransform::translated (const float dx,
const float dy) const throw()
const AffineTransform AffineTransform::translated (const float dx, const float dy) const throw()
{
return AffineTransform (mat00, mat01, mat02 + dx,
mat10, mat11, mat12 + dy);
}
const AffineTransform AffineTransform::translation (const float dx,
const float dy) throw()
const AffineTransform AffineTransform::translation (const float dx, const float dy) throw()
{
return AffineTransform (1.0f, 0, dx,
0, 1.0f, dy);
@ -152,8 +118,12 @@ const AffineTransform AffineTransform::rotated (const float rad) const throw()
const float cosRad = std::cos (rad);
const float sinRad = std::sin (rad);
return followedBy (cosRad, -sinRad, 0,
sinRad, cosRad, 0);
return AffineTransform (cosRad * mat00 + -sinRad * mat10,
cosRad * mat01 + -sinRad * mat11,
cosRad * mat02 + -sinRad * mat12,
sinRad * mat00 + cosRad * mat10,
sinRad * mat01 + cosRad * mat11,
sinRad * mat02 + cosRad * mat12);
}
const AffineTransform AffineTransform::rotation (const float rad) throw()
@ -165,33 +135,27 @@ const AffineTransform AffineTransform::rotation (const float rad) throw()
sinRad, cosRad, 0);
}
const AffineTransform AffineTransform::rotated (const float angle,
const float pivotX,
const float pivotY) const throw()
const AffineTransform AffineTransform::rotation (const float rad, const float pivotX, const float pivotY) throw()
{
return translated (-pivotX, -pivotY)
.rotated (angle)
.translated (pivotX, pivotY);
const float cosRad = std::cos (rad);
const float sinRad = std::sin (rad);
return AffineTransform (cosRad, -sinRad, -cosRad * pivotX + sinRad * pivotY + pivotX,
sinRad, cosRad, -sinRad * pivotX + -cosRad * pivotY + pivotY);
}
const AffineTransform AffineTransform::rotation (const float angle,
const float pivotX,
const float pivotY) throw()
const AffineTransform AffineTransform::rotated (const float angle, const float pivotX, const float pivotY) const throw()
{
return translation (-pivotX, -pivotY)
.rotated (angle)
.translated (pivotX, pivotY);
return followedBy (rotation (angle, pivotX, pivotY));
}
const AffineTransform AffineTransform::scaled (const float factorX,
const float factorY) const throw()
const AffineTransform AffineTransform::scaled (const float factorX, const float factorY) const throw()
{
return AffineTransform (factorX * mat00, factorX * mat01, factorX * mat02,
factorY * mat10, factorY * mat11, factorY * mat12);
}
const AffineTransform AffineTransform::scale (const float factorX,
const float factorY) throw()
const AffineTransform AffineTransform::scale (const float factorX, const float factorY) throw()
{
return AffineTransform (factorX, 0, 0,
0, factorY, 0);
@ -200,9 +164,8 @@ const AffineTransform AffineTransform::scale (const float factorX,
const AffineTransform AffineTransform::scaled (const float factorX, const float factorY,
const float pivotX, const float pivotY) const throw()
{
return translated (-pivotX, -pivotY)
.scaled (factorX, factorY)
.translated (pivotX, pivotY);
return AffineTransform (factorX * mat00, factorX * mat01, factorX * mat02 + pivotX * (1.0f - factorX),
factorY * mat10, factorY * mat11, factorY * mat12 + pivotY * (1.0f - factorY));
}
const AffineTransform AffineTransform::scale (const float factorX, const float factorY,
@ -212,11 +175,20 @@ const AffineTransform AffineTransform::scale (const float factorX, const float f
0, factorY, pivotY * (1.0f - factorY));
}
const AffineTransform AffineTransform::sheared (const float shearX,
const float shearY) const throw()
const AffineTransform AffineTransform::shear (float shearX, float shearY) throw()
{
return followedBy (1.0f, shearX, 0,
shearY, 1.0f, 0);
return AffineTransform (1.0f, shearX, 0,
shearY, 1.0f, 0);
}
const AffineTransform AffineTransform::sheared (const float shearX, const float shearY) const throw()
{
return AffineTransform (mat00 + shearX * mat10,
mat01 + shearX * mat11,
mat02 + shearX * mat12,
shearY * mat00 + mat10,
shearY * mat01 + mat11,
shearY * mat02 + mat12);
}
const AffineTransform AffineTransform::inverted() const throw()

View file

@ -178,11 +178,12 @@ public:
float pivotX, float pivotY) throw();
/** Returns a transform which is the same as this one followed by a shear.
The shear is centred around the origin (0, 0).
*/
const AffineTransform sheared (float shearX,
float shearY) const throw();
const AffineTransform sheared (float shearX, float shearY) const throw();
/** Returns a shear transform, centred around the origin (0, 0). */
static const AffineTransform shear (float shearX, float shearY) throw();
/** Returns a matrix which is the inverse operation of this one.
@ -244,11 +245,6 @@ public:
//==============================================================================
juce_UseDebuggingNewOperator
private:
//==============================================================================
const AffineTransform followedBy (float mat00, float mat01, float mat02,
float mat10, float mat11, float mat12) const throw();
};
#endif // __JUCE_AFFINETRANSFORM_JUCEHEADER__

View file

@ -2630,6 +2630,11 @@ void MouseCursor::deleteMouseCursor (void* const cursorHandle, const bool isStan
DestroyCursor ((HCURSOR) cursorHandle);
}
enum
{
hiddenMouseCursorHandle = 32500 // (arbitrary non-zero value to mark this type of cursor)
};
void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorType type)
{
LPCTSTR cursorName = IDC_ARROW;
@ -2637,7 +2642,7 @@ void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorT
switch (type)
{
case NormalCursor: break;
case NoCursor: return 0;
case NoCursor: return (void*) hiddenMouseCursorHandle;
case WaitCursor: cursorName = IDC_WAIT; break;
case IBeamCursor: cursorName = IDC_IBEAM; break;
case PointingHandCursor: cursorName = MAKEINTRESOURCE(32649); break;
@ -2696,6 +2701,8 @@ void MouseCursor::showInWindow (ComponentPeer*) const
if (c == 0)
c = LoadCursor (0, IDC_ARROW);
else if (c == (HCURSOR) hiddenMouseCursorHandle)
c = 0;
SetCursor (c);
}

View file

@ -208,6 +208,23 @@ void XmlDocument::skipHeader()
if (input == 0)
return;
#if JUCE_DEBUG
const String header (found, input - found);
const String encoding (header.fromFirstOccurrenceOf ("encoding", false, true)
.fromFirstOccurrenceOf ("=", false, false)
.fromFirstOccurrenceOf ("\"", false, false)
.upToFirstOccurrenceOf ("\"", false, false).trim());
/* If you load an XML document with a non-UTF encoding type, it may have been
loaded wrongly.. Since all the files are read via the normal juce file streams,
they're treated as UTF-8, so by the time it gets to the parser, the encoding will
have been lost. Best plan is to stick to utf-8 or if you have specific files to
read, use your own code to convert them to a unicode String, and pass that to the
XML parser.
*/
jassert (encoding.isEmpty() || encoding.startsWithIgnoreCase ("utf-"));
#endif
input += 2;
}