mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-05 03:50:07 +00:00
Updated the path flattening code to correctly observe tolerance values, and made the tolerances adapt to the scaling being used when drawing to a transformed graphics context. Fixed a small issue with focus listeners, and a mac menu dismissal problem.
This commit is contained in:
parent
f402ce803b
commit
5f347bc999
29 changed files with 432 additions and 311 deletions
|
|
@ -40,9 +40,9 @@
|
|||
#include <exdisp.h>
|
||||
#pragma warning (disable:4584)
|
||||
|
||||
#include "juce_IncludeBrowserPluginInfo.h"
|
||||
#include "../../../juce_amalgamated.h"
|
||||
#include "juce_BrowserPluginComponent.h"
|
||||
#include "juce_IncludeBrowserPluginInfo.h"
|
||||
|
||||
#ifndef JuceBrowserPlugin_ActiveXCLSID
|
||||
#error "For an activeX plugin, you need to define JuceBrowserPlugin_ActiveXCLSID in your BrowserPluginCharacteristics.h file!"
|
||||
|
|
|
|||
|
|
@ -66,9 +66,9 @@
|
|||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#include "juce_IncludeBrowserPluginInfo.h"
|
||||
#include "../../../juce_amalgamated.h"
|
||||
#include "juce_BrowserPluginComponent.h"
|
||||
#include "juce_IncludeBrowserPluginInfo.h"
|
||||
|
||||
#if JUCE_MAC && JUCE_DEBUG && 0
|
||||
#include <fstream>
|
||||
|
|
|
|||
|
|
@ -42956,7 +42956,9 @@ void Desktop::triggerFocusCallback()
|
|||
|
||||
void Desktop::handleAsyncUpdate()
|
||||
{
|
||||
Component* currentFocus = Component::getCurrentlyFocusedComponent();
|
||||
// The component may be deleted during this operation, but we'll use a SafePointer rather than a
|
||||
// BailOutChecker so that any remaining listeners will still get a callback (with a null pointer).
|
||||
Component::SafePointer<Component> currentFocus (Component::getCurrentlyFocusedComponent());
|
||||
focusListeners.call (&FocusChangeListener::globalFocusChanged, currentFocus);
|
||||
}
|
||||
|
||||
|
|
@ -70204,15 +70206,18 @@ int PopupMenu::showAt (Component* componentToAttachTo,
|
|||
}
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE PopupMenu::dismissAllActiveMenus()
|
||||
bool JUCE_CALLTYPE PopupMenu::dismissAllActiveMenus()
|
||||
{
|
||||
for (int i = Window::getActiveWindows().size(); --i >= 0;)
|
||||
const int numWindows = Window::getActiveWindows().size();
|
||||
for (int i = numWindows; --i >= 0;)
|
||||
{
|
||||
Window* const pmw = Window::getActiveWindows()[i];
|
||||
|
||||
if (pmw != 0)
|
||||
pmw->dismissMenu (0);
|
||||
}
|
||||
|
||||
return numWindows > 0;
|
||||
}
|
||||
|
||||
int PopupMenu::getNumItems() const throw()
|
||||
|
|
@ -82175,7 +82180,7 @@ void Graphics::strokePath (const Path& path,
|
|||
const AffineTransform& transform) const
|
||||
{
|
||||
Path stroke;
|
||||
strokeType.createStrokedPath (stroke, path, transform);
|
||||
strokeType.createStrokedPath (stroke, path, transform, context->getScaleFactor());
|
||||
fillPath (stroke);
|
||||
}
|
||||
|
||||
|
|
@ -82660,6 +82665,12 @@ void LowLevelGraphicsPostScriptRenderer::addTransform (const AffineTransform& /*
|
|||
jassertfalse;
|
||||
}
|
||||
|
||||
float LowLevelGraphicsPostScriptRenderer::getScaleFactor()
|
||||
{
|
||||
jassertfalse; //xxx
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
bool LowLevelGraphicsPostScriptRenderer::clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
needToClip = true;
|
||||
|
|
@ -84873,6 +84884,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
float getScaleFactor() const
|
||||
{
|
||||
return isOnlyTranslated ? 1.0f : complexTransform.getScaleFactor();
|
||||
}
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
if (clip != 0)
|
||||
|
|
@ -85278,6 +85294,11 @@ void LowLevelGraphicsSoftwareRenderer::addTransform (const AffineTransform& tran
|
|||
currentState->addTransform (transform);
|
||||
}
|
||||
|
||||
float LowLevelGraphicsSoftwareRenderer::getScaleFactor()
|
||||
{
|
||||
return currentState->getScaleFactor();
|
||||
}
|
||||
|
||||
bool LowLevelGraphicsSoftwareRenderer::clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
return currentState->clipToRectangle (r);
|
||||
|
|
@ -88682,7 +88703,7 @@ private:
|
|||
float x = getCoordLength (strokeWidth, viewBoxW), y = 0.0f;
|
||||
transform.transformPoints (ox, oy, x, y);
|
||||
|
||||
return PathStrokeType (strokeWidth.isNotEmpty() ? juce_hypotf (x - ox, y - oy) : 1.0f,
|
||||
return PathStrokeType (strokeWidth.isNotEmpty() ? juce_hypot (x - ox, y - oy) : 1.0f,
|
||||
joinStyle, capStyle);
|
||||
}
|
||||
|
||||
|
|
@ -91443,6 +91464,11 @@ bool AffineTransform::isOnlyTranslation() const throw()
|
|||
&& (mat11 == 1.0f);
|
||||
}
|
||||
|
||||
float AffineTransform::getScaleFactor() const throw()
|
||||
{
|
||||
return juce_hypot (mat00 + mat01, mat10 + mat11);
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
/*** End of inlined file: juce_AffineTransform.cpp ***/
|
||||
|
||||
|
|
@ -91581,6 +91607,11 @@ namespace PathHelpers
|
|||
|
||||
return String (start, (int) (t - start));
|
||||
}
|
||||
|
||||
inline double lengthOf (float x1, float y1, float x2, float y2) throw()
|
||||
{
|
||||
return juce_hypot ((double) (x1 - x2), (double) (y1 - y2));
|
||||
}
|
||||
}
|
||||
|
||||
const float Path::lineMarker = 100001.0f;
|
||||
|
|
@ -92481,13 +92512,13 @@ const AffineTransform Path::getTransformToScaleToFit (const float x, const float
|
|||
}
|
||||
}
|
||||
|
||||
bool Path::contains (const float x, const float y, const float tolerence) const
|
||||
bool Path::contains (const float x, const float y, const float tolerance) const
|
||||
{
|
||||
if (x <= pathXMin || x >= pathXMax
|
||||
|| y <= pathYMin || y >= pathYMax)
|
||||
return false;
|
||||
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerence);
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerance);
|
||||
|
||||
int positiveCrossings = 0;
|
||||
int negativeCrossings = 0;
|
||||
|
|
@ -92512,14 +92543,14 @@ bool Path::contains (const float x, const float y, const float tolerence) const
|
|||
: ((negativeCrossings + positiveCrossings) & 1) != 0;
|
||||
}
|
||||
|
||||
bool Path::contains (const Point<float>& point, const float tolerence) const
|
||||
bool Path::contains (const Point<float>& point, const float tolerance) const
|
||||
{
|
||||
return contains (point.getX(), point.getY(), tolerence);
|
||||
return contains (point.getX(), point.getY(), tolerance);
|
||||
}
|
||||
|
||||
bool Path::intersectsLine (const Line<float>& line, const float tolerence)
|
||||
bool Path::intersectsLine (const Line<float>& line, const float tolerance)
|
||||
{
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerence);
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerance);
|
||||
Point<float> intersection;
|
||||
|
||||
while (i.next())
|
||||
|
|
@ -92672,8 +92703,7 @@ const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
|
||||
if (lastWasLine)
|
||||
{
|
||||
const double len1 = juce_hypot (startX - joinX,
|
||||
startY - joinY);
|
||||
const double len1 = PathHelpers::lengthOf (startX, startY, joinX, joinY);
|
||||
|
||||
if (len1 > 0)
|
||||
{
|
||||
|
|
@ -92683,8 +92713,7 @@ const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
p.data.elements [p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded);
|
||||
}
|
||||
|
||||
const double len2 = juce_hypot (endX - joinX,
|
||||
endY - joinY);
|
||||
const double len2 = PathHelpers::lengthOf (endX, endY, joinX, joinY);
|
||||
|
||||
if (len2 > 0)
|
||||
{
|
||||
|
|
@ -92714,8 +92743,7 @@ const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
endX = data.elements [indexOfPathStartThis + 4];
|
||||
endY = data.elements [indexOfPathStartThis + 5];
|
||||
|
||||
const double len1 = juce_hypot (startX - joinX,
|
||||
startY - joinY);
|
||||
const double len1 = PathHelpers::lengthOf (startX, startY, joinX, joinY);
|
||||
|
||||
if (len1 > 0)
|
||||
{
|
||||
|
|
@ -92725,8 +92753,7 @@ const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
p.data.elements [p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded);
|
||||
}
|
||||
|
||||
const double len2 = juce_hypot (endX - joinX,
|
||||
endY - joinY);
|
||||
const double len2 = PathHelpers::lengthOf (endX, endY, joinX, joinY);
|
||||
|
||||
if (len2 > 0)
|
||||
{
|
||||
|
|
@ -93095,9 +93122,11 @@ BEGIN_JUCE_NAMESPACE
|
|||
#pragma optimize ("t", on)
|
||||
#endif
|
||||
|
||||
const float PathFlatteningIterator::defaultTolerance = 0.6f;
|
||||
|
||||
PathFlatteningIterator::PathFlatteningIterator (const Path& path_,
|
||||
const AffineTransform& transform_,
|
||||
float tolerence_)
|
||||
const float tolerance)
|
||||
: x2 (0),
|
||||
y2 (0),
|
||||
closesSubPath (false),
|
||||
|
|
@ -93105,7 +93134,7 @@ PathFlatteningIterator::PathFlatteningIterator (const Path& path_,
|
|||
path (path_),
|
||||
transform (transform_),
|
||||
points (path_.data.elements),
|
||||
tolerence (tolerence_ * tolerence_),
|
||||
toleranceSquared (tolerance * tolerance),
|
||||
subPathCloseX (0),
|
||||
subPathCloseY (0),
|
||||
isIdentityTransform (transform_.isIdentity()),
|
||||
|
|
@ -93221,11 +93250,6 @@ bool PathFlatteningIterator::next()
|
|||
stackPos = stackBase + offset;
|
||||
}
|
||||
|
||||
const float dx1 = x1 - x2;
|
||||
const float dy1 = y1 - y2;
|
||||
const float dx2 = x2 - x3;
|
||||
const float dy2 = y2 - y3;
|
||||
|
||||
const float m1x = (x1 + x2) * 0.5f;
|
||||
const float m1y = (y1 + y2) * 0.5f;
|
||||
const float m2x = (x2 + x3) * 0.5f;
|
||||
|
|
@ -93233,7 +93257,10 @@ bool PathFlatteningIterator::next()
|
|||
const float m3x = (m1x + m2x) * 0.5f;
|
||||
const float m3y = (m1y + m2y) * 0.5f;
|
||||
|
||||
if (dx1*dx1 + dy1*dy1 + dx2*dx2 + dy2*dy2 > tolerence)
|
||||
const float errorX = m3x - x2;
|
||||
const float errorY = m3y - y2;
|
||||
|
||||
if (errorX * errorX + errorY * errorY > toleranceSquared)
|
||||
{
|
||||
*stackPos++ = y3;
|
||||
*stackPos++ = x3;
|
||||
|
|
@ -93271,13 +93298,6 @@ bool PathFlatteningIterator::next()
|
|||
stackPos = stackBase + offset;
|
||||
}
|
||||
|
||||
const float dx1 = x1 - x2;
|
||||
const float dy1 = y1 - y2;
|
||||
const float dx2 = x2 - x3;
|
||||
const float dy2 = y2 - y3;
|
||||
const float dx3 = x3 - x4;
|
||||
const float dy3 = y3 - y4;
|
||||
|
||||
const float m1x = (x1 + x2) * 0.5f;
|
||||
const float m1y = (y1 + y2) * 0.5f;
|
||||
const float m2x = (x3 + x2) * 0.5f;
|
||||
|
|
@ -93289,8 +93309,13 @@ bool PathFlatteningIterator::next()
|
|||
const float m5x = (m3x + m2x) * 0.5f;
|
||||
const float m5y = (m3y + m2y) * 0.5f;
|
||||
|
||||
if (dx1*dx1 + dy1*dy1 + dx2*dx2
|
||||
+ dy2*dy2 + dx3*dx3 + dy3*dy3 > tolerence)
|
||||
const float error1X = m4x - x2;
|
||||
const float error1Y = m4y - y2;
|
||||
const float error2X = m5x - x3;
|
||||
const float error2Y = m5y - y3;
|
||||
|
||||
if (error1X * error1X + error1Y * error1Y > toleranceSquared
|
||||
|| error2X * error2X + error2Y * error2Y > toleranceSquared)
|
||||
{
|
||||
*stackPos++ = y4;
|
||||
*stackPos++ = x4;
|
||||
|
|
@ -93628,7 +93653,7 @@ namespace PathStrokeHelpers
|
|||
|
||||
float dx = x2 - x1;
|
||||
float dy = y2 - y1;
|
||||
const float len = juce_hypotf (dx, dy);
|
||||
const float len = juce_hypot (dx, dy);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
|
|
@ -93705,7 +93730,7 @@ namespace PathStrokeHelpers
|
|||
LineSection& l = subPath.getReference (subPath.size() - 1);
|
||||
float dx = l.rx2 - l.rx1;
|
||||
float dy = l.ry2 - l.ry1;
|
||||
const float len = juce_hypotf (dx, dy);
|
||||
const float len = juce_hypot (dx, dy);
|
||||
|
||||
if (len <= amountAtEnd && subPath.size() > 1)
|
||||
{
|
||||
|
|
@ -93733,7 +93758,7 @@ namespace PathStrokeHelpers
|
|||
LineSection& l = subPath.getReference (0);
|
||||
float dx = l.rx2 - l.rx1;
|
||||
float dy = l.ry2 - l.ry1;
|
||||
const float len = juce_hypotf (dx, dy);
|
||||
const float len = juce_hypot (dx, dy);
|
||||
|
||||
if (len <= amountAtStart && subPath.size() > 1)
|
||||
{
|
||||
|
|
@ -93876,6 +93901,8 @@ namespace PathStrokeHelpers
|
|||
const AffineTransform& transform,
|
||||
const float extraAccuracy, const Arrowhead* const arrowhead)
|
||||
{
|
||||
jassert (extraAccuracy > 0);
|
||||
|
||||
if (thickness <= 0)
|
||||
{
|
||||
destPath.clear();
|
||||
|
|
@ -93902,7 +93929,7 @@ namespace PathStrokeHelpers
|
|||
|
||||
// Iterate the path, creating a list of the
|
||||
// left/right-hand lines along either side of it...
|
||||
PathFlatteningIterator it (*sourcePath, transform, 9.0f / extraAccuracy);
|
||||
PathFlatteningIterator it (*sourcePath, transform, PathFlatteningIterator::defaultTolerance / extraAccuracy);
|
||||
|
||||
Array <LineSection> subPath;
|
||||
subPath.ensureStorageAllocated (512);
|
||||
|
|
@ -93910,7 +93937,7 @@ namespace PathStrokeHelpers
|
|||
l.x1 = 0;
|
||||
l.y1 = 0;
|
||||
|
||||
const float minSegmentLength = 2.0f / (extraAccuracy * extraAccuracy);
|
||||
const float minSegmentLength = 0.0001f;
|
||||
|
||||
while (it.next())
|
||||
{
|
||||
|
|
@ -93994,6 +94021,8 @@ void PathStrokeType::createDashedStroke (Path& destPath,
|
|||
const AffineTransform& transform,
|
||||
const float extraAccuracy) const
|
||||
{
|
||||
jassert (extraAccuracy > 0);
|
||||
|
||||
if (thickness <= 0)
|
||||
return;
|
||||
|
||||
|
|
@ -94001,7 +94030,7 @@ void PathStrokeType::createDashedStroke (Path& destPath,
|
|||
jassert ((numDashLengths & 1) == 0);
|
||||
|
||||
Path newDestPath;
|
||||
PathFlatteningIterator it (sourcePath, transform, 9.0f / extraAccuracy);
|
||||
PathFlatteningIterator it (sourcePath, transform, PathFlatteningIterator::defaultTolerance / extraAccuracy);
|
||||
|
||||
bool first = true;
|
||||
int dashNum = 0;
|
||||
|
|
@ -94037,7 +94066,7 @@ void PathStrokeType::createDashedStroke (Path& destPath,
|
|||
|
||||
dx = it.x2 - it.x1;
|
||||
dy = it.y2 - it.y1;
|
||||
lineLen = juce_hypotf (dx, dy);
|
||||
lineLen = juce_hypot (dx, dy);
|
||||
lineEndPos += lineLen;
|
||||
first = it.closesSubPath;
|
||||
}
|
||||
|
|
@ -240547,6 +240576,12 @@ public:
|
|||
jassertfalse;
|
||||
}
|
||||
|
||||
float getScaleFactor()
|
||||
{
|
||||
jassertfalse; //xxx
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
currentState->clipToRectangle (r);
|
||||
|
|
@ -265647,6 +265682,12 @@ public:
|
|||
lastClipRectIsValid = false;
|
||||
}
|
||||
|
||||
float getScaleFactor()
|
||||
{
|
||||
CGAffineTransform t = CGContextGetCTM (context);
|
||||
return (float) juce_hypot (t.a + t.c, t.b + t.d);
|
||||
}
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()));
|
||||
|
|
@ -270377,6 +270418,12 @@ public:
|
|||
lastClipRectIsValid = false;
|
||||
}
|
||||
|
||||
float getScaleFactor()
|
||||
{
|
||||
CGAffineTransform t = CGContextGetCTM (context);
|
||||
return (float) juce_hypot (t.a + t.c, t.b + t.d);
|
||||
}
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()));
|
||||
|
|
@ -273823,7 +273870,6 @@ class JuceMainMenuHandler : private MenuBarModel::Listener,
|
|||
private DeletedAtShutdown
|
||||
{
|
||||
public:
|
||||
static JuceMainMenuHandler* instance;
|
||||
|
||||
JuceMainMenuHandler()
|
||||
: currentModel (0),
|
||||
|
|
@ -273918,64 +273964,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static void flashMenuBar (NSMenu* menu)
|
||||
{
|
||||
if ([[menu title] isEqualToString: @"Apple"])
|
||||
return;
|
||||
|
||||
[menu retain];
|
||||
|
||||
const unichar f35Key = NSF35FunctionKey;
|
||||
NSString* f35String = [NSString stringWithCharacters: &f35Key length: 1];
|
||||
|
||||
NSMenuItem* item = [[NSMenuItem alloc] initWithTitle: @"x"
|
||||
action: nil
|
||||
keyEquivalent: f35String];
|
||||
[item setTarget: nil];
|
||||
[menu insertItem: item atIndex: [menu numberOfItems]];
|
||||
[item release];
|
||||
|
||||
if ([menu indexOfItem: item] >= 0)
|
||||
{
|
||||
NSEvent* f35Event = [NSEvent keyEventWithType: NSKeyDown
|
||||
location: NSZeroPoint
|
||||
modifierFlags: NSCommandKeyMask
|
||||
timestamp: 0
|
||||
windowNumber: 0
|
||||
context: [NSGraphicsContext currentContext]
|
||||
characters: f35String
|
||||
charactersIgnoringModifiers: f35String
|
||||
isARepeat: NO
|
||||
keyCode: 0];
|
||||
|
||||
[menu performKeyEquivalent: f35Event];
|
||||
|
||||
if ([menu indexOfItem: item] >= 0)
|
||||
[menu removeItem: item]; // (this throws if the item isn't actually in the menu)
|
||||
}
|
||||
|
||||
[menu release];
|
||||
}
|
||||
|
||||
static NSMenuItem* findMenuItem (NSMenu* const menu, const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
for (NSInteger i = [menu numberOfItems]; --i >= 0;)
|
||||
{
|
||||
NSMenuItem* m = [menu itemAtIndex: i];
|
||||
if ([m tag] == info.commandID)
|
||||
return m;
|
||||
|
||||
if ([m submenu] != 0)
|
||||
{
|
||||
NSMenuItem* found = findMenuItem ([m submenu], info);
|
||||
if (found != 0)
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
NSMenuItem* item = findMenuItem ([NSApp mainMenu], info);
|
||||
|
|
@ -273984,8 +273972,16 @@ public:
|
|||
flashMenuBar ([item menu]);
|
||||
}
|
||||
|
||||
void updateMenus()
|
||||
void updateMenus (NSMenu* menu)
|
||||
{
|
||||
if (PopupMenu::dismissAllActiveMenus())
|
||||
{
|
||||
// If we were running a juce menu, then we should let that modal loop finish before allowing
|
||||
// the OS menus to start their own modal loop - so cancel the menu that was being opened..
|
||||
if ([menu respondsToSelector: @selector (cancelTracking)])
|
||||
[menu performSelector: @selector (cancelTracking)];
|
||||
}
|
||||
|
||||
if (Time::getMillisecondCounter() > lastUpdateTime + 500)
|
||||
menuBarItemsChanged (0);
|
||||
}
|
||||
|
|
@ -274006,9 +274002,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
MenuBarModel* currentModel;
|
||||
uint32 lastUpdateTime;
|
||||
|
||||
void addMenuItem (PopupMenu::MenuItemIterator& iter, NSMenu* menuToAddTo,
|
||||
const int topLevelMenuId, const int topLevelIndex)
|
||||
{
|
||||
|
|
@ -274098,7 +274091,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static JuceMainMenuHandler* instance;
|
||||
|
||||
MenuBarModel* currentModel;
|
||||
uint32 lastUpdateTime;
|
||||
JuceMenuCallback* callback;
|
||||
|
||||
private:
|
||||
|
||||
NSMenu* createMenu (const PopupMenu menu,
|
||||
|
|
@ -274119,11 +274117,70 @@ private:
|
|||
[m update];
|
||||
return m;
|
||||
}
|
||||
|
||||
static NSMenuItem* findMenuItem (NSMenu* const menu, const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
for (NSInteger i = [menu numberOfItems]; --i >= 0;)
|
||||
{
|
||||
NSMenuItem* m = [menu itemAtIndex: i];
|
||||
if ([m tag] == info.commandID)
|
||||
return m;
|
||||
|
||||
if ([m submenu] != 0)
|
||||
{
|
||||
NSMenuItem* found = findMenuItem ([m submenu], info);
|
||||
if (found != 0)
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flashMenuBar (NSMenu* menu)
|
||||
{
|
||||
if ([[menu title] isEqualToString: @"Apple"])
|
||||
return;
|
||||
|
||||
[menu retain];
|
||||
|
||||
const unichar f35Key = NSF35FunctionKey;
|
||||
NSString* f35String = [NSString stringWithCharacters: &f35Key length: 1];
|
||||
|
||||
NSMenuItem* item = [[NSMenuItem alloc] initWithTitle: @"x"
|
||||
action: nil
|
||||
keyEquivalent: f35String];
|
||||
[item setTarget: nil];
|
||||
[menu insertItem: item atIndex: [menu numberOfItems]];
|
||||
[item release];
|
||||
|
||||
if ([menu indexOfItem: item] >= 0)
|
||||
{
|
||||
NSEvent* f35Event = [NSEvent keyEventWithType: NSKeyDown
|
||||
location: NSZeroPoint
|
||||
modifierFlags: NSCommandKeyMask
|
||||
timestamp: 0
|
||||
windowNumber: 0
|
||||
context: [NSGraphicsContext currentContext]
|
||||
characters: f35String
|
||||
charactersIgnoringModifiers: f35String
|
||||
isARepeat: NO
|
||||
keyCode: 0];
|
||||
|
||||
[menu performKeyEquivalent: f35Event];
|
||||
|
||||
if ([menu indexOfItem: item] >= 0)
|
||||
[menu removeItem: item]; // (this throws if the item isn't actually in the menu)
|
||||
}
|
||||
|
||||
[menu release];
|
||||
}
|
||||
};
|
||||
|
||||
JuceMainMenuHandler* JuceMainMenuHandler::instance = 0;
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
||||
@implementation JuceMenuCallback
|
||||
|
||||
- (JuceMenuCallback*) initWithOwner: (JuceMainMenuHandler*) owner_
|
||||
|
|
@ -274177,10 +274234,8 @@ END_JUCE_NAMESPACE
|
|||
|
||||
- (void) menuNeedsUpdate: (NSMenu*) menu;
|
||||
{
|
||||
(void) menu;
|
||||
|
||||
if (JuceMainMenuHandler::instance != 0)
|
||||
JuceMainMenuHandler::instance->updateMenus();
|
||||
JuceMainMenuHandler::instance->updateMenus (menu);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 103
|
||||
#define JUCE_BUILDNUMBER 104
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
@ -1261,25 +1261,15 @@ inline void swapVariables (Type& variable1, Type& variable2)
|
|||
|
||||
// Some useful maths functions that aren't always present with all compilers and build settings.
|
||||
|
||||
/** Using juce_hypot and juce_hypotf is easier than dealing with all the different
|
||||
versions of these functions of various platforms and compilers. */
|
||||
inline double juce_hypot (double a, double b) throw()
|
||||
/** Using juce_hypot is easier than dealing with the different types of hypot function
|
||||
that are provided by the various platforms and compilers. */
|
||||
template <typename Type>
|
||||
inline Type juce_hypot (Type a, Type b) throw()
|
||||
{
|
||||
#if JUCE_WINDOWS
|
||||
return _hypot (a, b);
|
||||
return static_cast <Type> (_hypot (a, b));
|
||||
#else
|
||||
return hypot (a, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Using juce_hypot and juce_hypotf is easier than dealing with all the different
|
||||
versions of these functions of various platforms and compilers. */
|
||||
inline float juce_hypotf (float a, float b) throw()
|
||||
{
|
||||
#if JUCE_WINDOWS
|
||||
return (float) _hypot (a, b);
|
||||
#else
|
||||
return hypotf (a, b);
|
||||
return static_cast <Type> (hypot (a, b));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -19796,6 +19786,12 @@ public:
|
|||
*/
|
||||
float getTranslationY() const throw() { return mat12; }
|
||||
|
||||
/** Returns the approximate scale factor by which lengths will be transformed.
|
||||
Obviously a length may be scaled by entirely different amounts depending on its
|
||||
direction, so this is only appropriate as a rough guide.
|
||||
*/
|
||||
float getScaleFactor() const throw();
|
||||
|
||||
/* The transform matrix is:
|
||||
|
||||
(mat00 mat01 mat02)
|
||||
|
|
@ -19902,10 +19898,10 @@ public:
|
|||
const Point operator-() const throw() { return Point (-x, -y); }
|
||||
|
||||
/** Returns the straight-line distance between this point and another one. */
|
||||
ValueType getDistanceFromOrigin() const throw() { return (ValueType) juce_hypot (x, y); }
|
||||
ValueType getDistanceFromOrigin() const throw() { return juce_hypot (x, y); }
|
||||
|
||||
/** Returns the straight-line distance between this point and another one. */
|
||||
ValueType getDistanceFrom (const Point& other) const throw() { return (ValueType) juce_hypot (x - other.x, y - other.y); }
|
||||
ValueType getDistanceFrom (const Point& other) const throw() { return juce_hypot (x - other.x, y - other.y); }
|
||||
|
||||
/** Returns the angle from this point to another one.
|
||||
|
||||
|
|
@ -20872,7 +20868,8 @@ public:
|
|||
ValueType perpendicularDistance) const throw()
|
||||
{
|
||||
const Point<ValueType> delta (end - start);
|
||||
const double length = juce_hypot (delta.getX(), delta.getY());
|
||||
const double length = juce_hypot ((double) delta.getX(),
|
||||
(double) delta.getY());
|
||||
if (length == 0)
|
||||
return start;
|
||||
|
||||
|
|
@ -21985,14 +21982,14 @@ public:
|
|||
|
||||
The path's winding rule is taken into account by this method.
|
||||
|
||||
The tolerence parameter is passed to the PathFlatteningIterator that
|
||||
is used to trace the path - for more info about it, see the notes for
|
||||
the PathFlatteningIterator constructor.
|
||||
The tolerance parameter is the maximum error allowed when flattening the path,
|
||||
so this method could return a false positive when your point is up to this distance
|
||||
outside the path's boundary.
|
||||
|
||||
@see closeSubPath, setUsingNonZeroWinding
|
||||
*/
|
||||
bool contains (float x, float y,
|
||||
float tolerence = 10.0f) const;
|
||||
float tolerance = 1.0f) const;
|
||||
|
||||
/** Checks whether a point lies within the path.
|
||||
|
||||
|
|
@ -22001,14 +21998,14 @@ public:
|
|||
|
||||
The path's winding rule is taken into account by this method.
|
||||
|
||||
The tolerence parameter is passed to the PathFlatteningIterator that
|
||||
is used to trace the path - for more info about it, see the notes for
|
||||
the PathFlatteningIterator constructor.
|
||||
The tolerance parameter is the maximum error allowed when flattening the path,
|
||||
so this method could return a false positive when your point is up to this distance
|
||||
outside the path's boundary.
|
||||
|
||||
@see closeSubPath, setUsingNonZeroWinding
|
||||
*/
|
||||
bool contains (const Point<float>& point,
|
||||
float tolerence = 10.0f) const;
|
||||
float tolerance = 1.0f) const;
|
||||
|
||||
/** Checks whether a line crosses the path.
|
||||
|
||||
|
|
@ -22016,12 +22013,12 @@ public:
|
|||
lines or curves. It doesn't take into account whether the line is inside
|
||||
or outside the path, or whether the path is open or closed.
|
||||
|
||||
The tolerence parameter is passed to the PathFlatteningIterator that
|
||||
is used to trace the path - for more info about it, see the notes for
|
||||
the PathFlatteningIterator constructor.
|
||||
The tolerance parameter is the maximum error allowed when flattening the path,
|
||||
so this method could return a false positive when your point is up to this distance
|
||||
outside the path's boundary.
|
||||
*/
|
||||
bool intersectsLine (const Line<float>& line,
|
||||
float tolerence = 10.0f);
|
||||
float tolerance = 1.0f);
|
||||
|
||||
/** Cuts off parts of a line to keep the parts that are either inside or
|
||||
outside this path.
|
||||
|
|
@ -23214,8 +23211,9 @@ public:
|
|||
@param transform an optional transform to apply to the points from the source path
|
||||
as they are being used
|
||||
@param extraAccuracy if this is greater than 1.0, it will subdivide the path to
|
||||
a higher resolution, which improved the quality if you'll later want
|
||||
to enlarge the stroked path
|
||||
a higher resolution, which improves the quality if you'll later want
|
||||
to enlarge the stroked path. So for example, if you're planning on drawing
|
||||
the stroke at 3x the size that you're creating it, you should set this to 3.
|
||||
|
||||
@see createDashedStroke
|
||||
*/
|
||||
|
|
@ -23243,8 +23241,9 @@ public:
|
|||
@param transform an optional transform to apply to the points from the source path
|
||||
as they are being used
|
||||
@param extraAccuracy if this is greater than 1.0, it will subdivide the path to
|
||||
a higher resolution, which improved the quality if you'll later want
|
||||
to enlarge the stroked path
|
||||
a higher resolution, which improves the quality if you'll later want
|
||||
to enlarge the stroked path. So for example, if you're planning on drawing
|
||||
the stroke at 3x the size that you're creating it, you should set this to 3.
|
||||
*/
|
||||
void createDashedStroke (Path& destPath,
|
||||
const Path& sourcePath,
|
||||
|
|
@ -23267,8 +23266,9 @@ public:
|
|||
@param transform an optional transform to apply to the points from the source path
|
||||
as they are being used
|
||||
@param extraAccuracy if this is greater than 1.0, it will subdivide the path to
|
||||
a higher resolution, which improved the quality if you'll later want
|
||||
to enlarge the stroked path
|
||||
a higher resolution, which improves the quality if you'll later want
|
||||
to enlarge the stroked path. So for example, if you're planning on drawing
|
||||
the stroke at 3x the size that you're creating it, you should set this to 3.
|
||||
@see createDashedStroke
|
||||
*/
|
||||
void createStrokeWithArrowheads (Path& destPath,
|
||||
|
|
@ -37307,7 +37307,7 @@ public:
|
|||
by some means other than a user action, and you'd like to make sure that menus
|
||||
aren't left hanging around.
|
||||
*/
|
||||
static void JUCE_CALLTYPE dismissAllActiveMenus();
|
||||
static bool JUCE_CALLTYPE dismissAllActiveMenus();
|
||||
|
||||
/** Specifies a look-and-feel for the menu and any sub-menus that it has.
|
||||
|
||||
|
|
@ -60277,6 +60277,7 @@ public:
|
|||
*/
|
||||
virtual void setOrigin (int x, int y) = 0;
|
||||
virtual void addTransform (const AffineTransform& transform) = 0;
|
||||
virtual float getScaleFactor() = 0;
|
||||
|
||||
virtual bool clipToRectangle (const Rectangle<int>& r) = 0;
|
||||
virtual bool clipToRectangleList (const RectangleList& clipRegion) = 0;
|
||||
|
|
@ -60342,6 +60343,7 @@ public:
|
|||
bool isVectorDevice() const;
|
||||
void setOrigin (int x, int y);
|
||||
void addTransform (const AffineTransform& transform);
|
||||
float getScaleFactor();
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r);
|
||||
bool clipToRectangleList (const RectangleList& clipRegion);
|
||||
|
|
@ -60440,6 +60442,7 @@ public:
|
|||
|
||||
void setOrigin (int x, int y);
|
||||
void addTransform (const AffineTransform& transform);
|
||||
float getScaleFactor();
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r);
|
||||
bool clipToRectangleList (const RectangleList& clipRegion);
|
||||
|
|
@ -61417,13 +61420,13 @@ public:
|
|||
|
||||
@param path the path to iterate along
|
||||
@param transform a transform to apply to each point in the path being iterated
|
||||
@param tolerence the amount by which the curves are allowed to deviate from the
|
||||
lines into which they are being broken down - a higher tolerence
|
||||
is a bit faster, but less smooth.
|
||||
@param tolerance the amount by which the curves are allowed to deviate from the lines
|
||||
into which they are being broken down - a higher tolerance contains
|
||||
less lines, so can be generated faster, but will be less smooth.
|
||||
*/
|
||||
PathFlatteningIterator (const Path& path,
|
||||
const AffineTransform& transform = AffineTransform::identity,
|
||||
float tolerence = 6.0f);
|
||||
float tolerance = defaultTolerance);
|
||||
|
||||
/** Destructor. */
|
||||
~PathFlatteningIterator();
|
||||
|
|
@ -61460,12 +61463,16 @@ public:
|
|||
bool isLastInSubpath() const throw() { return stackPos == stackBase.getData()
|
||||
&& (index >= path.numElements || points [index] == Path::moveMarker); }
|
||||
|
||||
/** This is the default value that should be used for the tolerance value (see the constructor parameters). */
|
||||
static const float defaultTolerance;
|
||||
|
||||
private:
|
||||
|
||||
const Path& path;
|
||||
const AffineTransform transform;
|
||||
float* points;
|
||||
float tolerence, subPathCloseX, subPathCloseY;
|
||||
const float toleranceSquared;
|
||||
float subPathCloseX, subPathCloseY;
|
||||
const bool isIdentityTransform;
|
||||
|
||||
HeapBlock <float> stackBase;
|
||||
|
|
|
|||
|
|
@ -292,25 +292,15 @@ inline void swapVariables (Type& variable1, Type& variable2)
|
|||
//==============================================================================
|
||||
// Some useful maths functions that aren't always present with all compilers and build settings.
|
||||
|
||||
/** Using juce_hypot and juce_hypotf is easier than dealing with all the different
|
||||
versions of these functions of various platforms and compilers. */
|
||||
inline double juce_hypot (double a, double b) throw()
|
||||
/** Using juce_hypot is easier than dealing with the different types of hypot function
|
||||
that are provided by the various platforms and compilers. */
|
||||
template <typename Type>
|
||||
inline Type juce_hypot (Type a, Type b) throw()
|
||||
{
|
||||
#if JUCE_WINDOWS
|
||||
return _hypot (a, b);
|
||||
return static_cast <Type> (_hypot (a, b));
|
||||
#else
|
||||
return hypot (a, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Using juce_hypot and juce_hypotf is easier than dealing with all the different
|
||||
versions of these functions of various platforms and compilers. */
|
||||
inline float juce_hypotf (float a, float b) throw()
|
||||
{
|
||||
#if JUCE_WINDOWS
|
||||
return (float) _hypot (a, b);
|
||||
#else
|
||||
return hypotf (a, b);
|
||||
return static_cast <Type> (hypot (a, b));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 103
|
||||
#define JUCE_BUILDNUMBER 104
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
|
|||
|
|
@ -274,7 +274,9 @@ void Desktop::triggerFocusCallback()
|
|||
|
||||
void Desktop::handleAsyncUpdate()
|
||||
{
|
||||
Component* currentFocus = Component::getCurrentlyFocusedComponent();
|
||||
// The component may be deleted during this operation, but we'll use a SafePointer rather than a
|
||||
// BailOutChecker so that any remaining listeners will still get a callback (with a null pointer).
|
||||
Component::SafePointer<Component> currentFocus (Component::getCurrentlyFocusedComponent());
|
||||
focusListeners.call (&FocusChangeListener::globalFocusChanged, currentFocus);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1528,15 +1528,18 @@ int PopupMenu::showAt (Component* componentToAttachTo,
|
|||
}
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE PopupMenu::dismissAllActiveMenus()
|
||||
bool JUCE_CALLTYPE PopupMenu::dismissAllActiveMenus()
|
||||
{
|
||||
for (int i = Window::getActiveWindows().size(); --i >= 0;)
|
||||
const int numWindows = Window::getActiveWindows().size();
|
||||
for (int i = numWindows; --i >= 0;)
|
||||
{
|
||||
Window* const pmw = Window::getActiveWindows()[i];
|
||||
|
||||
if (pmw != 0)
|
||||
pmw->dismissMenu (0);
|
||||
}
|
||||
|
||||
return numWindows > 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ public:
|
|||
by some means other than a user action, and you'd like to make sure that menus
|
||||
aren't left hanging around.
|
||||
*/
|
||||
static void JUCE_CALLTYPE dismissAllActiveMenus();
|
||||
static bool JUCE_CALLTYPE dismissAllActiveMenus();
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ void Graphics::strokePath (const Path& path,
|
|||
const AffineTransform& transform) const
|
||||
{
|
||||
Path stroke;
|
||||
strokeType.createStrokedPath (stroke, path, transform);
|
||||
strokeType.createStrokedPath (stroke, path, transform, context->getScaleFactor());
|
||||
fillPath (stroke);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ public:
|
|||
*/
|
||||
virtual void setOrigin (int x, int y) = 0;
|
||||
virtual void addTransform (const AffineTransform& transform) = 0;
|
||||
virtual float getScaleFactor() = 0;
|
||||
|
||||
virtual bool clipToRectangle (const Rectangle<int>& r) = 0;
|
||||
virtual bool clipToRectangleList (const RectangleList& clipRegion) = 0;
|
||||
|
|
|
|||
|
|
@ -118,6 +118,12 @@ void LowLevelGraphicsPostScriptRenderer::addTransform (const AffineTransform& /*
|
|||
jassertfalse;
|
||||
}
|
||||
|
||||
float LowLevelGraphicsPostScriptRenderer::getScaleFactor()
|
||||
{
|
||||
jassertfalse; //xxx
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
bool LowLevelGraphicsPostScriptRenderer::clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
needToClip = true;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ public:
|
|||
bool isVectorDevice() const;
|
||||
void setOrigin (int x, int y);
|
||||
void addTransform (const AffineTransform& transform);
|
||||
float getScaleFactor();
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r);
|
||||
bool clipToRectangleList (const RectangleList& clipRegion);
|
||||
|
|
|
|||
|
|
@ -1843,6 +1843,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
float getScaleFactor() const
|
||||
{
|
||||
return isOnlyTranslated ? 1.0f : complexTransform.getScaleFactor();
|
||||
}
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
if (clip != 0)
|
||||
|
|
@ -2254,6 +2259,11 @@ void LowLevelGraphicsSoftwareRenderer::addTransform (const AffineTransform& tran
|
|||
currentState->addTransform (transform);
|
||||
}
|
||||
|
||||
float LowLevelGraphicsSoftwareRenderer::getScaleFactor()
|
||||
{
|
||||
return currentState->getScaleFactor();
|
||||
}
|
||||
|
||||
bool LowLevelGraphicsSoftwareRenderer::clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
return currentState->clipToRectangle (r);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ public:
|
|||
//==============================================================================
|
||||
void setOrigin (int x, int y);
|
||||
void addTransform (const AffineTransform& transform);
|
||||
float getScaleFactor();
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r);
|
||||
bool clipToRectangleList (const RectangleList& clipRegion);
|
||||
|
|
|
|||
|
|
@ -819,7 +819,7 @@ private:
|
|||
float x = getCoordLength (strokeWidth, viewBoxW), y = 0.0f;
|
||||
transform.transformPoints (ox, oy, x, y);
|
||||
|
||||
return PathStrokeType (strokeWidth.isNotEmpty() ? juce_hypotf (x - ox, y - oy) : 1.0f,
|
||||
return PathStrokeType (strokeWidth.isNotEmpty() ? juce_hypot (x - ox, y - oy) : 1.0f,
|
||||
joinStyle, capStyle);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -244,5 +244,10 @@ bool AffineTransform::isOnlyTranslation() const throw()
|
|||
&& (mat11 == 1.0f);
|
||||
}
|
||||
|
||||
float AffineTransform::getScaleFactor() const throw()
|
||||
{
|
||||
return juce_hypot (mat00 + mat01, mat10 + mat11);
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -232,6 +232,12 @@ public:
|
|||
*/
|
||||
float getTranslationY() const throw() { return mat12; }
|
||||
|
||||
/** Returns the approximate scale factor by which lengths will be transformed.
|
||||
Obviously a length may be scaled by entirely different amounts depending on its
|
||||
direction, so this is only appropriate as a rough guide.
|
||||
*/
|
||||
float getScaleFactor() const throw();
|
||||
|
||||
//==============================================================================
|
||||
/* The transform matrix is:
|
||||
|
||||
|
|
|
|||
|
|
@ -209,7 +209,8 @@ public:
|
|||
ValueType perpendicularDistance) const throw()
|
||||
{
|
||||
const Point<ValueType> delta (end - start);
|
||||
const double length = juce_hypot (delta.getX(), delta.getY());
|
||||
const double length = juce_hypot ((double) delta.getX(),
|
||||
(double) delta.getY());
|
||||
if (length == 0)
|
||||
return start;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ namespace PathHelpers
|
|||
|
||||
return String (start, (int) (t - start));
|
||||
}
|
||||
|
||||
inline double lengthOf (float x1, float y1, float x2, float y2) throw()
|
||||
{
|
||||
return juce_hypot ((double) (x1 - x2), (double) (y1 - y2));
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -966,13 +971,13 @@ const AffineTransform Path::getTransformToScaleToFit (const float x, const float
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
bool Path::contains (const float x, const float y, const float tolerence) const
|
||||
bool Path::contains (const float x, const float y, const float tolerance) const
|
||||
{
|
||||
if (x <= pathXMin || x >= pathXMax
|
||||
|| y <= pathYMin || y >= pathYMax)
|
||||
return false;
|
||||
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerence);
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerance);
|
||||
|
||||
int positiveCrossings = 0;
|
||||
int negativeCrossings = 0;
|
||||
|
|
@ -997,14 +1002,14 @@ bool Path::contains (const float x, const float y, const float tolerence) const
|
|||
: ((negativeCrossings + positiveCrossings) & 1) != 0;
|
||||
}
|
||||
|
||||
bool Path::contains (const Point<float>& point, const float tolerence) const
|
||||
bool Path::contains (const Point<float>& point, const float tolerance) const
|
||||
{
|
||||
return contains (point.getX(), point.getY(), tolerence);
|
||||
return contains (point.getX(), point.getY(), tolerance);
|
||||
}
|
||||
|
||||
bool Path::intersectsLine (const Line<float>& line, const float tolerence)
|
||||
bool Path::intersectsLine (const Line<float>& line, const float tolerance)
|
||||
{
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerence);
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerance);
|
||||
Point<float> intersection;
|
||||
|
||||
while (i.next())
|
||||
|
|
@ -1158,8 +1163,7 @@ const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
|
||||
if (lastWasLine)
|
||||
{
|
||||
const double len1 = juce_hypot (startX - joinX,
|
||||
startY - joinY);
|
||||
const double len1 = PathHelpers::lengthOf (startX, startY, joinX, joinY);
|
||||
|
||||
if (len1 > 0)
|
||||
{
|
||||
|
|
@ -1169,8 +1173,7 @@ const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
p.data.elements [p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded);
|
||||
}
|
||||
|
||||
const double len2 = juce_hypot (endX - joinX,
|
||||
endY - joinY);
|
||||
const double len2 = PathHelpers::lengthOf (endX, endY, joinX, joinY);
|
||||
|
||||
if (len2 > 0)
|
||||
{
|
||||
|
|
@ -1200,8 +1203,7 @@ const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
endX = data.elements [indexOfPathStartThis + 4];
|
||||
endY = data.elements [indexOfPathStartThis + 5];
|
||||
|
||||
const double len1 = juce_hypot (startX - joinX,
|
||||
startY - joinY);
|
||||
const double len1 = PathHelpers::lengthOf (startX, startY, joinX, joinY);
|
||||
|
||||
if (len1 > 0)
|
||||
{
|
||||
|
|
@ -1211,8 +1213,7 @@ const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
p.data.elements [p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded);
|
||||
}
|
||||
|
||||
const double len2 = juce_hypot (endX - joinX,
|
||||
endY - joinY);
|
||||
const double len2 = PathHelpers::lengthOf (endX, endY, joinX, joinY);
|
||||
|
||||
if (len2 > 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -107,14 +107,14 @@ public:
|
|||
|
||||
The path's winding rule is taken into account by this method.
|
||||
|
||||
The tolerence parameter is passed to the PathFlatteningIterator that
|
||||
is used to trace the path - for more info about it, see the notes for
|
||||
the PathFlatteningIterator constructor.
|
||||
The tolerance parameter is the maximum error allowed when flattening the path,
|
||||
so this method could return a false positive when your point is up to this distance
|
||||
outside the path's boundary.
|
||||
|
||||
@see closeSubPath, setUsingNonZeroWinding
|
||||
*/
|
||||
bool contains (float x, float y,
|
||||
float tolerence = 10.0f) const;
|
||||
float tolerance = 1.0f) const;
|
||||
|
||||
/** Checks whether a point lies within the path.
|
||||
|
||||
|
|
@ -123,14 +123,14 @@ public:
|
|||
|
||||
The path's winding rule is taken into account by this method.
|
||||
|
||||
The tolerence parameter is passed to the PathFlatteningIterator that
|
||||
is used to trace the path - for more info about it, see the notes for
|
||||
the PathFlatteningIterator constructor.
|
||||
The tolerance parameter is the maximum error allowed when flattening the path,
|
||||
so this method could return a false positive when your point is up to this distance
|
||||
outside the path's boundary.
|
||||
|
||||
@see closeSubPath, setUsingNonZeroWinding
|
||||
*/
|
||||
bool contains (const Point<float>& point,
|
||||
float tolerence = 10.0f) const;
|
||||
float tolerance = 1.0f) const;
|
||||
|
||||
/** Checks whether a line crosses the path.
|
||||
|
||||
|
|
@ -138,12 +138,12 @@ public:
|
|||
lines or curves. It doesn't take into account whether the line is inside
|
||||
or outside the path, or whether the path is open or closed.
|
||||
|
||||
The tolerence parameter is passed to the PathFlatteningIterator that
|
||||
is used to trace the path - for more info about it, see the notes for
|
||||
the PathFlatteningIterator constructor.
|
||||
The tolerance parameter is the maximum error allowed when flattening the path,
|
||||
so this method could return a false positive when your point is up to this distance
|
||||
outside the path's boundary.
|
||||
*/
|
||||
bool intersectsLine (const Line<float>& line,
|
||||
float tolerence = 10.0f);
|
||||
float tolerance = 1.0f);
|
||||
|
||||
/** Cuts off parts of a line to keep the parts that are either inside or
|
||||
outside this path.
|
||||
|
|
|
|||
|
|
@ -33,10 +33,14 @@ BEGIN_JUCE_NAMESPACE
|
|||
#pragma optimize ("t", on)
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
const float PathFlatteningIterator::defaultTolerance = 0.6f;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
PathFlatteningIterator::PathFlatteningIterator (const Path& path_,
|
||||
const AffineTransform& transform_,
|
||||
float tolerence_)
|
||||
const float tolerance)
|
||||
: x2 (0),
|
||||
y2 (0),
|
||||
closesSubPath (false),
|
||||
|
|
@ -44,7 +48,7 @@ PathFlatteningIterator::PathFlatteningIterator (const Path& path_,
|
|||
path (path_),
|
||||
transform (transform_),
|
||||
points (path_.data.elements),
|
||||
tolerence (tolerence_ * tolerence_),
|
||||
toleranceSquared (tolerance * tolerance),
|
||||
subPathCloseX (0),
|
||||
subPathCloseY (0),
|
||||
isIdentityTransform (transform_.isIdentity()),
|
||||
|
|
@ -160,11 +164,6 @@ bool PathFlatteningIterator::next()
|
|||
stackPos = stackBase + offset;
|
||||
}
|
||||
|
||||
const float dx1 = x1 - x2;
|
||||
const float dy1 = y1 - y2;
|
||||
const float dx2 = x2 - x3;
|
||||
const float dy2 = y2 - y3;
|
||||
|
||||
const float m1x = (x1 + x2) * 0.5f;
|
||||
const float m1y = (y1 + y2) * 0.5f;
|
||||
const float m2x = (x2 + x3) * 0.5f;
|
||||
|
|
@ -172,7 +171,10 @@ bool PathFlatteningIterator::next()
|
|||
const float m3x = (m1x + m2x) * 0.5f;
|
||||
const float m3y = (m1y + m2y) * 0.5f;
|
||||
|
||||
if (dx1*dx1 + dy1*dy1 + dx2*dx2 + dy2*dy2 > tolerence)
|
||||
const float errorX = m3x - x2;
|
||||
const float errorY = m3y - y2;
|
||||
|
||||
if (errorX * errorX + errorY * errorY > toleranceSquared)
|
||||
{
|
||||
*stackPos++ = y3;
|
||||
*stackPos++ = x3;
|
||||
|
|
@ -210,13 +212,6 @@ bool PathFlatteningIterator::next()
|
|||
stackPos = stackBase + offset;
|
||||
}
|
||||
|
||||
const float dx1 = x1 - x2;
|
||||
const float dy1 = y1 - y2;
|
||||
const float dx2 = x2 - x3;
|
||||
const float dy2 = y2 - y3;
|
||||
const float dx3 = x3 - x4;
|
||||
const float dy3 = y3 - y4;
|
||||
|
||||
const float m1x = (x1 + x2) * 0.5f;
|
||||
const float m1y = (y1 + y2) * 0.5f;
|
||||
const float m2x = (x3 + x2) * 0.5f;
|
||||
|
|
@ -228,8 +223,13 @@ bool PathFlatteningIterator::next()
|
|||
const float m5x = (m3x + m2x) * 0.5f;
|
||||
const float m5y = (m3y + m2y) * 0.5f;
|
||||
|
||||
if (dx1*dx1 + dy1*dy1 + dx2*dx2
|
||||
+ dy2*dy2 + dx3*dx3 + dy3*dy3 > tolerence)
|
||||
const float error1X = m4x - x2;
|
||||
const float error1Y = m4y - y2;
|
||||
const float error2X = m5x - x3;
|
||||
const float error2Y = m5y - y3;
|
||||
|
||||
if (error1X * error1X + error1Y * error1Y > toleranceSquared
|
||||
|| error2X * error2X + error2Y * error2Y > toleranceSquared)
|
||||
{
|
||||
*stackPos++ = y4;
|
||||
*stackPos++ = x4;
|
||||
|
|
|
|||
|
|
@ -50,13 +50,13 @@ public:
|
|||
|
||||
@param path the path to iterate along
|
||||
@param transform a transform to apply to each point in the path being iterated
|
||||
@param tolerence the amount by which the curves are allowed to deviate from the
|
||||
lines into which they are being broken down - a higher tolerence
|
||||
is a bit faster, but less smooth.
|
||||
@param tolerance the amount by which the curves are allowed to deviate from the lines
|
||||
into which they are being broken down - a higher tolerance contains
|
||||
less lines, so can be generated faster, but will be less smooth.
|
||||
*/
|
||||
PathFlatteningIterator (const Path& path,
|
||||
const AffineTransform& transform = AffineTransform::identity,
|
||||
float tolerence = 6.0f);
|
||||
float tolerance = defaultTolerance);
|
||||
|
||||
/** Destructor. */
|
||||
~PathFlatteningIterator();
|
||||
|
|
@ -94,12 +94,17 @@ public:
|
|||
bool isLastInSubpath() const throw() { return stackPos == stackBase.getData()
|
||||
&& (index >= path.numElements || points [index] == Path::moveMarker); }
|
||||
|
||||
|
||||
/** This is the default value that should be used for the tolerance value (see the constructor parameters). */
|
||||
static const float defaultTolerance;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const Path& path;
|
||||
const AffineTransform transform;
|
||||
float* points;
|
||||
float tolerence, subPathCloseX, subPathCloseY;
|
||||
const float toleranceSquared;
|
||||
float subPathCloseX, subPathCloseY;
|
||||
const bool isIdentityTransform;
|
||||
|
||||
HeapBlock <float> stackBase;
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ namespace PathStrokeHelpers
|
|||
|
||||
float dx = x2 - x1;
|
||||
float dy = y2 - y1;
|
||||
const float len = juce_hypotf (dx, dy);
|
||||
const float len = juce_hypot (dx, dy);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
|
|
@ -380,7 +380,7 @@ namespace PathStrokeHelpers
|
|||
LineSection& l = subPath.getReference (subPath.size() - 1);
|
||||
float dx = l.rx2 - l.rx1;
|
||||
float dy = l.ry2 - l.ry1;
|
||||
const float len = juce_hypotf (dx, dy);
|
||||
const float len = juce_hypot (dx, dy);
|
||||
|
||||
if (len <= amountAtEnd && subPath.size() > 1)
|
||||
{
|
||||
|
|
@ -408,7 +408,7 @@ namespace PathStrokeHelpers
|
|||
LineSection& l = subPath.getReference (0);
|
||||
float dx = l.rx2 - l.rx1;
|
||||
float dy = l.ry2 - l.ry1;
|
||||
const float len = juce_hypotf (dx, dy);
|
||||
const float len = juce_hypot (dx, dy);
|
||||
|
||||
if (len <= amountAtStart && subPath.size() > 1)
|
||||
{
|
||||
|
|
@ -551,6 +551,8 @@ namespace PathStrokeHelpers
|
|||
const AffineTransform& transform,
|
||||
const float extraAccuracy, const Arrowhead* const arrowhead)
|
||||
{
|
||||
jassert (extraAccuracy > 0);
|
||||
|
||||
if (thickness <= 0)
|
||||
{
|
||||
destPath.clear();
|
||||
|
|
@ -577,7 +579,7 @@ namespace PathStrokeHelpers
|
|||
|
||||
// Iterate the path, creating a list of the
|
||||
// left/right-hand lines along either side of it...
|
||||
PathFlatteningIterator it (*sourcePath, transform, 9.0f / extraAccuracy);
|
||||
PathFlatteningIterator it (*sourcePath, transform, PathFlatteningIterator::defaultTolerance / extraAccuracy);
|
||||
|
||||
Array <LineSection> subPath;
|
||||
subPath.ensureStorageAllocated (512);
|
||||
|
|
@ -585,7 +587,7 @@ namespace PathStrokeHelpers
|
|||
l.x1 = 0;
|
||||
l.y1 = 0;
|
||||
|
||||
const float minSegmentLength = 2.0f / (extraAccuracy * extraAccuracy);
|
||||
const float minSegmentLength = 0.0001f;
|
||||
|
||||
while (it.next())
|
||||
{
|
||||
|
|
@ -669,6 +671,8 @@ void PathStrokeType::createDashedStroke (Path& destPath,
|
|||
const AffineTransform& transform,
|
||||
const float extraAccuracy) const
|
||||
{
|
||||
jassert (extraAccuracy > 0);
|
||||
|
||||
if (thickness <= 0)
|
||||
return;
|
||||
|
||||
|
|
@ -676,7 +680,7 @@ void PathStrokeType::createDashedStroke (Path& destPath,
|
|||
jassert ((numDashLengths & 1) == 0);
|
||||
|
||||
Path newDestPath;
|
||||
PathFlatteningIterator it (sourcePath, transform, 9.0f / extraAccuracy);
|
||||
PathFlatteningIterator it (sourcePath, transform, PathFlatteningIterator::defaultTolerance / extraAccuracy);
|
||||
|
||||
bool first = true;
|
||||
int dashNum = 0;
|
||||
|
|
@ -712,7 +716,7 @@ void PathStrokeType::createDashedStroke (Path& destPath,
|
|||
|
||||
dx = it.x2 - it.x1;
|
||||
dy = it.y2 - it.y1;
|
||||
lineLen = juce_hypotf (dx, dy);
|
||||
lineLen = juce_hypot (dx, dy);
|
||||
lineEndPos += lineLen;
|
||||
first = it.closesSubPath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,8 +96,9 @@ public:
|
|||
@param transform an optional transform to apply to the points from the source path
|
||||
as they are being used
|
||||
@param extraAccuracy if this is greater than 1.0, it will subdivide the path to
|
||||
a higher resolution, which improved the quality if you'll later want
|
||||
to enlarge the stroked path
|
||||
a higher resolution, which improves the quality if you'll later want
|
||||
to enlarge the stroked path. So for example, if you're planning on drawing
|
||||
the stroke at 3x the size that you're creating it, you should set this to 3.
|
||||
|
||||
@see createDashedStroke
|
||||
*/
|
||||
|
|
@ -127,8 +128,9 @@ public:
|
|||
@param transform an optional transform to apply to the points from the source path
|
||||
as they are being used
|
||||
@param extraAccuracy if this is greater than 1.0, it will subdivide the path to
|
||||
a higher resolution, which improved the quality if you'll later want
|
||||
to enlarge the stroked path
|
||||
a higher resolution, which improves the quality if you'll later want
|
||||
to enlarge the stroked path. So for example, if you're planning on drawing
|
||||
the stroke at 3x the size that you're creating it, you should set this to 3.
|
||||
*/
|
||||
void createDashedStroke (Path& destPath,
|
||||
const Path& sourcePath,
|
||||
|
|
@ -152,8 +154,9 @@ public:
|
|||
@param transform an optional transform to apply to the points from the source path
|
||||
as they are being used
|
||||
@param extraAccuracy if this is greater than 1.0, it will subdivide the path to
|
||||
a higher resolution, which improved the quality if you'll later want
|
||||
to enlarge the stroked path
|
||||
a higher resolution, which improves the quality if you'll later want
|
||||
to enlarge the stroked path. So for example, if you're planning on drawing
|
||||
the stroke at 3x the size that you're creating it, you should set this to 3.
|
||||
@see createDashedStroke
|
||||
*/
|
||||
void createStrokeWithArrowheads (Path& destPath,
|
||||
|
|
|
|||
|
|
@ -120,10 +120,10 @@ public:
|
|||
const Point operator-() const throw() { return Point (-x, -y); }
|
||||
|
||||
/** Returns the straight-line distance between this point and another one. */
|
||||
ValueType getDistanceFromOrigin() const throw() { return (ValueType) juce_hypot (x, y); }
|
||||
ValueType getDistanceFromOrigin() const throw() { return juce_hypot (x, y); }
|
||||
|
||||
/** Returns the straight-line distance between this point and another one. */
|
||||
ValueType getDistanceFrom (const Point& other) const throw() { return (ValueType) juce_hypot (x - other.x, y - other.y); }
|
||||
ValueType getDistanceFrom (const Point& other) const throw() { return juce_hypot (x - other.x, y - other.y); }
|
||||
|
||||
/** Returns the angle from this point to another one.
|
||||
|
||||
|
|
|
|||
|
|
@ -192,6 +192,12 @@ public:
|
|||
lastClipRectIsValid = false;
|
||||
}
|
||||
|
||||
float getScaleFactor()
|
||||
{
|
||||
CGAffineTransform t = CGContextGetCTM (context);
|
||||
return (float) juce_hypot (t.a + t.c, t.b + t.d);
|
||||
}
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()));
|
||||
|
|
|
|||
|
|
@ -57,8 +57,6 @@ class JuceMainMenuHandler : private MenuBarModel::Listener,
|
|||
private DeletedAtShutdown
|
||||
{
|
||||
public:
|
||||
static JuceMainMenuHandler* instance;
|
||||
|
||||
//==============================================================================
|
||||
JuceMainMenuHandler()
|
||||
: currentModel (0),
|
||||
|
|
@ -153,64 +151,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static void flashMenuBar (NSMenu* menu)
|
||||
{
|
||||
if ([[menu title] isEqualToString: @"Apple"])
|
||||
return;
|
||||
|
||||
[menu retain];
|
||||
|
||||
const unichar f35Key = NSF35FunctionKey;
|
||||
NSString* f35String = [NSString stringWithCharacters: &f35Key length: 1];
|
||||
|
||||
NSMenuItem* item = [[NSMenuItem alloc] initWithTitle: @"x"
|
||||
action: nil
|
||||
keyEquivalent: f35String];
|
||||
[item setTarget: nil];
|
||||
[menu insertItem: item atIndex: [menu numberOfItems]];
|
||||
[item release];
|
||||
|
||||
if ([menu indexOfItem: item] >= 0)
|
||||
{
|
||||
NSEvent* f35Event = [NSEvent keyEventWithType: NSKeyDown
|
||||
location: NSZeroPoint
|
||||
modifierFlags: NSCommandKeyMask
|
||||
timestamp: 0
|
||||
windowNumber: 0
|
||||
context: [NSGraphicsContext currentContext]
|
||||
characters: f35String
|
||||
charactersIgnoringModifiers: f35String
|
||||
isARepeat: NO
|
||||
keyCode: 0];
|
||||
|
||||
[menu performKeyEquivalent: f35Event];
|
||||
|
||||
if ([menu indexOfItem: item] >= 0)
|
||||
[menu removeItem: item]; // (this throws if the item isn't actually in the menu)
|
||||
}
|
||||
|
||||
[menu release];
|
||||
}
|
||||
|
||||
static NSMenuItem* findMenuItem (NSMenu* const menu, const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
for (NSInteger i = [menu numberOfItems]; --i >= 0;)
|
||||
{
|
||||
NSMenuItem* m = [menu itemAtIndex: i];
|
||||
if ([m tag] == info.commandID)
|
||||
return m;
|
||||
|
||||
if ([m submenu] != 0)
|
||||
{
|
||||
NSMenuItem* found = findMenuItem ([m submenu], info);
|
||||
if (found != 0)
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
NSMenuItem* item = findMenuItem ([NSApp mainMenu], info);
|
||||
|
|
@ -219,8 +159,16 @@ public:
|
|||
flashMenuBar ([item menu]);
|
||||
}
|
||||
|
||||
void updateMenus()
|
||||
void updateMenus (NSMenu* menu)
|
||||
{
|
||||
if (PopupMenu::dismissAllActiveMenus())
|
||||
{
|
||||
// If we were running a juce menu, then we should let that modal loop finish before allowing
|
||||
// the OS menus to start their own modal loop - so cancel the menu that was being opened..
|
||||
if ([menu respondsToSelector: @selector (cancelTracking)])
|
||||
[menu performSelector: @selector (cancelTracking)];
|
||||
}
|
||||
|
||||
if (Time::getMillisecondCounter() > lastUpdateTime + 500)
|
||||
menuBarItemsChanged (0);
|
||||
}
|
||||
|
|
@ -241,9 +189,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
MenuBarModel* currentModel;
|
||||
uint32 lastUpdateTime;
|
||||
|
||||
void addMenuItem (PopupMenu::MenuItemIterator& iter, NSMenu* menuToAddTo,
|
||||
const int topLevelMenuId, const int topLevelIndex)
|
||||
{
|
||||
|
|
@ -333,9 +278,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
JuceMenuCallback* callback;
|
||||
private:
|
||||
static JuceMainMenuHandler* instance;
|
||||
|
||||
MenuBarModel* currentModel;
|
||||
uint32 lastUpdateTime;
|
||||
JuceMenuCallback* callback;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
NSMenu* createMenu (const PopupMenu menu,
|
||||
const String& menuName,
|
||||
const int topLevelMenuId,
|
||||
|
|
@ -354,11 +304,71 @@ private:
|
|||
[m update];
|
||||
return m;
|
||||
}
|
||||
|
||||
static NSMenuItem* findMenuItem (NSMenu* const menu, const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
for (NSInteger i = [menu numberOfItems]; --i >= 0;)
|
||||
{
|
||||
NSMenuItem* m = [menu itemAtIndex: i];
|
||||
if ([m tag] == info.commandID)
|
||||
return m;
|
||||
|
||||
if ([m submenu] != 0)
|
||||
{
|
||||
NSMenuItem* found = findMenuItem ([m submenu], info);
|
||||
if (found != 0)
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flashMenuBar (NSMenu* menu)
|
||||
{
|
||||
if ([[menu title] isEqualToString: @"Apple"])
|
||||
return;
|
||||
|
||||
[menu retain];
|
||||
|
||||
const unichar f35Key = NSF35FunctionKey;
|
||||
NSString* f35String = [NSString stringWithCharacters: &f35Key length: 1];
|
||||
|
||||
NSMenuItem* item = [[NSMenuItem alloc] initWithTitle: @"x"
|
||||
action: nil
|
||||
keyEquivalent: f35String];
|
||||
[item setTarget: nil];
|
||||
[menu insertItem: item atIndex: [menu numberOfItems]];
|
||||
[item release];
|
||||
|
||||
if ([menu indexOfItem: item] >= 0)
|
||||
{
|
||||
NSEvent* f35Event = [NSEvent keyEventWithType: NSKeyDown
|
||||
location: NSZeroPoint
|
||||
modifierFlags: NSCommandKeyMask
|
||||
timestamp: 0
|
||||
windowNumber: 0
|
||||
context: [NSGraphicsContext currentContext]
|
||||
characters: f35String
|
||||
charactersIgnoringModifiers: f35String
|
||||
isARepeat: NO
|
||||
keyCode: 0];
|
||||
|
||||
[menu performKeyEquivalent: f35Event];
|
||||
|
||||
if ([menu indexOfItem: item] >= 0)
|
||||
[menu removeItem: item]; // (this throws if the item isn't actually in the menu)
|
||||
}
|
||||
|
||||
[menu release];
|
||||
}
|
||||
};
|
||||
|
||||
JuceMainMenuHandler* JuceMainMenuHandler::instance = 0;
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
||||
//==============================================================================
|
||||
@implementation JuceMenuCallback
|
||||
|
||||
- (JuceMenuCallback*) initWithOwner: (JuceMainMenuHandler*) owner_
|
||||
|
|
@ -412,10 +422,8 @@ END_JUCE_NAMESPACE
|
|||
|
||||
- (void) menuNeedsUpdate: (NSMenu*) menu;
|
||||
{
|
||||
(void) menu;
|
||||
|
||||
if (JuceMainMenuHandler::instance != 0)
|
||||
JuceMainMenuHandler::instance->updateMenus();
|
||||
JuceMainMenuHandler::instance->updateMenus (menu);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -125,6 +125,12 @@ public:
|
|||
jassertfalse;
|
||||
}
|
||||
|
||||
float getScaleFactor()
|
||||
{
|
||||
jassertfalse; //xxx
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
currentState->clipToRectangle (r);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue