Browse Source

Altered the way MessageManagerLocks are applied internally; tweaked ResamplingAudioSource to avoid a DC offset condition; changed AudioUnitPluginFormat to handle null-pointers; added a method to get all the currently modal components as well as just the most recent; changed AlertWindow to allow more customisation by the look and feel; added a few handy methods to Rectangle;

tags/2021-05-28
jules 16 years ago
parent
commit
975851d31c
27 changed files with 726 additions and 310 deletions
  1. +5
    -4
      build/macosx/Juce.xcodeproj/project.pbxproj
  2. +1
    -0
      build/macosx/platform_specific_code/juce_mac_AppleRemote.mm
  3. +19
    -5
      build/macosx/platform_specific_code/juce_mac_Fonts.mm
  4. +5
    -0
      build/macosx/platform_specific_code/juce_mac_MainMenu.mm
  5. +15
    -5
      build/macosx/platform_specific_code/juce_mac_MessageManager.mm
  6. +34
    -0
      build/macosx/platform_specific_code/juce_mac_NSViewComponentPeer.mm
  7. +2
    -0
      build/macosx/platform_specific_code/juce_mac_WebBrowserComponent.mm
  8. +2
    -0
      build/win32/platform_specific_code/juce_win32_Messaging.cpp
  9. +283
    -138
      juce_amalgamated.cpp
  10. +76
    -16
      juce_amalgamated.h
  11. +15
    -4
      src/juce_appframework/application/juce_Application.cpp
  12. +2
    -2
      src/juce_appframework/audio/audio_sources/juce_ResamplingAudioSource.cpp
  13. +31
    -12
      src/juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.mm
  14. +2
    -1
      src/juce_appframework/events/juce_MessageManager.cpp
  15. +3
    -2
      src/juce_appframework/events/juce_MessageManager.h
  16. +2
    -0
      src/juce_appframework/gui/components/controls/juce_TreeView.cpp
  17. +7
    -2
      src/juce_appframework/gui/components/juce_Component.cpp
  18. +15
    -4
      src/juce_appframework/gui/components/juce_Component.h
  19. +1
    -0
      src/juce_appframework/gui/components/keyboard/juce_KeyPressMappingSet.cpp
  20. +84
    -58
      src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp
  21. +11
    -1
      src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h
  22. +27
    -40
      src/juce_appframework/gui/components/windows/juce_AlertWindow.cpp
  23. +23
    -6
      src/juce_appframework/gui/components/windows/juce_AlertWindow.h
  24. +14
    -9
      src/juce_appframework/gui/components/windows/juce_ThreadWithProgressWindow.cpp
  25. +1
    -1
      src/juce_appframework/gui/components/windows/juce_ThreadWithProgressWindow.h
  26. +24
    -0
      src/juce_appframework/gui/graphics/geometry/juce_Rectangle.cpp
  27. +22
    -0
      src/juce_appframework/gui/graphics/geometry/juce_Rectangle.h

+ 5
- 4
build/macosx/Juce.xcodeproj/project.pbxproj View File

@@ -716,7 +716,7 @@
84A06BAA09CAD6A3006A43BD /* juce_AudioIODevice.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_AudioIODevice.cpp; sourceTree = "<group>"; }; 84A06BAA09CAD6A3006A43BD /* juce_AudioIODevice.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_AudioIODevice.cpp; sourceTree = "<group>"; };
84A06BAB09CAD6A3006A43BD /* juce_AudioIODeviceType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_AudioIODeviceType.cpp; sourceTree = "<group>"; }; 84A06BAB09CAD6A3006A43BD /* juce_AudioIODeviceType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_AudioIODeviceType.cpp; sourceTree = "<group>"; };
84A06BAC09CAD6A3006A43BD /* juce_AudioIODeviceType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_AudioIODeviceType.h; sourceTree = "<group>"; }; 84A06BAC09CAD6A3006A43BD /* juce_AudioIODeviceType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_AudioIODeviceType.h; sourceTree = "<group>"; };
84A4883508A22E4900752A2B /* juce_Application.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Application.cpp; path = ../../src/juce_appframework/application/juce_Application.cpp; sourceTree = SOURCE_ROOT; };
84A4883508A22E4900752A2B /* juce_Application.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 2; name = juce_Application.cpp; path = ../../src/juce_appframework/application/juce_Application.cpp; sourceTree = SOURCE_ROOT; };
84A4883608A22E4900752A2B /* juce_Application.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_Application.h; path = ../../src/juce_appframework/application/juce_Application.h; sourceTree = SOURCE_ROOT; }; 84A4883608A22E4900752A2B /* juce_Application.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_Application.h; path = ../../src/juce_appframework/application/juce_Application.h; sourceTree = SOURCE_ROOT; };
84A4883708A22E4900752A2B /* juce_DeletedAtShutdown.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DeletedAtShutdown.cpp; path = ../../src/juce_appframework/application/juce_DeletedAtShutdown.cpp; sourceTree = SOURCE_ROOT; }; 84A4883708A22E4900752A2B /* juce_DeletedAtShutdown.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DeletedAtShutdown.cpp; path = ../../src/juce_appframework/application/juce_DeletedAtShutdown.cpp; sourceTree = SOURCE_ROOT; };
84A4883808A22E4900752A2B /* juce_DeletedAtShutdown.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_DeletedAtShutdown.h; path = ../../src/juce_appframework/application/juce_DeletedAtShutdown.h; sourceTree = SOURCE_ROOT; }; 84A4883808A22E4900752A2B /* juce_DeletedAtShutdown.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_DeletedAtShutdown.h; path = ../../src/juce_appframework/application/juce_DeletedAtShutdown.h; sourceTree = SOURCE_ROOT; };
@@ -1080,13 +1080,13 @@
84E024DE0E94028C003E41AF /* juce_mac_CoreMidi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = juce_mac_CoreMidi.cpp; sourceTree = "<group>"; }; 84E024DE0E94028C003E41AF /* juce_mac_CoreMidi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = juce_mac_CoreMidi.cpp; sourceTree = "<group>"; };
84E024DF0E94028C003E41AF /* juce_mac_FileChooser.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_FileChooser.mm; sourceTree = "<group>"; }; 84E024DF0E94028C003E41AF /* juce_mac_FileChooser.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_FileChooser.mm; sourceTree = "<group>"; };
84E024E00E94028C003E41AF /* juce_mac_Files.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_Files.mm; sourceTree = "<group>"; }; 84E024E00E94028C003E41AF /* juce_mac_Files.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_Files.mm; sourceTree = "<group>"; };
84E024E10E94028C003E41AF /* juce_mac_Fonts.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_Fonts.mm; sourceTree = "<group>"; };
84E024E10E94028C003E41AF /* juce_mac_Fonts.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 2; path = juce_mac_Fonts.mm; sourceTree = "<group>"; };
84E024E20E94028C003E41AF /* juce_mac_MainMenu.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_MainMenu.mm; sourceTree = "<group>"; }; 84E024E20E94028C003E41AF /* juce_mac_MainMenu.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_MainMenu.mm; sourceTree = "<group>"; };
84E024E30E94028C003E41AF /* juce_mac_MessageManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_MessageManager.mm; sourceTree = "<group>"; };
84E024E30E94028C003E41AF /* juce_mac_MessageManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 2; path = juce_mac_MessageManager.mm; sourceTree = "<group>"; };
84E024E40E94028C003E41AF /* juce_mac_MouseCursor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_MouseCursor.mm; sourceTree = "<group>"; }; 84E024E40E94028C003E41AF /* juce_mac_MouseCursor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_MouseCursor.mm; sourceTree = "<group>"; };
84E024E50E94028C003E41AF /* juce_mac_NamedPipe.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = juce_mac_NamedPipe.cpp; sourceTree = "<group>"; }; 84E024E50E94028C003E41AF /* juce_mac_NamedPipe.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = juce_mac_NamedPipe.cpp; sourceTree = "<group>"; };
84E024E60E94028C003E41AF /* juce_mac_NativeCode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_NativeCode.mm; sourceTree = "<group>"; }; 84E024E60E94028C003E41AF /* juce_mac_NativeCode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_NativeCode.mm; sourceTree = "<group>"; };
84E024E80E94028C003E41AF /* juce_mac_Network.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_Network.mm; sourceTree = "<group>"; };
84E024E80E94028C003E41AF /* juce_mac_Network.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 2; path = juce_mac_Network.mm; sourceTree = "<group>"; };
84E024E90E94028C003E41AF /* juce_mac_NSViewComponent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_NSViewComponent.mm; sourceTree = "<group>"; }; 84E024E90E94028C003E41AF /* juce_mac_NSViewComponent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_mac_NSViewComponent.mm; sourceTree = "<group>"; };
84E024EA0E94028C003E41AF /* juce_mac_NSViewComponentPeer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 2; path = juce_mac_NSViewComponentPeer.mm; sourceTree = "<group>"; }; 84E024EA0E94028C003E41AF /* juce_mac_NSViewComponentPeer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 2; path = juce_mac_NSViewComponentPeer.mm; sourceTree = "<group>"; };
84E024EB0E94028C003E41AF /* juce_mac_OpenGLComponent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 2; path = juce_mac_OpenGLComponent.mm; sourceTree = "<group>"; }; 84E024EB0E94028C003E41AF /* juce_mac_OpenGLComponent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 2; path = juce_mac_OpenGLComponent.mm; sourceTree = "<group>"; };
@@ -1210,6 +1210,7 @@
84A4899708A22E4A00752A2B /* juce_core */, 84A4899708A22E4A00752A2B /* juce_core */,
84A4881C08A22E2400752A2B /* mac specific code */, 84A4881C08A22E2400752A2B /* mac specific code */,
); );
lineEnding = 2;
name = Source; name = Source;
sourceTree = "<group>"; sourceTree = "<group>";
}; };


+ 1
- 0
build/macosx/platform_specific_code/juce_mac_AppleRemote.mm View File

@@ -265,6 +265,7 @@ void AppleRemoteDevice::handleCallbackInternal()
{ {
if (strcmp (cookies, buttonPatterns + i) == 0) if (strcmp (cookies, buttonPatterns + i) == 0)
{ {
const MessageManagerLock mml;
buttonPressed ((ButtonType) buttonNum, totalValues > 0); buttonPressed ((ButtonType) buttonNum, totalValues > 0);
break; break;
} }


+ 19
- 5
build/macosx/platform_specific_code/juce_mac_Fonts.mm View File

@@ -44,6 +44,7 @@ public:
bool isBold, isItalic; bool isBold, isItalic;
float fontSize, totalSize, ascent; float fontSize, totalSize, ascent;
int refCount; int refCount;
NSMutableDictionary* attributes;
FontHelper (const String& name_, FontHelper (const String& name_,
const bool bold_, const bool bold_,
@@ -56,10 +57,23 @@ public:
fontSize (size_), fontSize (size_),
refCount (1) refCount (1)
{ {
attributes = [[NSMutableDictionary dictionaryWithObject: [NSNumber numberWithInt: 0]
forKey: NSLigatureAttributeName] retain];
font = [NSFont fontWithName: juceStringToNS (name_) size: size_]; font = [NSFont fontWithName: juceStringToNS (name_) size: size_];
if (italic_) if (italic_)
font = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSItalicFontMask];
{
NSFont* newFont = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSItalicFontMask];
if (newFont == font)
{
// couldn't find an italic version, so fake it with obliqueness..
[attributes setObject: [NSNumber numberWithFloat: 0.16] forKey: NSObliquenessAttributeName];
}
font = newFont;
}
if (bold_) if (bold_)
font = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSBoldFontMask]; font = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSBoldFontMask];
@@ -73,6 +87,7 @@ public:
~FontHelper() ~FontHelper()
{ {
[font release]; [font release];
[attributes release];
} }
bool getPathAndKerning (const juce_wchar char1, bool getPathAndKerning (const juce_wchar char1,
@@ -90,10 +105,9 @@ public:
String chars; String chars;
chars << ' ' << char1 << char2; chars << ' ' << char1 << char2;
NSTextStorage* textStorage = [[[NSTextStorage alloc]
initWithString: juceStringToNS (chars)
attributes: [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: 0]
forKey: NSLigatureAttributeName]] autorelease];
NSTextStorage* textStorage = [[[NSTextStorage alloc] initWithString: juceStringToNS (chars)
attributes: attributes] autorelease];
NSLayoutManager* layoutManager = [[[NSLayoutManager alloc] init] autorelease]; NSLayoutManager* layoutManager = [[[NSLayoutManager alloc] init] autorelease];
NSTextContainer* textContainer = [[[NSTextContainer alloc] init] autorelease]; NSTextContainer* textContainer = [[[NSTextContainer alloc] init] autorelease];
[layoutManager addTextContainer: textContainer]; [layoutManager addTextContainer: textContainer];


+ 5
- 0
build/macosx/platform_specific_code/juce_mac_MainMenu.mm View File

@@ -212,11 +212,16 @@ public:
void updateMenus() void updateMenus()
{ {
if (Time::getMillisecondCounter() > lastUpdateTime + 500) if (Time::getMillisecondCounter() > lastUpdateTime + 500)
{
const MessageManagerLock mml;
menuBarItemsChanged (0); menuBarItemsChanged (0);
}
} }
void invoke (const int commandId, ApplicationCommandManager* const commandManager, const int topLevelIndex) const void invoke (const int commandId, ApplicationCommandManager* const commandManager, const int topLevelIndex) const
{ {
const MessageManagerLock mml;
if (currentModel != 0) if (currentModel != 0)
{ {
if (commandManager != 0) if (commandManager != 0)


+ 15
- 5
build/macosx/platform_specific_code/juce_mac_MessageManager.mm View File

@@ -61,6 +61,7 @@ public:
{ {
if (JUCEApplication::getInstance() != 0) if (JUCEApplication::getInstance() != 0)
{ {
const MessageManagerLock mml;
JUCEApplication::getInstance()->systemRequestedQuit(); JUCEApplication::getInstance()->systemRequestedQuit();
return NSTerminateCancel; return NSTerminateCancel;
} }
@@ -72,6 +73,7 @@ public:
{ {
if (JUCEApplication::getInstance() != 0) if (JUCEApplication::getInstance() != 0)
{ {
const MessageManagerLock mml;
JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce (filename)); JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce (filename));
return YES; return YES;
} }
@@ -86,19 +88,31 @@ public:
files.add (nsStringToJuce ((NSString*) [filenames objectAtIndex: i])); files.add (nsStringToJuce ((NSString*) [filenames objectAtIndex: i]));
if (files.size() > 0 && JUCEApplication::getInstance() != 0) if (files.size() > 0 && JUCEApplication::getInstance() != 0)
{
const MessageManagerLock mml;
JUCEApplication::getInstance()->anotherInstanceStarted (files.joinIntoString (T(" "))); JUCEApplication::getInstance()->anotherInstanceStarted (files.joinIntoString (T(" ")));
}
} }
virtual void focusChanged() virtual void focusChanged()
{ {
const MessageManagerLock mml;
juce_HandleProcessFocusChange(); juce_HandleProcessFocusChange();
} }
virtual void deliverMessage (void* message) virtual void deliverMessage (void* message)
{ {
// no need for an mm lock here - deliverMessage locks it
MessageManager::getInstance()->deliverMessage (message); MessageManager::getInstance()->deliverMessage (message);
} }
virtual void performCallback (CallbackMessagePayload* pl)
{
const MessageManagerLock mml;
pl->result = (*pl->function) (pl->parameter);
pl->hasBeenExecuted = true;
}
virtual void deleteSelf() virtual void deleteSelf()
{ {
delete this; delete this;
@@ -227,10 +241,7 @@ static bool flushingMessages = false;
CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes]; CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes];
if (pl != 0) if (pl != 0)
{
pl->result = (*pl->function) (pl->parameter);
pl->hasBeenExecuted = true;
}
redirector->performCallback (pl);
} }
else else
{ {
@@ -249,7 +260,6 @@ static JuceAppDelegate* juceAppDelegate = 0;
void MessageManager::runDispatchLoop() void MessageManager::runDispatchLoop()
{ {
const ScopedAutoReleasePool pool; const ScopedAutoReleasePool pool;
MessageManagerLock mml;
// must only be called by the message thread! // must only be called by the message thread!
jassert (isThisTheMessageThread()); jassert (isThisTheMessageThread());


+ 34
- 0
build/macosx/platform_specific_code/juce_mac_NSViewComponentPeer.mm View File

@@ -100,6 +100,7 @@ END_JUCE_NAMESPACE
- (void) setOwner: (NSViewComponentPeer*) owner; - (void) setOwner: (NSViewComponentPeer*) owner;
- (BOOL) canBecomeKeyWindow; - (BOOL) canBecomeKeyWindow;
- (void) becomeKeyWindow;
- (BOOL) windowShouldClose: (id) window; - (BOOL) windowShouldClose: (id) window;
- (NSRect) constrainFrameRect: (NSRect) frameRect toScreen: (NSScreen*) screen; - (NSRect) constrainFrameRect: (NSRect) frameRect toScreen: (NSScreen*) screen;
- (NSSize) windowWillResize: (NSWindow*) window toSize: (NSSize) proposedFrameSize; - (NSSize) windowWillResize: (NSWindow*) window toSize: (NSSize) proposedFrameSize;
@@ -428,6 +429,14 @@ END_JUCE_NAMESPACE
return owner != 0 && owner->canBecomeKeyWindow(); return owner != 0 && owner->canBecomeKeyWindow();
} }
- (void) becomeKeyWindow
{
[super becomeKeyWindow];
if (owner != 0)
owner->grabFocus();
}
- (BOOL) windowShouldClose: (id) window - (BOOL) windowShouldClose: (id) window
{ {
return owner == 0 || owner->windowShouldClose(); return owner == 0 || owner->windowShouldClose();
@@ -909,6 +918,8 @@ NSRect NSViewComponentPeer::constrainRect (NSRect r)
{ {
if (constrainer != 0) if (constrainer != 0)
{ {
const MessageManagerLock mml;
NSRect current = [window frame]; NSRect current = [window frame];
current.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - current.origin.y - current.size.height; current.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - current.origin.y - current.size.height;
@@ -1124,6 +1135,8 @@ void NSViewComponentPeer::grabFocus()
{ {
[window makeKeyWindow]; [window makeKeyWindow];
[window makeFirstResponder: view]; [window makeFirstResponder: view];
viewFocusGain();
} }
} }
@@ -1133,6 +1146,8 @@ void NSViewComponentPeer::textInputRequired (int /*x*/, int /*y*/)
bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown) bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown)
{ {
const MessageManagerLock mml;
String unicode (nsStringToJuce ([ev characters])); String unicode (nsStringToJuce ([ev characters]));
String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers])); String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers]));
int keyCode = getKeyCodeFromEvent (ev); int keyCode = getKeyCodeFromEvent (ev);
@@ -1172,6 +1187,7 @@ bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown)
bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev) bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateKeysDown (ev, true); updateKeysDown (ev, true);
bool used = handleKeyEvent (ev, true); bool used = handleKeyEvent (ev, true);
@@ -1187,12 +1203,14 @@ bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev)
bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev) bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateKeysDown (ev, false); updateKeysDown (ev, false);
return handleKeyEvent (ev, false); return handleKeyEvent (ev, false);
} }
void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev) void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
handleModifierKeysChange(); handleModifierKeysChange();
} }
@@ -1200,6 +1218,7 @@ void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev)
#if MACOS_10_4_OR_EARLIER #if MACOS_10_4_OR_EARLIER
bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev) bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev)
{ {
const MessageManagerLock mml;
if ([ev type] == NSKeyDown) if ([ev type] == NSKeyDown)
return redirectKeyDown (ev); return redirectKeyDown (ev);
else if ([ev type] == NSKeyUp) else if ([ev type] == NSKeyUp)
@@ -1212,6 +1231,7 @@ bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev)
//============================================================================== //==============================================================================
void NSViewComponentPeer::redirectMouseDown (NSEvent* ev) void NSViewComponentPeer::redirectMouseDown (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]); currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]);
int x, y; int x, y;
@@ -1222,6 +1242,7 @@ void NSViewComponentPeer::redirectMouseDown (NSEvent* ev)
void NSViewComponentPeer::redirectMouseUp (NSEvent* ev) void NSViewComponentPeer::redirectMouseUp (NSEvent* ev)
{ {
const MessageManagerLock mml;
const int oldMods = currentModifiers; const int oldMods = currentModifiers;
updateModifiers (ev); updateModifiers (ev);
currentModifiers &= ~getModifierForButtonNumber ([ev buttonNumber]); currentModifiers &= ~getModifierForButtonNumber ([ev buttonNumber]);
@@ -1233,6 +1254,7 @@ void NSViewComponentPeer::redirectMouseUp (NSEvent* ev)
void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev) void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]); currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]);
int x, y; int x, y;
@@ -1243,6 +1265,7 @@ void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev)
void NSViewComponentPeer::redirectMouseMove (NSEvent* ev) void NSViewComponentPeer::redirectMouseMove (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
int x, y; int x, y;
getMousePos (ev, view, x, y); getMousePos (ev, view, x, y);
@@ -1252,6 +1275,7 @@ void NSViewComponentPeer::redirectMouseMove (NSEvent* ev)
void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev) void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
int x, y; int x, y;
getMousePos (ev, view, x, y); getMousePos (ev, view, x, y);
@@ -1261,6 +1285,7 @@ void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev)
void NSViewComponentPeer::redirectMouseExit (NSEvent* ev) void NSViewComponentPeer::redirectMouseExit (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
int x, y; int x, y;
getMousePos (ev, view, x, y); getMousePos (ev, view, x, y);
@@ -1270,6 +1295,7 @@ void NSViewComponentPeer::redirectMouseExit (NSEvent* ev)
void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev) void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
handleMouseWheel (roundFloatToInt ([ev deltaX] * 10.0f), handleMouseWheel (roundFloatToInt ([ev deltaX] * 10.0f),
@@ -1280,6 +1306,8 @@ void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev)
//============================================================================== //==============================================================================
BOOL NSViewComponentPeer::sendDragCallback (int type, id <NSDraggingInfo> sender) BOOL NSViewComponentPeer::sendDragCallback (int type, id <NSDraggingInfo> sender)
{ {
const MessageManagerLock mml;
NSString* bestType NSString* bestType
= [[sender draggingPasteboard] availableTypeFromArray: [view getSupportedDragTypes]]; = [[sender draggingPasteboard] availableTypeFromArray: [view getSupportedDragTypes]];
@@ -1330,6 +1358,7 @@ void NSViewComponentPeer::drawRect (NSRect r)
if (r.size.width < 1.0f || r.size.height < 1.0f) if (r.size.width < 1.0f || r.size.height < 1.0f)
return; return;
const MessageManagerLock mml;
const float y = [view frame].size.height - (r.origin.y + r.size.height); const float y = [view frame].size.height - (r.origin.y + r.size.height);
JuceNSImage temp ((int) (r.size.width + 0.5f), JuceNSImage temp ((int) (r.size.width + 0.5f),
@@ -1363,6 +1392,8 @@ void NSViewComponentPeer::drawRect (NSRect r)
bool NSViewComponentPeer::canBecomeKeyWindow() bool NSViewComponentPeer::canBecomeKeyWindow()
{ {
const MessageManagerLock mml;
// If running as a plugin, let the component decide whether it's going to allow the window to get focused. // If running as a plugin, let the component decide whether it's going to allow the window to get focused.
return JUCEApplication::getInstance() != 0 return JUCEApplication::getInstance() != 0
|| (isValidPeer (this) && getComponent()->getWantsKeyboardFocus()); || (isValidPeer (this) && getComponent()->getWantsKeyboardFocus());
@@ -1370,6 +1401,8 @@ bool NSViewComponentPeer::canBecomeKeyWindow()
bool NSViewComponentPeer::windowShouldClose() bool NSViewComponentPeer::windowShouldClose()
{ {
const MessageManagerLock mml;
if (! isValidPeer (this)) if (! isValidPeer (this))
return YES; return YES;
@@ -1379,6 +1412,7 @@ bool NSViewComponentPeer::windowShouldClose()
void NSViewComponentPeer::redirectMovedOrResized() void NSViewComponentPeer::redirectMovedOrResized()
{ {
const MessageManagerLock mml;
handleMovedOrResized(); handleMovedOrResized();
} }


+ 2
- 0
build/macosx/platform_specific_code/juce_mac_WebBrowserComponent.mm View File

@@ -69,6 +69,8 @@ END_JUCE_NAMESPACE
{ {
NSURL* url = [actionInformation valueForKey: @"WebActionOriginalURLKey"]; NSURL* url = [actionInformation valueForKey: @"WebActionOriginalURLKey"];
const MessageManagerLock mml;
if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString]))) if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString])))
[listener use]; [listener use];
else else


+ 2
- 0
build/win32/platform_specific_code/juce_win32_Messaging.cpp View File

@@ -101,6 +101,8 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages
if (GetMessage (&m, (HWND) 0, 0, 0) > 0) if (GetMessage (&m, (HWND) 0, 0, 0) > 0)
{ {
const MessageManagerLock mml;
if (m.message == specialId if (m.message == specialId
&& m.hwnd == juce_messageWindowHandle) && m.hwnd == juce_messageWindowHandle)
{ {


+ 283
- 138
juce_amalgamated.cpp View File

@@ -15680,8 +15680,12 @@ int JUCEApplication::main (String& commandLine, JUCEApplication* const app)
{ {
juce_setCurrentThreadName ("Juce Message Thread"); juce_setCurrentThreadName ("Juce Message Thread");


// let the app do its setting-up..
app->initialise (app->commandLineParameters);
{
const MessageManagerLock mml;

// let the app do its setting-up..
app->initialise (app->commandLineParameters);
}


// register for broadcast new app messages // register for broadcast new app messages
MessageManager::getInstance()->registerBroadcastListener (app); MessageManager::getInstance()->registerBroadcastListener (app);
@@ -15728,6 +15732,7 @@ int JUCEApplication::shutdownAppAndClearUp()
JUCE_TRY JUCE_TRY
{ {
// give the app a chance to clean up.. // give the app a chance to clean up..
const MessageManagerLock mml;
app->shutdown(); app->shutdown();
} }
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS #if JUCE_CATCH_UNHANDLED_EXCEPTIONS
@@ -15824,9 +15829,15 @@ void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI()
#if JUCE_MAC #if JUCE_MAC
const ScopedAutoReleasePool pool; const ScopedAutoReleasePool pool;
#endif #endif
DeletedAtShutdown::deleteAll();
{
const MessageManagerLock mml;
DeletedAtShutdown::deleteAll();

LookAndFeel::clearDefaultLookAndFeel();
}

delete MessageManager::getInstance();


LookAndFeel::clearDefaultLookAndFeel();
shutdownJuce_NonGUI(); shutdownJuce_NonGUI();


juceInitialisedGUI = false; juceInitialisedGUI = false;
@@ -21872,7 +21883,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf


input->getNextAudioBlock (readInfo); input->getNextAudioBlock (readInfo);


if (ratio > 1.0)
if (ratio > 1.0001)
{ {
// for down-sampling, pre-apply the filter.. // for down-sampling, pre-apply the filter..


@@ -21918,7 +21929,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf
} }
} }


if (ratio < 1.0)
if (ratio < 0.9999)
{ {
// for up-sampling, apply the filter after transposing.. // for up-sampling, apply the filter after transposing..


@@ -28855,13 +28866,19 @@ OSStatus AudioUnitPluginInstance::getBeatAndTempo (Float64* outCurrentBeat, Floa


if (ph != 0 && ph->getCurrentPosition (result)) if (ph != 0 && ph->getCurrentPosition (result))
{ {
*outCurrentBeat = result.ppqPosition;
*outCurrentTempo = result.bpm;
if (outCurrentBeat != 0)
*outCurrentBeat = result.ppqPosition;

if (outCurrentTempo != 0)
*outCurrentTempo = result.bpm;
} }
else else
{ {
*outCurrentBeat = 0;
*outCurrentTempo = 120.0;
if (outCurrentBeat != 0)
*outCurrentBeat = 0;

if (outCurrentTempo != 0)
*outCurrentTempo = 120.0;
} }


return noErr; return noErr;
@@ -28877,18 +28894,31 @@ OSStatus AudioUnitPluginInstance::getMusicalTimeLocation (UInt32* outDeltaSample


if (ph != 0 && ph->getCurrentPosition (result)) if (ph != 0 && ph->getCurrentPosition (result))
{ {
*outTimeSig_Numerator = result.timeSigNumerator;
*outTimeSig_Denominator = result.timeSigDenominator;
if (outTimeSig_Numerator != 0)
*outTimeSig_Numerator = result.timeSigNumerator;


*outDeltaSampleOffsetToNextBeat = 0; //xxx
*outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong
if (outTimeSig_Denominator != 0)
*outTimeSig_Denominator = result.timeSigDenominator;

if (outDeltaSampleOffsetToNextBeat != 0)
*outDeltaSampleOffsetToNextBeat = 0; //xxx

if (outCurrentMeasureDownBeat != 0)
*outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong
} }
else else
{ {
*outDeltaSampleOffsetToNextBeat = 0;
*outTimeSig_Numerator = 4;
*outTimeSig_Denominator = 4;
*outCurrentMeasureDownBeat = 0;
if (outDeltaSampleOffsetToNextBeat != 0)
*outDeltaSampleOffsetToNextBeat = 0;

if (outTimeSig_Numerator != 0)
*outTimeSig_Numerator = 4;

if (outTimeSig_Denominator != 0)
*outTimeSig_Denominator = 4;

if (outCurrentMeasureDownBeat != 0)
*outCurrentMeasureDownBeat = 0;
} }


return noErr; return noErr;
@@ -36771,7 +36801,8 @@ MessageManager::MessageManager() throw()
quitMessagePosted (false), quitMessagePosted (false),
quitMessageReceived (false) quitMessageReceived (false)
{ {
currentLockingThreadId = messageThreadId = Thread::getCurrentThreadId();
currentLockingThreadId = 0;
messageThreadId = Thread::getCurrentThreadId();
} }


MessageManager::~MessageManager() throw() MessageManager::~MessageManager() throw()
@@ -38879,9 +38910,14 @@ bool Component::isCurrentlyBlockedByAnotherModalComponent() const throw()
&& ! mc->canModalEventBeSentToComponent (this); && ! mc->canModalEventBeSentToComponent (this);
} }


Component* JUCE_CALLTYPE Component::getCurrentlyModalComponent() throw()
int JUCE_CALLTYPE Component::getNumCurrentlyModalComponents() throw()
{
return modalComponentStack.size();
}

Component* JUCE_CALLTYPE Component::getCurrentlyModalComponent (int index) throw()
{ {
Component* const c = (Component*) modalComponentStack.getLast();
Component* const c = (Component*) (modalComponentStack [modalComponentStack.size() - index - 1]);


return c->isValidComponent() ? c : 0; return c->isValidComponent() ? c : 0;
} }
@@ -51957,7 +51993,9 @@ void TreeView::paint (Graphics& g)
void TreeView::resized() void TreeView::resized()
{ {
viewport->setBounds (0, 0, getWidth(), getHeight()); viewport->setBounds (0, 0, getWidth(), getHeight());

itemsChanged(); itemsChanged();
handleAsyncUpdate();
} }


void TreeView::moveSelectedRow (int delta) void TreeView::moveSelectedRow (int delta)
@@ -56283,6 +56321,7 @@ bool KeyPressMappingSet::keyStateChanged (Component* originatingComponent)
{ {
keyPressEntryIndex = k; keyPressEntryIndex = k;
wasDown = true; wasDown = true;
used = true;
break; break;
} }
} }
@@ -60278,78 +60317,104 @@ void LookAndFeel::changeToggleButtonWidthToFitText (ToggleButton& button)
button.getHeight()); button.getHeight());
} }


AlertWindow* LookAndFeel::createAlertWindow (const String& title,
const String& message,
const String& button1,
const String& button2,
const String& button3,
AlertWindow::AlertIconType iconType,
int numButtons,
Component* associatedComponent)
{
AlertWindow* aw = new AlertWindow (title, message, iconType);

if (numButtons == 1)
{
aw->addButton (button1, 0,
KeyPress (KeyPress::escapeKey, 0, 0),
KeyPress (KeyPress::returnKey, 0, 0));
}
else
{
const KeyPress button1ShortCut (CharacterFunctions::toLowerCase (button1[0]), 0, 0);
KeyPress button2ShortCut (CharacterFunctions::toLowerCase (button2[0]), 0, 0);
if (button1ShortCut == button2ShortCut)
button2ShortCut = KeyPress();

if (numButtons == 2)
{
aw->addButton (button1, 1, KeyPress (KeyPress::returnKey, 0, 0), button1ShortCut);
aw->addButton (button2, 0, KeyPress (KeyPress::escapeKey, 0, 0), button2ShortCut);
}
else
{
jassert (numButtons == 3);

aw->addButton (button1, 1, button1ShortCut);
aw->addButton (button2, 2, button2ShortCut);
aw->addButton (button3, 0, KeyPress (KeyPress::escapeKey, 0, 0));
}
}

return aw;
}

void LookAndFeel::drawAlertBox (Graphics& g, void LookAndFeel::drawAlertBox (Graphics& g,
AlertWindow& alert, AlertWindow& alert,
const Rectangle& textArea, const Rectangle& textArea,
TextLayout& textLayout) TextLayout& textLayout)
{ {
const int iconWidth = 80;

const Colour background (alert.findColour (AlertWindow::backgroundColourId));

g.fillAll (background);
g.fillAll (alert.findColour (AlertWindow::backgroundColourId));


int iconSpaceUsed = 0; int iconSpaceUsed = 0;
Justification alignment (Justification::horizontallyCentred); Justification alignment (Justification::horizontallyCentred);


const int iconWidth = 80;
int iconSize = jmin (iconWidth + 50, alert.getHeight() + 20); int iconSize = jmin (iconWidth + 50, alert.getHeight() + 20);


if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2) if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2)
iconSize = jmin (iconSize, textArea.getHeight() + 50); iconSize = jmin (iconSize, textArea.getHeight() + 50);


const Rectangle iconRect (iconSize / -10,
iconSize / -10,
iconSize,
iconSize);
const Rectangle iconRect (iconSize / -10, iconSize / -10,
iconSize, iconSize);


if (alert.getAlertType() == AlertWindow::QuestionIcon
|| alert.getAlertType() == AlertWindow::InfoIcon)
if (alert.getAlertType() != AlertWindow::NoIcon)
{ {
if (alert.getAlertType() == AlertWindow::InfoIcon)
g.setColour (background.overlaidWith (Colour (0x280000ff)));
Path icon;
uint32 colour;
char character;

if (alert.getAlertType() == AlertWindow::WarningIcon)
{
colour = 0x55ff5555;
character = '!';

icon.addTriangle (iconRect.getX() + iconRect.getWidth() * 0.5f, (float) iconRect.getY(),
(float) iconRect.getRight(), (float) iconRect.getBottom(),
(float) iconRect.getX(), (float) iconRect.getBottom());

icon = icon.createPathWithRoundedCorners (5.0f);
}
else else
g.setColour (background.overlaidWith (Colours::gold.darker().withAlpha (0.25f)));

g.fillEllipse ((float) iconRect.getX(),
(float) iconRect.getY(),
(float) iconRect.getWidth(),
(float) iconRect.getHeight());

g.setColour (background);
g.setFont (iconRect.getHeight() * 0.9f, Font::bold);
g.drawText ((alert.getAlertType() == AlertWindow::InfoIcon) ? "i"
: "?",
iconRect.getX(),
iconRect.getY(),
iconRect.getWidth(),
iconRect.getHeight(),
Justification::centred, false);
{
colour = alert.getAlertType() == AlertWindow::InfoIcon ? 0x605555ff : 0x40b69900;
character = alert.getAlertType() == AlertWindow::InfoIcon ? 'i' : '?';


iconSpaceUsed = iconWidth;
alignment = Justification::left;
}
else if (alert.getAlertType() == AlertWindow::WarningIcon)
{
Path p;
p.addTriangle (iconRect.getX() + iconRect.getWidth() * 0.5f,
(float) iconRect.getY(),
(float) iconRect.getRight(),
(float) iconRect.getBottom(),
(float) iconRect.getX(),
(float) iconRect.getBottom());

g.setColour (background.overlaidWith (Colour (0x33ff0000)));
g.fillPath (p.createPathWithRoundedCorners (5.0f));

g.setColour (background);
g.setFont (iconRect.getHeight() * 0.9f, Font::bold);

g.drawText (T("!"),
iconRect.getX(),
iconRect.getY(),
iconRect.getWidth(),
iconRect.getHeight() + iconRect.getHeight() / 8,
Justification::centred, false);
icon.addEllipse ((float) iconRect.getX(), (float) iconRect.getY(),
(float) iconRect.getWidth(), (float) iconRect.getHeight());
}

GlyphArrangement ga;
ga.addFittedText (Font (iconRect.getHeight() * 0.9f, Font::bold),
String::charToString (character),
(float) iconRect.getX(), (float) iconRect.getY(),
(float) iconRect.getWidth(), (float) iconRect.getHeight(),
Justification::centred, false);
ga.createPath (icon);

icon.setUsingNonZeroWinding (false);
g.setColour (Colour (colour));
g.fillPath (icon);


iconSpaceUsed = iconWidth; iconSpaceUsed = iconWidth;
alignment = Justification::left; alignment = Justification::left;
@@ -60358,10 +60423,8 @@ void LookAndFeel::drawAlertBox (Graphics& g,
g.setColour (alert.findColour (AlertWindow::textColourId)); g.setColour (alert.findColour (AlertWindow::textColourId));


textLayout.drawWithin (g, textLayout.drawWithin (g,
textArea.getX() + iconSpaceUsed,
textArea.getY(),
textArea.getWidth() - iconSpaceUsed,
textArea.getHeight(),
textArea.getX() + iconSpaceUsed, textArea.getY(),
textArea.getWidth() - iconSpaceUsed, textArea.getHeight(),
alignment.getFlags() | Justification::top); alignment.getFlags() | Justification::top);


g.setColour (alert.findColour (AlertWindow::outlineColourId)); g.setColour (alert.findColour (AlertWindow::outlineColourId));
@@ -71264,18 +71327,17 @@ private:


AlertWindow::AlertWindow (const String& title, AlertWindow::AlertWindow (const String& title,
const String& message, const String& message,
AlertIconType iconType)
AlertIconType iconType,
Component* associatedComponent_)
: TopLevelWindow (title, true), : TopLevelWindow (title, true),
alertIconType (iconType)
alertIconType (iconType),
associatedComponent (associatedComponent_)
{ {
if (message.isEmpty()) if (message.isEmpty())
text = T(" "); // to force an update if the message is empty text = T(" "); // to force an update if the message is empty


setMessage (message); setMessage (message);


#if JUCE_MAC
setAlwaysOnTop (true);
#else
for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;)
{ {
Component* const c = Desktop::getInstance().getComponent (i); Component* const c = Desktop::getInstance().getComponent (i);
@@ -71286,7 +71348,6 @@ AlertWindow::AlertWindow (const String& title,
break; break;
} }
} }
#endif


lookAndFeelChanged(); lookAndFeelChanged();


@@ -71634,7 +71695,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)


if (! isVisible()) if (! isVisible())
{ {
centreAroundComponent (0, w, h);
centreAroundComponent (associatedComponent, w, h);
} }
else else
{ {
@@ -71751,7 +71812,7 @@ void AlertWindow::lookAndFeelChanged()
const int flags = getLookAndFeel().getAlertBoxWindowFlags(); const int flags = getLookAndFeel().getAlertBoxWindowFlags();


setUsingNativeTitleBar ((flags & ComponentPeer::windowHasTitleBar) != 0); setUsingNativeTitleBar ((flags & ComponentPeer::windowHasTitleBar) != 0);
setDropShadowEnabled ((flags & ComponentPeer::windowHasDropShadow) != 0);
setDropShadowEnabled (isOpaque() && (flags & ComponentPeer::windowHasDropShadow) != 0);
} }


int AlertWindow::getDesktopWindowStyleFlags() const int AlertWindow::getDesktopWindowStyleFlags() const
@@ -71764,6 +71825,7 @@ struct AlertWindowInfo
String title, message, button1, button2, button3; String title, message, button1, button2, button3;
AlertWindow::AlertIconType iconType; AlertWindow::AlertIconType iconType;
int numButtons; int numButtons;
Component* associatedComponent;


int run() const int run() const
{ {
@@ -71774,37 +71836,19 @@ struct AlertWindowInfo
private: private:
int show() const int show() const
{ {
AlertWindow aw (title, message, iconType);
jassert (associatedComponent == 0 || associatedComponent->isValidComponent()); // has your comp been deleted?


if (numButtons == 1)
{
aw.addButton (button1, 0,
KeyPress (KeyPress::escapeKey, 0, 0),
KeyPress (KeyPress::returnKey, 0, 0));
}
else
{
const KeyPress button1ShortCut (CharacterFunctions::toLowerCase (button1[0]), 0, 0);
KeyPress button2ShortCut (CharacterFunctions::toLowerCase (button2[0]), 0, 0);
if (button1ShortCut == button2ShortCut)
button2ShortCut = KeyPress();
LookAndFeel& lf = associatedComponent->isValidComponent() ? associatedComponent->getLookAndFeel()
: LookAndFeel::getDefaultLookAndFeel();


if (numButtons == 2)
{
aw.addButton (button1, 1, KeyPress (KeyPress::returnKey, 0, 0), button1ShortCut);
aw.addButton (button2, 0, KeyPress (KeyPress::escapeKey, 0, 0), button2ShortCut);
}
else
{
jassert (numButtons == 3);
Component* const alertBox = lf.createAlertWindow (title, message, button1, button2, button3,
iconType, numButtons, associatedComponent);


aw.addButton (button1, 1, button1ShortCut);
aw.addButton (button2, 2, button2ShortCut);
aw.addButton (button3, 0, KeyPress (KeyPress::escapeKey, 0, 0));
}
}
jassert (alertBox != 0); // you have to return one of these!


return aw.runModalLoop();
const int result = alertBox->runModalLoop();
delete alertBox;
return result;
} }


static void* showCallback (void* userData) static void* showCallback (void* userData)
@@ -71816,7 +71860,8 @@ private:
void AlertWindow::showMessageBox (AlertIconType iconType, void AlertWindow::showMessageBox (AlertIconType iconType,
const String& title, const String& title,
const String& message, const String& message,
const String& buttonText)
const String& buttonText,
Component* associatedComponent)
{ {
AlertWindowInfo info; AlertWindowInfo info;
info.title = title; info.title = title;
@@ -71824,6 +71869,7 @@ void AlertWindow::showMessageBox (AlertIconType iconType,
info.button1 = buttonText.isEmpty() ? TRANS("ok") : buttonText; info.button1 = buttonText.isEmpty() ? TRANS("ok") : buttonText;
info.iconType = iconType; info.iconType = iconType;
info.numButtons = 1; info.numButtons = 1;
info.associatedComponent = associatedComponent;


info.run(); info.run();
} }
@@ -71832,7 +71878,8 @@ bool AlertWindow::showOkCancelBox (AlertIconType iconType,
const String& title, const String& title,
const String& message, const String& message,
const String& button1Text, const String& button1Text,
const String& button2Text)
const String& button2Text,
Component* associatedComponent)
{ {
AlertWindowInfo info; AlertWindowInfo info;
info.title = title; info.title = title;
@@ -71841,6 +71888,7 @@ bool AlertWindow::showOkCancelBox (AlertIconType iconType,
info.button2 = button2Text.isEmpty() ? TRANS("cancel") : button2Text; info.button2 = button2Text.isEmpty() ? TRANS("cancel") : button2Text;
info.iconType = iconType; info.iconType = iconType;
info.numButtons = 2; info.numButtons = 2;
info.associatedComponent = associatedComponent;


return info.run() != 0; return info.run() != 0;
} }
@@ -71850,7 +71898,8 @@ int AlertWindow::showYesNoCancelBox (AlertIconType iconType,
const String& message, const String& message,
const String& button1Text, const String& button1Text,
const String& button2Text, const String& button2Text,
const String& button3Text)
const String& button3Text,
Component* associatedComponent)
{ {
AlertWindowInfo info; AlertWindowInfo info;
info.title = title; info.title = title;
@@ -71860,6 +71909,7 @@ int AlertWindow::showYesNoCancelBox (AlertIconType iconType,
info.button3 = button3Text.isEmpty() ? TRANS("cancel") : button3Text; info.button3 = button3Text.isEmpty() ? TRANS("cancel") : button3Text;
info.iconType = iconType; info.iconType = iconType;
info.numButtons = 3; info.numButtons = 3;
info.associatedComponent = associatedComponent;


return info.run(); return info.run();
} }
@@ -73672,19 +73722,23 @@ ThreadWithProgressWindow::ThreadWithProgressWindow (const String& title,
const String& cancelButtonText) const String& cancelButtonText)
: Thread ("Juce Progress Window"), : Thread ("Juce Progress Window"),
progress (0.0), progress (0.0),
alertWindow (title, String::empty, AlertWindow::NoIcon),
timeOutMsWhenCancelling (timeOutMsWhenCancelling_) timeOutMsWhenCancelling (timeOutMsWhenCancelling_)
{ {
alertWindow = LookAndFeel::getDefaultLookAndFeel()
.createAlertWindow (title, String::empty, cancelButtonText, String::empty, String::empty,
AlertWindow::NoIcon, 1, 0);

if (hasProgressBar) if (hasProgressBar)
alertWindow.addProgressBarComponent (progress);
alertWindow->addProgressBarComponent (progress);


if (hasCancelButton) if (hasCancelButton)
alertWindow.addButton (cancelButtonText, 1);
alertWindow->addButton (cancelButtonText, 1);
} }


ThreadWithProgressWindow::~ThreadWithProgressWindow() ThreadWithProgressWindow::~ThreadWithProgressWindow()
{ {
stopThread (timeOutMsWhenCancelling); stopThread (timeOutMsWhenCancelling);
delete alertWindow;
} }


bool ThreadWithProgressWindow::runThread (const int priority) bool ThreadWithProgressWindow::runThread (const int priority)
@@ -73694,14 +73748,14 @@ bool ThreadWithProgressWindow::runThread (const int priority)


{ {
const ScopedLock sl (messageLock); const ScopedLock sl (messageLock);
alertWindow.setMessage (message);
alertWindow->setMessage (message);
} }


const bool wasCancelled = alertWindow.runModalLoop() != 0;
const bool wasCancelled = alertWindow->runModalLoop() != 0;


stopThread (timeOutMsWhenCancelling); stopThread (timeOutMsWhenCancelling);


alertWindow.setVisible (false);
alertWindow->setVisible (false);


return ! wasCancelled; return ! wasCancelled;
} }
@@ -73722,13 +73776,13 @@ void ThreadWithProgressWindow::timerCallback()
if (! isThreadRunning()) if (! isThreadRunning())
{ {
// thread has finished normally.. // thread has finished normally..
alertWindow.exitModalState (0);
alertWindow.setVisible (false);
alertWindow->exitModalState (0);
alertWindow->setVisible (false);
} }
else else
{ {
const ScopedLock sl (messageLock); const ScopedLock sl (messageLock);
alertWindow.setMessage (message);
alertWindow->setMessage (message);
} }
} }


@@ -87373,6 +87427,30 @@ void Rectangle::setSize (const int w_,
h = h_; h = h_;
} }


void Rectangle::setLeft (const int newLeft) throw()
{
w = jmax (0, x + w - newLeft);
x = newLeft;
}

void Rectangle::setTop (const int newTop) throw()
{
h = jmax (0, y + h - newTop);
y = newTop;
}

void Rectangle::setRight (const int newRight) throw()
{
x = jmin (x, newRight);
w = newRight - x;
}

void Rectangle::setBottom (const int newBottom) throw()
{
y = jmin (y, newBottom);
h = newBottom - y;
}

void Rectangle::translate (const int dx, void Rectangle::translate (const int dx,
const int dy) throw() const int dy) throw()
{ {
@@ -242157,6 +242235,8 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages


if (GetMessage (&m, (HWND) 0, 0, 0) > 0) if (GetMessage (&m, (HWND) 0, 0, 0) > 0)
{ {
const MessageManagerLock mml;

if (m.message == specialId if (m.message == specialId
&& m.hwnd == juce_messageWindowHandle) && m.hwnd == juce_messageWindowHandle)
{ {
@@ -265915,7 +265995,6 @@ void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool c
#endif #endif


#endif #endif

/********* End of inlined file: juce_mac_MiscUtilities.mm *********/ /********* End of inlined file: juce_mac_MiscUtilities.mm *********/


/********* Start of inlined file: juce_mac_Debugging.mm *********/ /********* Start of inlined file: juce_mac_Debugging.mm *********/
@@ -266034,6 +266113,7 @@ END_JUCE_NAMESPACE


- (void) setOwner: (NSViewComponentPeer*) owner; - (void) setOwner: (NSViewComponentPeer*) owner;
- (BOOL) canBecomeKeyWindow; - (BOOL) canBecomeKeyWindow;
- (void) becomeKeyWindow;
- (BOOL) windowShouldClose: (id) window; - (BOOL) windowShouldClose: (id) window;
- (NSRect) constrainFrameRect: (NSRect) frameRect toScreen: (NSScreen*) screen; - (NSRect) constrainFrameRect: (NSRect) frameRect toScreen: (NSScreen*) screen;
- (NSSize) windowWillResize: (NSWindow*) window toSize: (NSSize) proposedFrameSize; - (NSSize) windowWillResize: (NSWindow*) window toSize: (NSSize) proposedFrameSize;
@@ -266351,6 +266431,14 @@ END_JUCE_NAMESPACE
return owner != 0 && owner->canBecomeKeyWindow(); return owner != 0 && owner->canBecomeKeyWindow();
} }


- (void) becomeKeyWindow
{
[super becomeKeyWindow];

if (owner != 0)
owner->grabFocus();
}

- (BOOL) windowShouldClose: (id) window - (BOOL) windowShouldClose: (id) window
{ {
return owner == 0 || owner->windowShouldClose(); return owner == 0 || owner->windowShouldClose();
@@ -266826,6 +266914,8 @@ NSRect NSViewComponentPeer::constrainRect (NSRect r)
{ {
if (constrainer != 0) if (constrainer != 0)
{ {
const MessageManagerLock mml;

NSRect current = [window frame]; NSRect current = [window frame];
current.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - current.origin.y - current.size.height; current.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - current.origin.y - current.size.height;


@@ -267040,6 +267130,8 @@ void NSViewComponentPeer::grabFocus()
{ {
[window makeKeyWindow]; [window makeKeyWindow];
[window makeFirstResponder: view]; [window makeFirstResponder: view];

viewFocusGain();
} }
} }


@@ -267049,6 +267141,8 @@ void NSViewComponentPeer::textInputRequired (int /*x*/, int /*y*/)


bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown) bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown)
{ {
const MessageManagerLock mml;

String unicode (nsStringToJuce ([ev characters])); String unicode (nsStringToJuce ([ev characters]));
String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers])); String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers]));
int keyCode = getKeyCodeFromEvent (ev); int keyCode = getKeyCodeFromEvent (ev);
@@ -267088,6 +267182,7 @@ bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown)


bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev) bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateKeysDown (ev, true); updateKeysDown (ev, true);
bool used = handleKeyEvent (ev, true); bool used = handleKeyEvent (ev, true);


@@ -267103,12 +267198,14 @@ bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev)


bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev) bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateKeysDown (ev, false); updateKeysDown (ev, false);
return handleKeyEvent (ev, false); return handleKeyEvent (ev, false);
} }


void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev) void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
handleModifierKeysChange(); handleModifierKeysChange();
} }
@@ -267116,6 +267213,7 @@ void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev)
#if MACOS_10_4_OR_EARLIER #if MACOS_10_4_OR_EARLIER
bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev) bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev)
{ {
const MessageManagerLock mml;
if ([ev type] == NSKeyDown) if ([ev type] == NSKeyDown)
return redirectKeyDown (ev); return redirectKeyDown (ev);
else if ([ev type] == NSKeyUp) else if ([ev type] == NSKeyUp)
@@ -267127,6 +267225,7 @@ bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev)


void NSViewComponentPeer::redirectMouseDown (NSEvent* ev) void NSViewComponentPeer::redirectMouseDown (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]); currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]);
int x, y; int x, y;
@@ -267137,6 +267236,7 @@ void NSViewComponentPeer::redirectMouseDown (NSEvent* ev)


void NSViewComponentPeer::redirectMouseUp (NSEvent* ev) void NSViewComponentPeer::redirectMouseUp (NSEvent* ev)
{ {
const MessageManagerLock mml;
const int oldMods = currentModifiers; const int oldMods = currentModifiers;
updateModifiers (ev); updateModifiers (ev);
currentModifiers &= ~getModifierForButtonNumber ([ev buttonNumber]); currentModifiers &= ~getModifierForButtonNumber ([ev buttonNumber]);
@@ -267148,6 +267248,7 @@ void NSViewComponentPeer::redirectMouseUp (NSEvent* ev)


void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev) void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]); currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]);
int x, y; int x, y;
@@ -267158,6 +267259,7 @@ void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev)


void NSViewComponentPeer::redirectMouseMove (NSEvent* ev) void NSViewComponentPeer::redirectMouseMove (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
int x, y; int x, y;
getMousePos (ev, view, x, y); getMousePos (ev, view, x, y);
@@ -267167,6 +267269,7 @@ void NSViewComponentPeer::redirectMouseMove (NSEvent* ev)


void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev) void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
int x, y; int x, y;
getMousePos (ev, view, x, y); getMousePos (ev, view, x, y);
@@ -267176,6 +267279,7 @@ void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev)


void NSViewComponentPeer::redirectMouseExit (NSEvent* ev) void NSViewComponentPeer::redirectMouseExit (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);
int x, y; int x, y;
getMousePos (ev, view, x, y); getMousePos (ev, view, x, y);
@@ -267185,6 +267289,7 @@ void NSViewComponentPeer::redirectMouseExit (NSEvent* ev)


void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev) void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev)
{ {
const MessageManagerLock mml;
updateModifiers (ev); updateModifiers (ev);


handleMouseWheel (roundFloatToInt ([ev deltaX] * 10.0f), handleMouseWheel (roundFloatToInt ([ev deltaX] * 10.0f),
@@ -267194,6 +267299,8 @@ void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev)


BOOL NSViewComponentPeer::sendDragCallback (int type, id <NSDraggingInfo> sender) BOOL NSViewComponentPeer::sendDragCallback (int type, id <NSDraggingInfo> sender)
{ {
const MessageManagerLock mml;

NSString* bestType NSString* bestType
= [[sender draggingPasteboard] availableTypeFromArray: [view getSupportedDragTypes]]; = [[sender draggingPasteboard] availableTypeFromArray: [view getSupportedDragTypes]];


@@ -267244,6 +267351,7 @@ void NSViewComponentPeer::drawRect (NSRect r)
if (r.size.width < 1.0f || r.size.height < 1.0f) if (r.size.width < 1.0f || r.size.height < 1.0f)
return; return;


const MessageManagerLock mml;
const float y = [view frame].size.height - (r.origin.y + r.size.height); const float y = [view frame].size.height - (r.origin.y + r.size.height);


JuceNSImage temp ((int) (r.size.width + 0.5f), JuceNSImage temp ((int) (r.size.width + 0.5f),
@@ -267277,6 +267385,8 @@ void NSViewComponentPeer::drawRect (NSRect r)


bool NSViewComponentPeer::canBecomeKeyWindow() bool NSViewComponentPeer::canBecomeKeyWindow()
{ {
const MessageManagerLock mml;

// If running as a plugin, let the component decide whether it's going to allow the window to get focused. // If running as a plugin, let the component decide whether it's going to allow the window to get focused.
return JUCEApplication::getInstance() != 0 return JUCEApplication::getInstance() != 0
|| (isValidPeer (this) && getComponent()->getWantsKeyboardFocus()); || (isValidPeer (this) && getComponent()->getWantsKeyboardFocus());
@@ -267284,6 +267394,8 @@ bool NSViewComponentPeer::canBecomeKeyWindow()


bool NSViewComponentPeer::windowShouldClose() bool NSViewComponentPeer::windowShouldClose()
{ {
const MessageManagerLock mml;

if (! isValidPeer (this)) if (! isValidPeer (this))
return YES; return YES;


@@ -267293,6 +267405,7 @@ bool NSViewComponentPeer::windowShouldClose()


void NSViewComponentPeer::redirectMovedOrResized() void NSViewComponentPeer::redirectMovedOrResized()
{ {
const MessageManagerLock mml;
handleMovedOrResized(); handleMovedOrResized();
} }


@@ -267923,6 +268036,7 @@ void AppleRemoteDevice::handleCallbackInternal()
{ {
if (strcmp (cookies, buttonPatterns + i) == 0) if (strcmp (cookies, buttonPatterns + i) == 0)
{ {
const MessageManagerLock mml;
buttonPressed ((ButtonType) buttonNum, totalValues > 0); buttonPressed ((ButtonType) buttonNum, totalValues > 0);
break; break;
} }
@@ -268149,7 +268263,7 @@ public:
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator


NSOpenGLContext* renderContext; NSOpenGLContext* renderContext;
ThreadSafeNSOpenGLView* view;
ThreadSafeNSOpenGLView* view;


private: private:
OpenGLPixelFormat pixelFormat; OpenGLPixelFormat pixelFormat;
@@ -268401,11 +268515,16 @@ public:
void updateMenus() void updateMenus()
{ {
if (Time::getMillisecondCounter() > lastUpdateTime + 500) if (Time::getMillisecondCounter() > lastUpdateTime + 500)
{
const MessageManagerLock mml;
menuBarItemsChanged (0); menuBarItemsChanged (0);
}
} }


void invoke (const int commandId, ApplicationCommandManager* const commandManager, const int topLevelIndex) const void invoke (const int commandId, ApplicationCommandManager* const commandManager, const int topLevelIndex) const
{ {
const MessageManagerLock mml;

if (currentModel != 0) if (currentModel != 0)
{ {
if (commandManager != 0) if (commandManager != 0)
@@ -269502,6 +269621,7 @@ public:
bool isBold, isItalic; bool isBold, isItalic;
float fontSize, totalSize, ascent; float fontSize, totalSize, ascent;
int refCount; int refCount;
NSMutableDictionary* attributes;


FontHelper (const String& name_, FontHelper (const String& name_,
const bool bold_, const bool bold_,
@@ -269514,10 +269634,23 @@ public:
fontSize (size_), fontSize (size_),
refCount (1) refCount (1)
{ {
attributes = [[NSMutableDictionary dictionaryWithObject: [NSNumber numberWithInt: 0]
forKey: NSLigatureAttributeName] retain];

font = [NSFont fontWithName: juceStringToNS (name_) size: size_]; font = [NSFont fontWithName: juceStringToNS (name_) size: size_];


if (italic_) if (italic_)
font = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSItalicFontMask];
{
NSFont* newFont = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSItalicFontMask];

if (newFont == font)
{
// couldn't find an italic version, so fake it with obliqueness..
[attributes setObject: [NSNumber numberWithFloat: 0.16] forKey: NSObliquenessAttributeName];
}

font = newFont;
}


if (bold_) if (bold_)
font = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSBoldFontMask]; font = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSBoldFontMask];
@@ -269531,6 +269664,7 @@ public:
~FontHelper() ~FontHelper()
{ {
[font release]; [font release];
[attributes release];
} }


bool getPathAndKerning (const juce_wchar char1, bool getPathAndKerning (const juce_wchar char1,
@@ -269548,10 +269682,9 @@ public:


String chars; String chars;
chars << ' ' << char1 << char2; chars << ' ' << char1 << char2;
NSTextStorage* textStorage = [[[NSTextStorage alloc]
initWithString: juceStringToNS (chars)
attributes: [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: 0]
forKey: NSLigatureAttributeName]] autorelease];

NSTextStorage* textStorage = [[[NSTextStorage alloc] initWithString: juceStringToNS (chars)
attributes: attributes] autorelease];
NSLayoutManager* layoutManager = [[[NSLayoutManager alloc] init] autorelease]; NSLayoutManager* layoutManager = [[[NSLayoutManager alloc] init] autorelease];
NSTextContainer* textContainer = [[[NSTextContainer alloc] init] autorelease]; NSTextContainer* textContainer = [[[NSTextContainer alloc] init] autorelease];
[layoutManager addTextContainer: textContainer]; [layoutManager addTextContainer: textContainer];
@@ -269829,6 +269962,7 @@ public:
{ {
if (JUCEApplication::getInstance() != 0) if (JUCEApplication::getInstance() != 0)
{ {
const MessageManagerLock mml;
JUCEApplication::getInstance()->systemRequestedQuit(); JUCEApplication::getInstance()->systemRequestedQuit();
return NSTerminateCancel; return NSTerminateCancel;
} }
@@ -269840,6 +269974,7 @@ public:
{ {
if (JUCEApplication::getInstance() != 0) if (JUCEApplication::getInstance() != 0)
{ {
const MessageManagerLock mml;
JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce (filename)); JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce (filename));
return YES; return YES;
} }
@@ -269854,19 +269989,31 @@ public:
files.add (nsStringToJuce ((NSString*) [filenames objectAtIndex: i])); files.add (nsStringToJuce ((NSString*) [filenames objectAtIndex: i]));


if (files.size() > 0 && JUCEApplication::getInstance() != 0) if (files.size() > 0 && JUCEApplication::getInstance() != 0)
{
const MessageManagerLock mml;
JUCEApplication::getInstance()->anotherInstanceStarted (files.joinIntoString (T(" "))); JUCEApplication::getInstance()->anotherInstanceStarted (files.joinIntoString (T(" ")));
}
} }


virtual void focusChanged() virtual void focusChanged()
{ {
const MessageManagerLock mml;
juce_HandleProcessFocusChange(); juce_HandleProcessFocusChange();
} }


virtual void deliverMessage (void* message) virtual void deliverMessage (void* message)
{ {
// no need for an mm lock here - deliverMessage locks it
MessageManager::getInstance()->deliverMessage (message); MessageManager::getInstance()->deliverMessage (message);
} }


virtual void performCallback (CallbackMessagePayload* pl)
{
const MessageManagerLock mml;
pl->result = (*pl->function) (pl->parameter);
pl->hasBeenExecuted = true;
}

virtual void deleteSelf() virtual void deleteSelf()
{ {
delete this; delete this;
@@ -269995,10 +270142,7 @@ static bool flushingMessages = false;
CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes]; CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes];


if (pl != 0) if (pl != 0)
{
pl->result = (*pl->function) (pl->parameter);
pl->hasBeenExecuted = true;
}
redirector->performCallback (pl);
} }
else else
{ {
@@ -270017,7 +270161,6 @@ static JuceAppDelegate* juceAppDelegate = 0;
void MessageManager::runDispatchLoop() void MessageManager::runDispatchLoop()
{ {
const ScopedAutoReleasePool pool; const ScopedAutoReleasePool pool;
MessageManagerLock mml;


// must only be called by the message thread! // must only be called by the message thread!
jassert (isThisTheMessageThread()); jassert (isThisTheMessageThread());
@@ -270173,6 +270316,8 @@ END_JUCE_NAMESPACE
{ {
NSURL* url = [actionInformation valueForKey: @"WebActionOriginalURLKey"]; NSURL* url = [actionInformation valueForKey: @"WebActionOriginalURLKey"];


const MessageManagerLock mml;

if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString]))) if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString])))
[listener use]; [listener use];
else else


+ 76
- 16
juce_amalgamated.h View File

@@ -15016,8 +15016,8 @@ private:
#if ! JUCE_ONLY_BUILD_CORE_LIBRARY #if ! JUCE_ONLY_BUILD_CORE_LIBRARY


/********* Start of inlined file: juce_app_includes.h *********/ /********* Start of inlined file: juce_app_includes.h *********/
#ifndef __JUCE_JUCE_APP_INCLUDES_INCLUDEFILES__
#define __JUCE_JUCE_APP_INCLUDES_INCLUDEFILES__
#ifndef __JUCE_APP_INCLUDES_JUCEHEADER__
#define __JUCE_APP_INCLUDES_JUCEHEADER__


#ifndef __JUCE_APPLICATION_JUCEHEADER__ #ifndef __JUCE_APPLICATION_JUCEHEADER__


@@ -17747,6 +17747,28 @@ public:
void setBounds (const int newX, const int newY, void setBounds (const int newX, const int newY,
const int newWidth, const int newHeight) throw(); const int newWidth, const int newHeight) throw();


/** Moves the x position, adjusting the width so that the right-hand edge remains in the same place.
If the x is moved to be on the right of the current right-hand edge, the width will be set to zero.
*/
void setLeft (const int newLeft) throw();

/** Moves the y position, adjusting the height so that the bottom edge remains in the same place.
If the y is moved to be below the current bottom edge, the height will be set to zero.
*/
void setTop (const int newTop) throw();

/** Adjusts the width so that the right-hand edge of the rectangle has this new value.
If the new right is below the current X value, the X will be pushed down to match it.
@see getRight
*/
void setRight (const int newRight) throw();

/** Adjusts the height so that the bottom edge of the rectangle has this new value.
If the new bottom is lower than the current Y value, the Y will be pushed down to match it.
@see getBottom
*/
void setBottom (const int newBottom) throw();

/** Moves the rectangle's position by adding amount to its x and y co-ordinates. */ /** Moves the rectangle's position by adding amount to its x and y co-ordinates. */
void translate (const int deltaX, void translate (const int deltaX,
const int deltaY) throw(); const int deltaY) throw();
@@ -22451,12 +22473,23 @@ public:
*/ */
bool isCurrentlyModal() const throw(); bool isCurrentlyModal() const throw();


/** Returns the component that is currently modal.
/** Returns the number of components that are currently in a modal state.
@see getCurrentlyModalComponent
*/
static int JUCE_CALLTYPE getNumCurrentlyModalComponents() throw();

/** Returns one of the components that are currently modal.


@returns the modal component, or null if no components are modal
@see runModalLoop, isCurrentlyModal
The index specifies which of the possible modal components to return. The order
of the components in this list is the reverse of the order in which they became
modal - so the component at index 0 is always the active component, and the others
are progressively earlier ones that are themselves now blocked by later ones.

@returns the modal component, or null if no components are modal (or if the
index is out of range)
@see getNumCurrentlyModalComponents, runModalLoop, isCurrentlyModal
*/ */
static Component* JUCE_CALLTYPE getCurrentlyModalComponent() throw();
static Component* JUCE_CALLTYPE getCurrentlyModalComponent (int index = 0) throw();


/** Checks whether there's a modal component somewhere that's stopping this one /** Checks whether there's a modal component somewhere that's stopping this one
from receiving messages. from receiving messages.
@@ -37764,7 +37797,7 @@ typedef void* (MessageCallbackFunction) (void* userData);


@see Message, MessageListener, MessageManagerLock, JUCEApplication @see Message, MessageListener, MessageManagerLock, JUCEApplication
*/ */
class JUCE_API MessageManager : private DeletedAtShutdown
class JUCE_API MessageManager
{ {
public: public:


@@ -37871,12 +37904,13 @@ public:
void deliverMessage (void*); void deliverMessage (void*);
/** @internal */ /** @internal */
void deliverBroadcastMessage (const String&); void deliverBroadcastMessage (const String&);
/** @internal */
~MessageManager() throw();


juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator


private: private:
MessageManager() throw(); MessageManager() throw();
~MessageManager() throw();


friend class MessageListener; friend class MessageListener;
friend class ChangeBroadcaster; friend class ChangeBroadcaster;
@@ -50522,10 +50556,14 @@ public:
@param message a longer, more descriptive message to show underneath the @param message a longer, more descriptive message to show underneath the
headline headline
@param iconType the type of icon to display @param iconType the type of icon to display
@param associatedComponent if this is non-zero, it specifies the component that the
alert window should be associated with. Depending on the look
and feel, this might be used for positioning of the alert window.
*/ */
AlertWindow (const String& title, AlertWindow (const String& title,
const String& message, const String& message,
AlertIconType iconType);
AlertIconType iconType,
Component* associatedComponent = 0);


/** Destroys the AlertWindow */ /** Destroys the AlertWindow */
~AlertWindow(); ~AlertWindow();
@@ -50670,11 +50708,15 @@ public:
headline headline
@param buttonText the text to show in the button - if this string is empty, the @param buttonText the text to show in the button - if this string is empty, the
default string "ok" (or a localised version) will be used. default string "ok" (or a localised version) will be used.
@param associatedComponent if this is non-zero, it specifies the component that the
alert window should be associated with. Depending on the look
and feel, this might be used for positioning of the alert window.
*/ */
static void JUCE_CALLTYPE showMessageBox (AlertIconType iconType, static void JUCE_CALLTYPE showMessageBox (AlertIconType iconType,
const String& title, const String& title,
const String& message, const String& message,
const String& buttonText = String::empty);
const String& buttonText = String::empty,
Component* associatedComponent = 0);


/** Shows a dialog box with two buttons. /** Shows a dialog box with two buttons.


@@ -50691,13 +50733,17 @@ public:
@param button2Text the text to show in the second button - if this string is @param button2Text the text to show in the second button - if this string is
empty, the default string "cancel" (or a localised version of it) empty, the default string "cancel" (or a localised version of it)
will be used. will be used.
@returns true if button 1 was clicked, false if it was button 2
@param associatedComponent if this is non-zero, it specifies the component that the
alert window should be associated with. Depending on the look
and feel, this might be used for positioning of the alert window.
@returns true if button 1 was clicked, false if it was button 2
*/ */
static bool JUCE_CALLTYPE showOkCancelBox (AlertIconType iconType, static bool JUCE_CALLTYPE showOkCancelBox (AlertIconType iconType,
const String& title, const String& title,
const String& message, const String& message,
const String& button1Text = String::empty, const String& button1Text = String::empty,
const String& button2Text = String::empty);
const String& button2Text = String::empty,
Component* associatedComponent = 0);


/** Shows a dialog box with three buttons. /** Shows a dialog box with three buttons.


@@ -50715,6 +50761,9 @@ public:
"no" will be used (or a localised version of it) "no" will be used (or a localised version of it)
@param button3Text the text to show in the first button - if an empty string, then @param button3Text the text to show in the first button - if an empty string, then
"cancel" will be used (or a localised version of it) "cancel" will be used (or a localised version of it)
@param associatedComponent if this is non-zero, it specifies the component that the
alert window should be associated with. Depending on the look
and feel, this might be used for positioning of the alert window.


@returns one of the following values: @returns one of the following values:
- 0 if the third button was pressed (normally used for 'cancel') - 0 if the third button was pressed (normally used for 'cancel')
@@ -50726,7 +50775,8 @@ public:
const String& message, const String& message,
const String& button1Text = String::empty, const String& button1Text = String::empty,
const String& button2Text = String::empty, const String& button2Text = String::empty,
const String& button3Text = String::empty);
const String& button3Text = String::empty,
Component* associatedComponent = 0);


/** Shows an operating-system native dialog box. /** Shows an operating-system native dialog box.


@@ -50785,6 +50835,7 @@ private:
VoidArray progressBars, customComps, textBlocks, allComps; VoidArray progressBars, customComps, textBlocks, allComps;
StringArray textboxNames, comboBoxNames; StringArray textboxNames, comboBoxNames;
Font font; Font font;
Component* associatedComponent;


void updateLayout (const bool onlyIncreaseSize); void updateLayout (const bool onlyIncreaseSize);


@@ -51161,7 +51212,7 @@ private:
void timerCallback(); void timerCallback();


double progress; double progress;
AlertWindow alertWindow;
AlertWindow* alertWindow;
String message; String message;
CriticalSection messageLock; CriticalSection messageLock;
const int timeOutMsWhenCancelling; const int timeOutMsWhenCancelling;
@@ -53196,8 +53247,17 @@ public:
const bool isMouseOverButton, const bool isMouseOverButton,
const bool isButtonDown); const bool isButtonDown);


/** Draws the contents of a message box.
/** AlertWindow handling..
*/ */
virtual AlertWindow* createAlertWindow (const String& title,
const String& message,
const String& button1,
const String& button2,
const String& button3,
AlertWindow::AlertIconType iconType,
int numButtons,
Component* associatedComponent);

virtual void drawAlertBox (Graphics& g, virtual void drawAlertBox (Graphics& g,
AlertWindow& alert, AlertWindow& alert,
const Rectangle& textArea, const Rectangle& textArea,
@@ -54173,7 +54233,7 @@ private:


#endif #endif


#endif
#endif // __JUCE_APP_INCLUDES_JUCEHEADER__
/********* End of inlined file: juce_app_includes.h *********/ /********* End of inlined file: juce_app_includes.h *********/


#endif #endif


+ 15
- 4
src/juce_appframework/application/juce_Application.cpp View File

@@ -194,8 +194,12 @@ int JUCEApplication::main (String& commandLine, JUCEApplication* const app)
{ {
juce_setCurrentThreadName ("Juce Message Thread"); juce_setCurrentThreadName ("Juce Message Thread");
// let the app do its setting-up..
app->initialise (app->commandLineParameters);
{
const MessageManagerLock mml;
// let the app do its setting-up..
app->initialise (app->commandLineParameters);
}
// register for broadcast new app messages // register for broadcast new app messages
MessageManager::getInstance()->registerBroadcastListener (app); MessageManager::getInstance()->registerBroadcastListener (app);
@@ -242,6 +246,7 @@ int JUCEApplication::shutdownAppAndClearUp()
JUCE_TRY JUCE_TRY
{ {
// give the app a chance to clean up.. // give the app a chance to clean up..
const MessageManagerLock mml;
app->shutdown(); app->shutdown();
} }
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS #if JUCE_CATCH_UNHANDLED_EXCEPTIONS
@@ -340,9 +345,15 @@ void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI()
#if JUCE_MAC #if JUCE_MAC
const ScopedAutoReleasePool pool; const ScopedAutoReleasePool pool;
#endif #endif
DeletedAtShutdown::deleteAll();
{
const MessageManagerLock mml;
DeletedAtShutdown::deleteAll();
LookAndFeel::clearDefaultLookAndFeel();
}
delete MessageManager::getInstance();
LookAndFeel::clearDefaultLookAndFeel();
shutdownJuce_NonGUI(); shutdownJuce_NonGUI();
juceInitialisedGUI = false; juceInitialisedGUI = false;


+ 2
- 2
src/juce_appframework/audio/audio_sources/juce_ResamplingAudioSource.cpp View File

@@ -126,7 +126,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf
input->getNextAudioBlock (readInfo); input->getNextAudioBlock (readInfo);
if (ratio > 1.0)
if (ratio > 1.0001)
{ {
// for down-sampling, pre-apply the filter.. // for down-sampling, pre-apply the filter..
@@ -172,7 +172,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf
} }
} }
if (ratio < 1.0)
if (ratio < 0.9999)
{ {
// for up-sampling, apply the filter after transposing.. // for up-sampling, apply the filter after transposing..


+ 31
- 12
src/juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.mm View File

@@ -730,13 +730,19 @@ OSStatus AudioUnitPluginInstance::getBeatAndTempo (Float64* outCurrentBeat, Floa
if (ph != 0 && ph->getCurrentPosition (result)) if (ph != 0 && ph->getCurrentPosition (result))
{ {
*outCurrentBeat = result.ppqPosition;
*outCurrentTempo = result.bpm;
if (outCurrentBeat != 0)
*outCurrentBeat = result.ppqPosition;
if (outCurrentTempo != 0)
*outCurrentTempo = result.bpm;
} }
else else
{ {
*outCurrentBeat = 0;
*outCurrentTempo = 120.0;
if (outCurrentBeat != 0)
*outCurrentBeat = 0;
if (outCurrentTempo != 0)
*outCurrentTempo = 120.0;
} }
return noErr; return noErr;
@@ -752,18 +758,31 @@ OSStatus AudioUnitPluginInstance::getMusicalTimeLocation (UInt32* outDeltaSample
if (ph != 0 && ph->getCurrentPosition (result)) if (ph != 0 && ph->getCurrentPosition (result))
{ {
*outTimeSig_Numerator = result.timeSigNumerator;
*outTimeSig_Denominator = result.timeSigDenominator;
if (outTimeSig_Numerator != 0)
*outTimeSig_Numerator = result.timeSigNumerator;
if (outTimeSig_Denominator != 0)
*outTimeSig_Denominator = result.timeSigDenominator;
if (outDeltaSampleOffsetToNextBeat != 0)
*outDeltaSampleOffsetToNextBeat = 0; //xxx
*outDeltaSampleOffsetToNextBeat = 0; //xxx
*outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong
if (outCurrentMeasureDownBeat != 0)
*outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong
} }
else else
{ {
*outDeltaSampleOffsetToNextBeat = 0;
*outTimeSig_Numerator = 4;
*outTimeSig_Denominator = 4;
*outCurrentMeasureDownBeat = 0;
if (outDeltaSampleOffsetToNextBeat != 0)
*outDeltaSampleOffsetToNextBeat = 0;
if (outTimeSig_Numerator != 0)
*outTimeSig_Numerator = 4;
if (outTimeSig_Denominator != 0)
*outTimeSig_Denominator = 4;
if (outCurrentMeasureDownBeat != 0)
*outCurrentMeasureDownBeat = 0;
} }
return noErr; return noErr;


+ 2
- 1
src/juce_appframework/events/juce_MessageManager.cpp View File

@@ -57,7 +57,8 @@ MessageManager::MessageManager() throw()
quitMessagePosted (false), quitMessagePosted (false),
quitMessageReceived (false) quitMessageReceived (false)
{ {
currentLockingThreadId = messageThreadId = Thread::getCurrentThreadId();
currentLockingThreadId = 0;
messageThreadId = Thread::getCurrentThreadId();
} }
MessageManager::~MessageManager() throw() MessageManager::~MessageManager() throw()


+ 3
- 2
src/juce_appframework/events/juce_MessageManager.h View File

@@ -52,7 +52,7 @@ typedef void* (MessageCallbackFunction) (void* userData);
@see Message, MessageListener, MessageManagerLock, JUCEApplication @see Message, MessageListener, MessageManagerLock, JUCEApplication
*/ */
class JUCE_API MessageManager : private DeletedAtShutdown
class JUCE_API MessageManager
{ {
public: public:
//============================================================================== //==============================================================================
@@ -163,13 +163,14 @@ public:
void deliverMessage (void*); void deliverMessage (void*);
/** @internal */ /** @internal */
void deliverBroadcastMessage (const String&); void deliverBroadcastMessage (const String&);
/** @internal */
~MessageManager() throw();
//============================================================================== //==============================================================================
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator
private: private:
MessageManager() throw(); MessageManager() throw();
~MessageManager() throw();
friend class MessageListener; friend class MessageListener;
friend class ChangeBroadcaster; friend class ChangeBroadcaster;


+ 2
- 0
src/juce_appframework/gui/components/controls/juce_TreeView.cpp View File

@@ -567,7 +567,9 @@ void TreeView::paint (Graphics& g)
void TreeView::resized() void TreeView::resized()
{ {
viewport->setBounds (0, 0, getWidth(), getHeight()); viewport->setBounds (0, 0, getWidth(), getHeight());
itemsChanged(); itemsChanged();
handleAsyncUpdate();
} }
void TreeView::moveSelectedRow (int delta) void TreeView::moveSelectedRow (int delta)


+ 7
- 2
src/juce_appframework/gui/components/juce_Component.cpp View File

@@ -1539,9 +1539,14 @@ bool Component::isCurrentlyBlockedByAnotherModalComponent() const throw()
&& ! mc->canModalEventBeSentToComponent (this); && ! mc->canModalEventBeSentToComponent (this);
} }
Component* JUCE_CALLTYPE Component::getCurrentlyModalComponent() throw()
int JUCE_CALLTYPE Component::getNumCurrentlyModalComponents() throw()
{ {
Component* const c = (Component*) modalComponentStack.getLast();
return modalComponentStack.size();
}
Component* JUCE_CALLTYPE Component::getCurrentlyModalComponent (int index) throw()
{
Component* const c = (Component*) (modalComponentStack [modalComponentStack.size() - index - 1]);
return c->isValidComponent() ? c : 0; return c->isValidComponent() ? c : 0;
} }


+ 15
- 4
src/juce_appframework/gui/components/juce_Component.h View File

@@ -1763,12 +1763,23 @@ public:
*/ */
bool isCurrentlyModal() const throw(); bool isCurrentlyModal() const throw();
/** Returns the component that is currently modal.
/** Returns the number of components that are currently in a modal state.
@see getCurrentlyModalComponent
*/
static int JUCE_CALLTYPE getNumCurrentlyModalComponents() throw();
/** Returns one of the components that are currently modal.
@returns the modal component, or null if no components are modal
@see runModalLoop, isCurrentlyModal
The index specifies which of the possible modal components to return. The order
of the components in this list is the reverse of the order in which they became
modal - so the component at index 0 is always the active component, and the others
are progressively earlier ones that are themselves now blocked by later ones.
@returns the modal component, or null if no components are modal (or if the
index is out of range)
@see getNumCurrentlyModalComponents, runModalLoop, isCurrentlyModal
*/ */
static Component* JUCE_CALLTYPE getCurrentlyModalComponent() throw();
static Component* JUCE_CALLTYPE getCurrentlyModalComponent (int index = 0) throw();
/** Checks whether there's a modal component somewhere that's stopping this one /** Checks whether there's a modal component somewhere that's stopping this one
from receiving messages. from receiving messages.


+ 1
- 0
src/juce_appframework/gui/components/keyboard/juce_KeyPressMappingSet.cpp View File

@@ -393,6 +393,7 @@ bool KeyPressMappingSet::keyStateChanged (Component* originatingComponent)
{ {
keyPressEntryIndex = k; keyPressEntryIndex = k;
wasDown = true; wasDown = true;
used = true;
break; break;
} }
} }


+ 84
- 58
src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp View File

@@ -465,78 +465,105 @@ void LookAndFeel::changeToggleButtonWidthToFitText (ToggleButton& button)
button.getHeight()); button.getHeight());
} }
//==============================================================================
AlertWindow* LookAndFeel::createAlertWindow (const String& title,
const String& message,
const String& button1,
const String& button2,
const String& button3,
AlertWindow::AlertIconType iconType,
int numButtons,
Component* associatedComponent)
{
AlertWindow* aw = new AlertWindow (title, message, iconType);
if (numButtons == 1)
{
aw->addButton (button1, 0,
KeyPress (KeyPress::escapeKey, 0, 0),
KeyPress (KeyPress::returnKey, 0, 0));
}
else
{
const KeyPress button1ShortCut (CharacterFunctions::toLowerCase (button1[0]), 0, 0);
KeyPress button2ShortCut (CharacterFunctions::toLowerCase (button2[0]), 0, 0);
if (button1ShortCut == button2ShortCut)
button2ShortCut = KeyPress();
if (numButtons == 2)
{
aw->addButton (button1, 1, KeyPress (KeyPress::returnKey, 0, 0), button1ShortCut);
aw->addButton (button2, 0, KeyPress (KeyPress::escapeKey, 0, 0), button2ShortCut);
}
else
{
jassert (numButtons == 3);
aw->addButton (button1, 1, button1ShortCut);
aw->addButton (button2, 2, button2ShortCut);
aw->addButton (button3, 0, KeyPress (KeyPress::escapeKey, 0, 0));
}
}
return aw;
}
void LookAndFeel::drawAlertBox (Graphics& g, void LookAndFeel::drawAlertBox (Graphics& g,
AlertWindow& alert, AlertWindow& alert,
const Rectangle& textArea, const Rectangle& textArea,
TextLayout& textLayout) TextLayout& textLayout)
{ {
const int iconWidth = 80;
const Colour background (alert.findColour (AlertWindow::backgroundColourId));
g.fillAll (background);
g.fillAll (alert.findColour (AlertWindow::backgroundColourId));
int iconSpaceUsed = 0; int iconSpaceUsed = 0;
Justification alignment (Justification::horizontallyCentred); Justification alignment (Justification::horizontallyCentred);
const int iconWidth = 80;
int iconSize = jmin (iconWidth + 50, alert.getHeight() + 20); int iconSize = jmin (iconWidth + 50, alert.getHeight() + 20);
if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2) if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2)
iconSize = jmin (iconSize, textArea.getHeight() + 50); iconSize = jmin (iconSize, textArea.getHeight() + 50);
const Rectangle iconRect (iconSize / -10,
iconSize / -10,
iconSize,
iconSize);
const Rectangle iconRect (iconSize / -10, iconSize / -10,
iconSize, iconSize);
if (alert.getAlertType() == AlertWindow::QuestionIcon
|| alert.getAlertType() == AlertWindow::InfoIcon)
if (alert.getAlertType() != AlertWindow::NoIcon)
{ {
if (alert.getAlertType() == AlertWindow::InfoIcon)
g.setColour (background.overlaidWith (Colour (0x280000ff)));
Path icon;
uint32 colour;
char character;
if (alert.getAlertType() == AlertWindow::WarningIcon)
{
colour = 0x55ff5555;
character = '!';
icon.addTriangle (iconRect.getX() + iconRect.getWidth() * 0.5f, (float) iconRect.getY(),
(float) iconRect.getRight(), (float) iconRect.getBottom(),
(float) iconRect.getX(), (float) iconRect.getBottom());
icon = icon.createPathWithRoundedCorners (5.0f);
}
else else
g.setColour (background.overlaidWith (Colours::gold.darker().withAlpha (0.25f)));
g.fillEllipse ((float) iconRect.getX(),
(float) iconRect.getY(),
(float) iconRect.getWidth(),
(float) iconRect.getHeight());
g.setColour (background);
g.setFont (iconRect.getHeight() * 0.9f, Font::bold);
g.drawText ((alert.getAlertType() == AlertWindow::InfoIcon) ? "i"
: "?",
iconRect.getX(),
iconRect.getY(),
iconRect.getWidth(),
iconRect.getHeight(),
Justification::centred, false);
{
colour = alert.getAlertType() == AlertWindow::InfoIcon ? 0x605555ff : 0x40b69900;
character = alert.getAlertType() == AlertWindow::InfoIcon ? 'i' : '?';
iconSpaceUsed = iconWidth;
alignment = Justification::left;
}
else if (alert.getAlertType() == AlertWindow::WarningIcon)
{
Path p;
p.addTriangle (iconRect.getX() + iconRect.getWidth() * 0.5f,
(float) iconRect.getY(),
(float) iconRect.getRight(),
(float) iconRect.getBottom(),
(float) iconRect.getX(),
(float) iconRect.getBottom());
g.setColour (background.overlaidWith (Colour (0x33ff0000)));
g.fillPath (p.createPathWithRoundedCorners (5.0f));
g.setColour (background);
g.setFont (iconRect.getHeight() * 0.9f, Font::bold);
g.drawText (T("!"),
iconRect.getX(),
iconRect.getY(),
iconRect.getWidth(),
iconRect.getHeight() + iconRect.getHeight() / 8,
Justification::centred, false);
icon.addEllipse ((float) iconRect.getX(), (float) iconRect.getY(),
(float) iconRect.getWidth(), (float) iconRect.getHeight());
}
GlyphArrangement ga;
ga.addFittedText (Font (iconRect.getHeight() * 0.9f, Font::bold),
String::charToString (character),
(float) iconRect.getX(), (float) iconRect.getY(),
(float) iconRect.getWidth(), (float) iconRect.getHeight(),
Justification::centred, false);
ga.createPath (icon);
icon.setUsingNonZeroWinding (false);
g.setColour (Colour (colour));
g.fillPath (icon);
iconSpaceUsed = iconWidth; iconSpaceUsed = iconWidth;
alignment = Justification::left; alignment = Justification::left;
@@ -545,10 +572,8 @@ void LookAndFeel::drawAlertBox (Graphics& g,
g.setColour (alert.findColour (AlertWindow::textColourId)); g.setColour (alert.findColour (AlertWindow::textColourId));
textLayout.drawWithin (g, textLayout.drawWithin (g,
textArea.getX() + iconSpaceUsed,
textArea.getY(),
textArea.getWidth() - iconSpaceUsed,
textArea.getHeight(),
textArea.getX() + iconSpaceUsed, textArea.getY(),
textArea.getWidth() - iconSpaceUsed, textArea.getHeight(),
alignment.getFlags() | Justification::top); alignment.getFlags() | Justification::top);
g.setColour (alert.findColour (AlertWindow::outlineColourId)); g.setColour (alert.findColour (AlertWindow::outlineColourId));
@@ -571,6 +596,7 @@ const Font LookAndFeel::getAlertWindowFont()
return Font (12.0f); return Font (12.0f);
} }
//==============================================================================
void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar,
int width, int height, int width, int height,
double progress, const String& textToShow) double progress, const String& textToShow)


+ 11
- 1
src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h View File

@@ -36,6 +36,7 @@
#include "../../graphics/effects/juce_DropShadowEffect.h" #include "../../graphics/effects/juce_DropShadowEffect.h"
#include "../controls/juce_Slider.h" #include "../controls/juce_Slider.h"
#include "../layout/juce_TabbedComponent.h" #include "../layout/juce_TabbedComponent.h"
#include "../windows/juce_AlertWindow.h"
class ToggleButton; class ToggleButton;
class TextButton; class TextButton;
@@ -175,8 +176,17 @@ public:
const bool isButtonDown); const bool isButtonDown);
//============================================================================== //==============================================================================
/** Draws the contents of a message box.
/** AlertWindow handling..
*/ */
virtual AlertWindow* createAlertWindow (const String& title,
const String& message,
const String& button1,
const String& button2,
const String& button3,
AlertWindow::AlertIconType iconType,
int numButtons,
Component* associatedComponent);
virtual void drawAlertBox (Graphics& g, virtual void drawAlertBox (Graphics& g,
AlertWindow& alert, AlertWindow& alert,
const Rectangle& textArea, const Rectangle& textArea,


+ 27
- 40
src/juce_appframework/gui/components/windows/juce_AlertWindow.cpp View File

@@ -90,18 +90,17 @@ private:
//============================================================================== //==============================================================================
AlertWindow::AlertWindow (const String& title, AlertWindow::AlertWindow (const String& title,
const String& message, const String& message,
AlertIconType iconType)
AlertIconType iconType,
Component* associatedComponent_)
: TopLevelWindow (title, true), : TopLevelWindow (title, true),
alertIconType (iconType)
alertIconType (iconType),
associatedComponent (associatedComponent_)
{ {
if (message.isEmpty()) if (message.isEmpty())
text = T(" "); // to force an update if the message is empty text = T(" "); // to force an update if the message is empty
setMessage (message); setMessage (message);
#if JUCE_MAC
setAlwaysOnTop (true);
#else
for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;)
{ {
Component* const c = Desktop::getInstance().getComponent (i); Component* const c = Desktop::getInstance().getComponent (i);
@@ -112,7 +111,6 @@ AlertWindow::AlertWindow (const String& title,
break; break;
} }
} }
#endif
lookAndFeelChanged(); lookAndFeelChanged();
@@ -470,7 +468,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
if (! isVisible()) if (! isVisible())
{ {
centreAroundComponent (0, w, h);
centreAroundComponent (associatedComponent, w, h);
} }
else else
{ {
@@ -588,7 +586,7 @@ void AlertWindow::lookAndFeelChanged()
const int flags = getLookAndFeel().getAlertBoxWindowFlags(); const int flags = getLookAndFeel().getAlertBoxWindowFlags();
setUsingNativeTitleBar ((flags & ComponentPeer::windowHasTitleBar) != 0); setUsingNativeTitleBar ((flags & ComponentPeer::windowHasTitleBar) != 0);
setDropShadowEnabled ((flags & ComponentPeer::windowHasDropShadow) != 0);
setDropShadowEnabled (isOpaque() && (flags & ComponentPeer::windowHasDropShadow) != 0);
} }
int AlertWindow::getDesktopWindowStyleFlags() const int AlertWindow::getDesktopWindowStyleFlags() const
@@ -602,6 +600,7 @@ struct AlertWindowInfo
String title, message, button1, button2, button3; String title, message, button1, button2, button3;
AlertWindow::AlertIconType iconType; AlertWindow::AlertIconType iconType;
int numButtons; int numButtons;
Component* associatedComponent;
int run() const int run() const
{ {
@@ -612,37 +611,19 @@ struct AlertWindowInfo
private: private:
int show() const int show() const
{ {
AlertWindow aw (title, message, iconType);
jassert (associatedComponent == 0 || associatedComponent->isValidComponent()); // has your comp been deleted?
if (numButtons == 1)
{
aw.addButton (button1, 0,
KeyPress (KeyPress::escapeKey, 0, 0),
KeyPress (KeyPress::returnKey, 0, 0));
}
else
{
const KeyPress button1ShortCut (CharacterFunctions::toLowerCase (button1[0]), 0, 0);
KeyPress button2ShortCut (CharacterFunctions::toLowerCase (button2[0]), 0, 0);
if (button1ShortCut == button2ShortCut)
button2ShortCut = KeyPress();
if (numButtons == 2)
{
aw.addButton (button1, 1, KeyPress (KeyPress::returnKey, 0, 0), button1ShortCut);
aw.addButton (button2, 0, KeyPress (KeyPress::escapeKey, 0, 0), button2ShortCut);
}
else
{
jassert (numButtons == 3);
aw.addButton (button1, 1, button1ShortCut);
aw.addButton (button2, 2, button2ShortCut);
aw.addButton (button3, 0, KeyPress (KeyPress::escapeKey, 0, 0));
}
}
LookAndFeel& lf = associatedComponent->isValidComponent() ? associatedComponent->getLookAndFeel()
: LookAndFeel::getDefaultLookAndFeel();
Component* const alertBox = lf.createAlertWindow (title, message, button1, button2, button3,
iconType, numButtons, associatedComponent);
jassert (alertBox != 0); // you have to return one of these!
return aw.runModalLoop();
const int result = alertBox->runModalLoop();
delete alertBox;
return result;
} }
static void* showCallback (void* userData) static void* showCallback (void* userData)
@@ -654,7 +635,8 @@ private:
void AlertWindow::showMessageBox (AlertIconType iconType, void AlertWindow::showMessageBox (AlertIconType iconType,
const String& title, const String& title,
const String& message, const String& message,
const String& buttonText)
const String& buttonText,
Component* associatedComponent)
{ {
AlertWindowInfo info; AlertWindowInfo info;
info.title = title; info.title = title;
@@ -662,6 +644,7 @@ void AlertWindow::showMessageBox (AlertIconType iconType,
info.button1 = buttonText.isEmpty() ? TRANS("ok") : buttonText; info.button1 = buttonText.isEmpty() ? TRANS("ok") : buttonText;
info.iconType = iconType; info.iconType = iconType;
info.numButtons = 1; info.numButtons = 1;
info.associatedComponent = associatedComponent;
info.run(); info.run();
} }
@@ -670,7 +653,8 @@ bool AlertWindow::showOkCancelBox (AlertIconType iconType,
const String& title, const String& title,
const String& message, const String& message,
const String& button1Text, const String& button1Text,
const String& button2Text)
const String& button2Text,
Component* associatedComponent)
{ {
AlertWindowInfo info; AlertWindowInfo info;
info.title = title; info.title = title;
@@ -679,6 +663,7 @@ bool AlertWindow::showOkCancelBox (AlertIconType iconType,
info.button2 = button2Text.isEmpty() ? TRANS("cancel") : button2Text; info.button2 = button2Text.isEmpty() ? TRANS("cancel") : button2Text;
info.iconType = iconType; info.iconType = iconType;
info.numButtons = 2; info.numButtons = 2;
info.associatedComponent = associatedComponent;
return info.run() != 0; return info.run() != 0;
} }
@@ -688,7 +673,8 @@ int AlertWindow::showYesNoCancelBox (AlertIconType iconType,
const String& message, const String& message,
const String& button1Text, const String& button1Text,
const String& button2Text, const String& button2Text,
const String& button3Text)
const String& button3Text,
Component* associatedComponent)
{ {
AlertWindowInfo info; AlertWindowInfo info;
info.title = title; info.title = title;
@@ -698,6 +684,7 @@ int AlertWindow::showYesNoCancelBox (AlertIconType iconType,
info.button3 = button3Text.isEmpty() ? TRANS("cancel") : button3Text; info.button3 = button3Text.isEmpty() ? TRANS("cancel") : button3Text;
info.iconType = iconType; info.iconType = iconType;
info.numButtons = 3; info.numButtons = 3;
info.associatedComponent = associatedComponent;
return info.run(); return info.run();
} }


+ 23
- 6
src/juce_appframework/gui/components/windows/juce_AlertWindow.h View File

@@ -76,10 +76,14 @@ public:
@param message a longer, more descriptive message to show underneath the @param message a longer, more descriptive message to show underneath the
headline headline
@param iconType the type of icon to display @param iconType the type of icon to display
@param associatedComponent if this is non-zero, it specifies the component that the
alert window should be associated with. Depending on the look
and feel, this might be used for positioning of the alert window.
*/ */
AlertWindow (const String& title, AlertWindow (const String& title,
const String& message, const String& message,
AlertIconType iconType);
AlertIconType iconType,
Component* associatedComponent = 0);
/** Destroys the AlertWindow */ /** Destroys the AlertWindow */
~AlertWindow(); ~AlertWindow();
@@ -234,11 +238,15 @@ public:
headline headline
@param buttonText the text to show in the button - if this string is empty, the @param buttonText the text to show in the button - if this string is empty, the
default string "ok" (or a localised version) will be used. default string "ok" (or a localised version) will be used.
@param associatedComponent if this is non-zero, it specifies the component that the
alert window should be associated with. Depending on the look
and feel, this might be used for positioning of the alert window.
*/ */
static void JUCE_CALLTYPE showMessageBox (AlertIconType iconType, static void JUCE_CALLTYPE showMessageBox (AlertIconType iconType,
const String& title, const String& title,
const String& message, const String& message,
const String& buttonText = String::empty);
const String& buttonText = String::empty,
Component* associatedComponent = 0);
/** Shows a dialog box with two buttons. /** Shows a dialog box with two buttons.
@@ -255,13 +263,17 @@ public:
@param button2Text the text to show in the second button - if this string is @param button2Text the text to show in the second button - if this string is
empty, the default string "cancel" (or a localised version of it) empty, the default string "cancel" (or a localised version of it)
will be used. will be used.
@returns true if button 1 was clicked, false if it was button 2
@param associatedComponent if this is non-zero, it specifies the component that the
alert window should be associated with. Depending on the look
and feel, this might be used for positioning of the alert window.
@returns true if button 1 was clicked, false if it was button 2
*/ */
static bool JUCE_CALLTYPE showOkCancelBox (AlertIconType iconType, static bool JUCE_CALLTYPE showOkCancelBox (AlertIconType iconType,
const String& title, const String& title,
const String& message, const String& message,
const String& button1Text = String::empty, const String& button1Text = String::empty,
const String& button2Text = String::empty);
const String& button2Text = String::empty,
Component* associatedComponent = 0);
/** Shows a dialog box with three buttons. /** Shows a dialog box with three buttons.
@@ -279,7 +291,10 @@ public:
"no" will be used (or a localised version of it) "no" will be used (or a localised version of it)
@param button3Text the text to show in the first button - if an empty string, then @param button3Text the text to show in the first button - if an empty string, then
"cancel" will be used (or a localised version of it) "cancel" will be used (or a localised version of it)
@param associatedComponent if this is non-zero, it specifies the component that the
alert window should be associated with. Depending on the look
and feel, this might be used for positioning of the alert window.
@returns one of the following values: @returns one of the following values:
- 0 if the third button was pressed (normally used for 'cancel') - 0 if the third button was pressed (normally used for 'cancel')
- 1 if the first button was pressed (normally used for 'yes') - 1 if the first button was pressed (normally used for 'yes')
@@ -290,7 +305,8 @@ public:
const String& message, const String& message,
const String& button1Text = String::empty, const String& button1Text = String::empty,
const String& button2Text = String::empty, const String& button2Text = String::empty,
const String& button3Text = String::empty);
const String& button3Text = String::empty,
Component* associatedComponent = 0);
//============================================================================== //==============================================================================
/** Shows an operating-system native dialog box. /** Shows an operating-system native dialog box.
@@ -353,6 +369,7 @@ private:
VoidArray progressBars, customComps, textBlocks, allComps; VoidArray progressBars, customComps, textBlocks, allComps;
StringArray textboxNames, comboBoxNames; StringArray textboxNames, comboBoxNames;
Font font; Font font;
Component* associatedComponent;
void updateLayout (const bool onlyIncreaseSize); void updateLayout (const bool onlyIncreaseSize);


+ 14
- 9
src/juce_appframework/gui/components/windows/juce_ThreadWithProgressWindow.cpp View File

@@ -35,6 +35,7 @@ BEGIN_JUCE_NAMESPACE
#include "juce_ThreadWithProgressWindow.h" #include "juce_ThreadWithProgressWindow.h"
#include "../lookandfeel/juce_LookAndFeel.h"
#include "../../../../juce_core/text/juce_LocalisedStrings.h" #include "../../../../juce_core/text/juce_LocalisedStrings.h"
@@ -46,19 +47,23 @@ ThreadWithProgressWindow::ThreadWithProgressWindow (const String& title,
const String& cancelButtonText) const String& cancelButtonText)
: Thread ("Juce Progress Window"), : Thread ("Juce Progress Window"),
progress (0.0), progress (0.0),
alertWindow (title, String::empty, AlertWindow::NoIcon),
timeOutMsWhenCancelling (timeOutMsWhenCancelling_) timeOutMsWhenCancelling (timeOutMsWhenCancelling_)
{ {
alertWindow = LookAndFeel::getDefaultLookAndFeel()
.createAlertWindow (title, String::empty, cancelButtonText, String::empty, String::empty,
AlertWindow::NoIcon, 1, 0);
if (hasProgressBar) if (hasProgressBar)
alertWindow.addProgressBarComponent (progress);
alertWindow->addProgressBarComponent (progress);
if (hasCancelButton) if (hasCancelButton)
alertWindow.addButton (cancelButtonText, 1);
alertWindow->addButton (cancelButtonText, 1);
} }
ThreadWithProgressWindow::~ThreadWithProgressWindow() ThreadWithProgressWindow::~ThreadWithProgressWindow()
{ {
stopThread (timeOutMsWhenCancelling); stopThread (timeOutMsWhenCancelling);
delete alertWindow;
} }
bool ThreadWithProgressWindow::runThread (const int priority) bool ThreadWithProgressWindow::runThread (const int priority)
@@ -68,14 +73,14 @@ bool ThreadWithProgressWindow::runThread (const int priority)
{ {
const ScopedLock sl (messageLock); const ScopedLock sl (messageLock);
alertWindow.setMessage (message);
alertWindow->setMessage (message);
} }
const bool wasCancelled = alertWindow.runModalLoop() != 0;
const bool wasCancelled = alertWindow->runModalLoop() != 0;
stopThread (timeOutMsWhenCancelling); stopThread (timeOutMsWhenCancelling);
alertWindow.setVisible (false);
alertWindow->setVisible (false);
return ! wasCancelled; return ! wasCancelled;
} }
@@ -96,13 +101,13 @@ void ThreadWithProgressWindow::timerCallback()
if (! isThreadRunning()) if (! isThreadRunning())
{ {
// thread has finished normally.. // thread has finished normally..
alertWindow.exitModalState (0);
alertWindow.setVisible (false);
alertWindow->exitModalState (0);
alertWindow->setVisible (false);
} }
else else
{ {
const ScopedLock sl (messageLock); const ScopedLock sl (messageLock);
alertWindow.setMessage (message);
alertWindow->setMessage (message);
} }
} }


+ 1
- 1
src/juce_appframework/gui/components/windows/juce_ThreadWithProgressWindow.h View File

@@ -155,7 +155,7 @@ private:
void timerCallback(); void timerCallback();
double progress; double progress;
AlertWindow alertWindow;
AlertWindow* alertWindow;
String message; String message;
CriticalSection messageLock; CriticalSection messageLock;
const int timeOutMsWhenCancelling; const int timeOutMsWhenCancelling;


+ 24
- 0
src/juce_appframework/gui/graphics/geometry/juce_Rectangle.cpp View File

@@ -106,6 +106,30 @@ void Rectangle::setSize (const int w_,
h = h_; h = h_;
} }
void Rectangle::setLeft (const int newLeft) throw()
{
w = jmax (0, x + w - newLeft);
x = newLeft;
}
void Rectangle::setTop (const int newTop) throw()
{
h = jmax (0, y + h - newTop);
y = newTop;
}
void Rectangle::setRight (const int newRight) throw()
{
x = jmin (x, newRight);
w = newRight - x;
}
void Rectangle::setBottom (const int newBottom) throw()
{
y = jmin (y, newBottom);
h = newBottom - y;
}
void Rectangle::translate (const int dx, void Rectangle::translate (const int dx,
const int dy) throw() const int dy) throw()
{ {


+ 22
- 0
src/juce_appframework/gui/graphics/geometry/juce_Rectangle.h View File

@@ -102,6 +102,28 @@ public:
void setBounds (const int newX, const int newY, void setBounds (const int newX, const int newY,
const int newWidth, const int newHeight) throw(); const int newWidth, const int newHeight) throw();
/** Moves the x position, adjusting the width so that the right-hand edge remains in the same place.
If the x is moved to be on the right of the current right-hand edge, the width will be set to zero.
*/
void setLeft (const int newLeft) throw();
/** Moves the y position, adjusting the height so that the bottom edge remains in the same place.
If the y is moved to be below the current bottom edge, the height will be set to zero.
*/
void setTop (const int newTop) throw();
/** Adjusts the width so that the right-hand edge of the rectangle has this new value.
If the new right is below the current X value, the X will be pushed down to match it.
@see getRight
*/
void setRight (const int newRight) throw();
/** Adjusts the height so that the bottom edge of the rectangle has this new value.
If the new bottom is lower than the current Y value, the Y will be pushed down to match it.
@see getBottom
*/
void setBottom (const int newBottom) throw();
/** Moves the rectangle's position by adding amount to its x and y co-ordinates. */ /** Moves the rectangle's position by adding amount to its x and y co-ordinates. */
void translate (const int deltaX, void translate (const int deltaX,
const int deltaY) throw(); const int deltaY) throw();


Loading…
Cancel
Save