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>"; };
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>"; };
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; };
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; };
@@ -1080,13 +1080,13 @@
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>"; };
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>"; };
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>"; };
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>"; };
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>"; };
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>"; };
@@ -1210,6 +1210,7 @@
84A4899708A22E4A00752A2B /* juce_core */,
84A4881C08A22E2400752A2B /* mac specific code */,
);
lineEnding = 2;
name = Source;
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)
{
const MessageManagerLock mml;
buttonPressed ((ButtonType) buttonNum, totalValues > 0);
break;
}


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

@@ -44,6 +44,7 @@ public:
bool isBold, isItalic;
float fontSize, totalSize, ascent;
int refCount;
NSMutableDictionary* attributes;
FontHelper (const String& name_,
const bool bold_,
@@ -56,10 +57,23 @@ public:
fontSize (size_),
refCount (1)
{
attributes = [[NSMutableDictionary dictionaryWithObject: [NSNumber numberWithInt: 0]
forKey: NSLigatureAttributeName] retain];
font = [NSFont fontWithName: juceStringToNS (name_) size: size_];
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_)
font = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSBoldFontMask];
@@ -73,6 +87,7 @@ public:
~FontHelper()
{
[font release];
[attributes release];
}
bool getPathAndKerning (const juce_wchar char1,
@@ -90,10 +105,9 @@ public:
String chars;
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];
NSTextContainer* textContainer = [[[NSTextContainer alloc] init] autorelease];
[layoutManager addTextContainer: textContainer];


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

@@ -212,11 +212,16 @@ public:
void updateMenus()
{
if (Time::getMillisecondCounter() > lastUpdateTime + 500)
{
const MessageManagerLock mml;
menuBarItemsChanged (0);
}
}
void invoke (const int commandId, ApplicationCommandManager* const commandManager, const int topLevelIndex) const
{
const MessageManagerLock mml;
if (currentModel != 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)
{
const MessageManagerLock mml;
JUCEApplication::getInstance()->systemRequestedQuit();
return NSTerminateCancel;
}
@@ -72,6 +73,7 @@ public:
{
if (JUCEApplication::getInstance() != 0)
{
const MessageManagerLock mml;
JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce (filename));
return YES;
}
@@ -86,19 +88,31 @@ public:
files.add (nsStringToJuce ((NSString*) [filenames objectAtIndex: i]));
if (files.size() > 0 && JUCEApplication::getInstance() != 0)
{
const MessageManagerLock mml;
JUCEApplication::getInstance()->anotherInstanceStarted (files.joinIntoString (T(" ")));
}
}
virtual void focusChanged()
{
const MessageManagerLock mml;
juce_HandleProcessFocusChange();
}
virtual void deliverMessage (void* message)
{
// no need for an mm lock here - deliverMessage locks it
MessageManager::getInstance()->deliverMessage (message);
}
virtual void performCallback (CallbackMessagePayload* pl)
{
const MessageManagerLock mml;
pl->result = (*pl->function) (pl->parameter);
pl->hasBeenExecuted = true;
}
virtual void deleteSelf()
{
delete this;
@@ -227,10 +241,7 @@ static bool flushingMessages = false;
CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes];
if (pl != 0)
{
pl->result = (*pl->function) (pl->parameter);
pl->hasBeenExecuted = true;
}
redirector->performCallback (pl);
}
else
{
@@ -249,7 +260,6 @@ static JuceAppDelegate* juceAppDelegate = 0;
void MessageManager::runDispatchLoop()
{
const ScopedAutoReleasePool pool;
MessageManagerLock mml;
// must only be called by the message thread!
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;
- (BOOL) canBecomeKeyWindow;
- (void) becomeKeyWindow;
- (BOOL) windowShouldClose: (id) window;
- (NSRect) constrainFrameRect: (NSRect) frameRect toScreen: (NSScreen*) screen;
- (NSSize) windowWillResize: (NSWindow*) window toSize: (NSSize) proposedFrameSize;
@@ -428,6 +429,14 @@ END_JUCE_NAMESPACE
return owner != 0 && owner->canBecomeKeyWindow();
}
- (void) becomeKeyWindow
{
[super becomeKeyWindow];
if (owner != 0)
owner->grabFocus();
}
- (BOOL) windowShouldClose: (id) window
{
return owner == 0 || owner->windowShouldClose();
@@ -909,6 +918,8 @@ NSRect NSViewComponentPeer::constrainRect (NSRect r)
{
if (constrainer != 0)
{
const MessageManagerLock mml;
NSRect current = [window frame];
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 makeFirstResponder: view];
viewFocusGain();
}
}
@@ -1133,6 +1146,8 @@ void NSViewComponentPeer::textInputRequired (int /*x*/, int /*y*/)
bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown)
{
const MessageManagerLock mml;
String unicode (nsStringToJuce ([ev characters]));
String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers]));
int keyCode = getKeyCodeFromEvent (ev);
@@ -1172,6 +1187,7 @@ bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown)
bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev)
{
const MessageManagerLock mml;
updateKeysDown (ev, true);
bool used = handleKeyEvent (ev, true);
@@ -1187,12 +1203,14 @@ bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev)
bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev)
{
const MessageManagerLock mml;
updateKeysDown (ev, false);
return handleKeyEvent (ev, false);
}
void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev)
{
const MessageManagerLock mml;
updateModifiers (ev);
handleModifierKeysChange();
}
@@ -1200,6 +1218,7 @@ void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev)
#if MACOS_10_4_OR_EARLIER
bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev)
{
const MessageManagerLock mml;
if ([ev type] == NSKeyDown)
return redirectKeyDown (ev);
else if ([ev type] == NSKeyUp)
@@ -1212,6 +1231,7 @@ bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev)
//==============================================================================
void NSViewComponentPeer::redirectMouseDown (NSEvent* ev)
{
const MessageManagerLock mml;
updateModifiers (ev);
currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]);
int x, y;
@@ -1222,6 +1242,7 @@ void NSViewComponentPeer::redirectMouseDown (NSEvent* ev)
void NSViewComponentPeer::redirectMouseUp (NSEvent* ev)
{
const MessageManagerLock mml;
const int oldMods = currentModifiers;
updateModifiers (ev);
currentModifiers &= ~getModifierForButtonNumber ([ev buttonNumber]);
@@ -1233,6 +1254,7 @@ void NSViewComponentPeer::redirectMouseUp (NSEvent* ev)
void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev)
{
const MessageManagerLock mml;
updateModifiers (ev);
currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]);
int x, y;
@@ -1243,6 +1265,7 @@ void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev)
void NSViewComponentPeer::redirectMouseMove (NSEvent* ev)
{
const MessageManagerLock mml;
updateModifiers (ev);
int x, y;
getMousePos (ev, view, x, y);
@@ -1252,6 +1275,7 @@ void NSViewComponentPeer::redirectMouseMove (NSEvent* ev)
void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev)
{
const MessageManagerLock mml;
updateModifiers (ev);
int x, y;
getMousePos (ev, view, x, y);
@@ -1261,6 +1285,7 @@ void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev)
void NSViewComponentPeer::redirectMouseExit (NSEvent* ev)
{
const MessageManagerLock mml;
updateModifiers (ev);
int x, y;
getMousePos (ev, view, x, y);
@@ -1270,6 +1295,7 @@ void NSViewComponentPeer::redirectMouseExit (NSEvent* ev)
void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev)
{
const MessageManagerLock mml;
updateModifiers (ev);
handleMouseWheel (roundFloatToInt ([ev deltaX] * 10.0f),
@@ -1280,6 +1306,8 @@ void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev)
//==============================================================================
BOOL NSViewComponentPeer::sendDragCallback (int type, id <NSDraggingInfo> sender)
{
const MessageManagerLock mml;
NSString* bestType
= [[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)
return;
const MessageManagerLock mml;
const float y = [view frame].size.height - (r.origin.y + r.size.height);
JuceNSImage temp ((int) (r.size.width + 0.5f),
@@ -1363,6 +1392,8 @@ void NSViewComponentPeer::drawRect (NSRect r)
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.
return JUCEApplication::getInstance() != 0
|| (isValidPeer (this) && getComponent()->getWantsKeyboardFocus());
@@ -1370,6 +1401,8 @@ bool NSViewComponentPeer::canBecomeKeyWindow()
bool NSViewComponentPeer::windowShouldClose()
{
const MessageManagerLock mml;
if (! isValidPeer (this))
return YES;
@@ -1379,6 +1412,7 @@ bool NSViewComponentPeer::windowShouldClose()
void NSViewComponentPeer::redirectMovedOrResized()
{
const MessageManagerLock mml;
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"];
const MessageManagerLock mml;
if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString])))
[listener use];
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)
{
const MessageManagerLock mml;
if (m.message == specialId
&& 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");

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

LookAndFeel::clearDefaultLookAndFeel();
}

delete MessageManager::getInstance();

LookAndFeel::clearDefaultLookAndFeel();
shutdownJuce_NonGUI();

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

input->getNextAudioBlock (readInfo);

if (ratio > 1.0)
if (ratio > 1.0001)
{
// 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..

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

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
{
*outCurrentBeat = 0;
*outCurrentTempo = 120.0;
if (outCurrentBeat != 0)
*outCurrentBeat = 0;

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

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

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
{
*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;
@@ -36771,7 +36801,8 @@ MessageManager::MessageManager() throw()
quitMessagePosted (false),
quitMessageReceived (false)
{
currentLockingThreadId = messageThreadId = Thread::getCurrentThreadId();
currentLockingThreadId = 0;
messageThreadId = Thread::getCurrentThreadId();
}

MessageManager::~MessageManager() throw()
@@ -38879,9 +38910,14 @@ bool Component::isCurrentlyBlockedByAnotherModalComponent() const throw()
&& ! 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;
}
@@ -51957,7 +51993,9 @@ void TreeView::paint (Graphics& g)
void TreeView::resized()
{
viewport->setBounds (0, 0, getWidth(), getHeight());

itemsChanged();
handleAsyncUpdate();
}

void TreeView::moveSelectedRow (int delta)
@@ -56283,6 +56321,7 @@ bool KeyPressMappingSet::keyStateChanged (Component* originatingComponent)
{
keyPressEntryIndex = k;
wasDown = true;
used = true;
break;
}
}
@@ -60278,78 +60317,104 @@ void LookAndFeel::changeToggleButtonWidthToFitText (ToggleButton& button)
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,
AlertWindow& alert,
const Rectangle& textArea,
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;
Justification alignment (Justification::horizontallyCentred);

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

if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2)
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
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;
alignment = Justification::left;
@@ -60358,10 +60423,8 @@ void LookAndFeel::drawAlertBox (Graphics& g,
g.setColour (alert.findColour (AlertWindow::textColourId));

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);

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

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

setMessage (message);

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

lookAndFeelChanged();

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

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

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

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

int run() const
{
@@ -71774,37 +71836,19 @@ struct AlertWindowInfo
private:
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)
@@ -71816,7 +71860,8 @@ private:
void AlertWindow::showMessageBox (AlertIconType iconType,
const String& title,
const String& message,
const String& buttonText)
const String& buttonText,
Component* associatedComponent)
{
AlertWindowInfo info;
info.title = title;
@@ -71824,6 +71869,7 @@ void AlertWindow::showMessageBox (AlertIconType iconType,
info.button1 = buttonText.isEmpty() ? TRANS("ok") : buttonText;
info.iconType = iconType;
info.numButtons = 1;
info.associatedComponent = associatedComponent;

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

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

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

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

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

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

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

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

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

stopThread (timeOutMsWhenCancelling);

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

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

@@ -87373,6 +87427,30 @@ void Rectangle::setSize (const int w_,
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,
const int dy) throw()
{
@@ -242157,6 +242235,8 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages

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

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

#endif

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

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

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

- (void) becomeKeyWindow
{
[super becomeKeyWindow];

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

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

NSRect current = [window frame];
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 makeFirstResponder: view];

viewFocusGain();
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

NSString* bestType
= [[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)
return;

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

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

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.
return JUCEApplication::getInstance() != 0
|| (isValidPeer (this) && getComponent()->getWantsKeyboardFocus());
@@ -267284,6 +267394,8 @@ bool NSViewComponentPeer::canBecomeKeyWindow()

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

if (! isValidPeer (this))
return YES;

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

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

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

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

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

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

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

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

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

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_)
font = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSBoldFontMask];
@@ -269531,6 +269664,7 @@ public:
~FontHelper()
{
[font release];
[attributes release];
}

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

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

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

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

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

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

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

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

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

const MessageManagerLock mml;

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


+ 76
- 16
juce_amalgamated.h View File

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

/********* 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__

@@ -17747,6 +17747,28 @@ public:
void setBounds (const int newX, const int newY,
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. */
void translate (const int deltaX,
const int deltaY) throw();
@@ -22451,12 +22473,23 @@ public:
*/
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
from receiving messages.
@@ -37764,7 +37797,7 @@ typedef void* (MessageCallbackFunction) (void* userData);

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

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

juce_UseDebuggingNewOperator

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

friend class MessageListener;
friend class ChangeBroadcaster;
@@ -50522,10 +50556,14 @@ public:
@param message a longer, more descriptive message to show underneath the
headline
@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,
const String& message,
AlertIconType iconType);
AlertIconType iconType,
Component* associatedComponent = 0);

/** Destroys the AlertWindow */
~AlertWindow();
@@ -50670,11 +50708,15 @@ public:
headline
@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.
@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,
const String& title,
const String& message,
const String& buttonText = String::empty);
const String& buttonText = String::empty,
Component* associatedComponent = 0);

/** 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
empty, the default string "cancel" (or a localised version of it)
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,
const String& title,
const String& message,
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.

@@ -50715,6 +50761,9 @@ public:
"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
"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:
- 0 if the third button was pressed (normally used for 'cancel')
@@ -50726,7 +50775,8 @@ public:
const String& message,
const String& button1Text = 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.

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

void updateLayout (const bool onlyIncreaseSize);

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

double progress;
AlertWindow alertWindow;
AlertWindow* alertWindow;
String message;
CriticalSection messageLock;
const int timeOutMsWhenCancelling;
@@ -53196,8 +53247,17 @@ public:
const bool isMouseOverButton,
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,
AlertWindow& alert,
const Rectangle& textArea,
@@ -54173,7 +54233,7 @@ private:

#endif

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

#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");
// 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
MessageManager::getInstance()->registerBroadcastListener (app);
@@ -242,6 +246,7 @@ int JUCEApplication::shutdownAppAndClearUp()
JUCE_TRY
{
// give the app a chance to clean up..
const MessageManagerLock mml;
app->shutdown();
}
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS
@@ -340,9 +345,15 @@ void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI()
#if JUCE_MAC
const ScopedAutoReleasePool pool;
#endif
DeletedAtShutdown::deleteAll();
{
const MessageManagerLock mml;
DeletedAtShutdown::deleteAll();
LookAndFeel::clearDefaultLookAndFeel();
}
delete MessageManager::getInstance();
LookAndFeel::clearDefaultLookAndFeel();
shutdownJuce_NonGUI();
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);
if (ratio > 1.0)
if (ratio > 1.0001)
{
// 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..


+ 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))
{
*outCurrentBeat = result.ppqPosition;
*outCurrentTempo = result.bpm;
if (outCurrentBeat != 0)
*outCurrentBeat = result.ppqPosition;
if (outCurrentTempo != 0)
*outCurrentTempo = result.bpm;
}
else
{
*outCurrentBeat = 0;
*outCurrentTempo = 120.0;
if (outCurrentBeat != 0)
*outCurrentBeat = 0;
if (outCurrentTempo != 0)
*outCurrentTempo = 120.0;
}
return noErr;
@@ -752,18 +758,31 @@ OSStatus AudioUnitPluginInstance::getMusicalTimeLocation (UInt32* outDeltaSample
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
{
*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;


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

@@ -57,7 +57,8 @@ MessageManager::MessageManager() throw()
quitMessagePosted (false),
quitMessageReceived (false)
{
currentLockingThreadId = messageThreadId = Thread::getCurrentThreadId();
currentLockingThreadId = 0;
messageThreadId = Thread::getCurrentThreadId();
}
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
*/
class JUCE_API MessageManager : private DeletedAtShutdown
class JUCE_API MessageManager
{
public:
//==============================================================================
@@ -163,13 +163,14 @@ public:
void deliverMessage (void*);
/** @internal */
void deliverBroadcastMessage (const String&);
/** @internal */
~MessageManager() throw();
//==============================================================================
juce_UseDebuggingNewOperator
private:
MessageManager() throw();
~MessageManager() throw();
friend class MessageListener;
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()
{
viewport->setBounds (0, 0, getWidth(), getHeight());
itemsChanged();
handleAsyncUpdate();
}
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);
}
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;
}


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

@@ -1763,12 +1763,23 @@ public:
*/
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
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;
wasDown = true;
used = true;
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());
}
//==============================================================================
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,
AlertWindow& alert,
const Rectangle& textArea,
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;
Justification alignment (Justification::horizontallyCentred);
const int iconWidth = 80;
int iconSize = jmin (iconWidth + 50, alert.getHeight() + 20);
if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2)
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
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;
alignment = Justification::left;
@@ -545,10 +572,8 @@ void LookAndFeel::drawAlertBox (Graphics& g,
g.setColour (alert.findColour (AlertWindow::textColourId));
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);
g.setColour (alert.findColour (AlertWindow::outlineColourId));
@@ -571,6 +596,7 @@ const Font LookAndFeel::getAlertWindowFont()
return Font (12.0f);
}
//==============================================================================
void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar,
int width, int height,
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 "../controls/juce_Slider.h"
#include "../layout/juce_TabbedComponent.h"
#include "../windows/juce_AlertWindow.h"
class ToggleButton;
class TextButton;
@@ -175,8 +176,17 @@ public:
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,
AlertWindow& alert,
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,
const String& message,
AlertIconType iconType)
AlertIconType iconType,
Component* associatedComponent_)
: TopLevelWindow (title, true),
alertIconType (iconType)
alertIconType (iconType),
associatedComponent (associatedComponent_)
{
if (message.isEmpty())
text = T(" "); // to force an update if the message is empty
setMessage (message);
#if JUCE_MAC
setAlwaysOnTop (true);
#else
for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;)
{
Component* const c = Desktop::getInstance().getComponent (i);
@@ -112,7 +111,6 @@ AlertWindow::AlertWindow (const String& title,
break;
}
}
#endif
lookAndFeelChanged();
@@ -470,7 +468,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
if (! isVisible())
{
centreAroundComponent (0, w, h);
centreAroundComponent (associatedComponent, w, h);
}
else
{
@@ -588,7 +586,7 @@ void AlertWindow::lookAndFeelChanged()
const int flags = getLookAndFeel().getAlertBoxWindowFlags();
setUsingNativeTitleBar ((flags & ComponentPeer::windowHasTitleBar) != 0);
setDropShadowEnabled ((flags & ComponentPeer::windowHasDropShadow) != 0);
setDropShadowEnabled (isOpaque() && (flags & ComponentPeer::windowHasDropShadow) != 0);
}
int AlertWindow::getDesktopWindowStyleFlags() const
@@ -602,6 +600,7 @@ struct AlertWindowInfo
String title, message, button1, button2, button3;
AlertWindow::AlertIconType iconType;
int numButtons;
Component* associatedComponent;
int run() const
{
@@ -612,37 +611,19 @@ struct AlertWindowInfo
private:
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)
@@ -654,7 +635,8 @@ private:
void AlertWindow::showMessageBox (AlertIconType iconType,
const String& title,
const String& message,
const String& buttonText)
const String& buttonText,
Component* associatedComponent)
{
AlertWindowInfo info;
info.title = title;
@@ -662,6 +644,7 @@ void AlertWindow::showMessageBox (AlertIconType iconType,
info.button1 = buttonText.isEmpty() ? TRANS("ok") : buttonText;
info.iconType = iconType;
info.numButtons = 1;
info.associatedComponent = associatedComponent;
info.run();
}
@@ -670,7 +653,8 @@ bool AlertWindow::showOkCancelBox (AlertIconType iconType,
const String& title,
const String& message,
const String& button1Text,
const String& button2Text)
const String& button2Text,
Component* associatedComponent)
{
AlertWindowInfo info;
info.title = title;
@@ -679,6 +663,7 @@ bool AlertWindow::showOkCancelBox (AlertIconType iconType,
info.button2 = button2Text.isEmpty() ? TRANS("cancel") : button2Text;
info.iconType = iconType;
info.numButtons = 2;
info.associatedComponent = associatedComponent;
return info.run() != 0;
}
@@ -688,7 +673,8 @@ int AlertWindow::showYesNoCancelBox (AlertIconType iconType,
const String& message,
const String& button1Text,
const String& button2Text,
const String& button3Text)
const String& button3Text,
Component* associatedComponent)
{
AlertWindowInfo info;
info.title = title;
@@ -698,6 +684,7 @@ int AlertWindow::showYesNoCancelBox (AlertIconType iconType,
info.button3 = button3Text.isEmpty() ? TRANS("cancel") : button3Text;
info.iconType = iconType;
info.numButtons = 3;
info.associatedComponent = associatedComponent;
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
headline
@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,
const String& message,
AlertIconType iconType);
AlertIconType iconType,
Component* associatedComponent = 0);
/** Destroys the AlertWindow */
~AlertWindow();
@@ -234,11 +238,15 @@ public:
headline
@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.
@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,
const String& title,
const String& message,
const String& buttonText = String::empty);
const String& buttonText = String::empty,
Component* associatedComponent = 0);
/** 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
empty, the default string "cancel" (or a localised version of it)
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,
const String& title,
const String& message,
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.
@@ -279,7 +291,10 @@ public:
"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
"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:
- 0 if the third button was pressed (normally used for 'cancel')
- 1 if the first button was pressed (normally used for 'yes')
@@ -290,7 +305,8 @@ public:
const String& message,
const String& button1Text = 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.
@@ -353,6 +369,7 @@ private:
VoidArray progressBars, customComps, textBlocks, allComps;
StringArray textboxNames, comboBoxNames;
Font font;
Component* associatedComponent;
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 "../lookandfeel/juce_LookAndFeel.h"
#include "../../../../juce_core/text/juce_LocalisedStrings.h"
@@ -46,19 +47,23 @@ ThreadWithProgressWindow::ThreadWithProgressWindow (const String& title,
const String& cancelButtonText)
: Thread ("Juce Progress Window"),
progress (0.0),
alertWindow (title, String::empty, AlertWindow::NoIcon),
timeOutMsWhenCancelling (timeOutMsWhenCancelling_)
{
alertWindow = LookAndFeel::getDefaultLookAndFeel()
.createAlertWindow (title, String::empty, cancelButtonText, String::empty, String::empty,
AlertWindow::NoIcon, 1, 0);
if (hasProgressBar)
alertWindow.addProgressBarComponent (progress);
alertWindow->addProgressBarComponent (progress);
if (hasCancelButton)
alertWindow.addButton (cancelButtonText, 1);
alertWindow->addButton (cancelButtonText, 1);
}
ThreadWithProgressWindow::~ThreadWithProgressWindow()
{
stopThread (timeOutMsWhenCancelling);
delete alertWindow;
}
bool ThreadWithProgressWindow::runThread (const int priority)
@@ -68,14 +73,14 @@ bool ThreadWithProgressWindow::runThread (const int priority)
{
const ScopedLock sl (messageLock);
alertWindow.setMessage (message);
alertWindow->setMessage (message);
}
const bool wasCancelled = alertWindow.runModalLoop() != 0;
const bool wasCancelled = alertWindow->runModalLoop() != 0;
stopThread (timeOutMsWhenCancelling);
alertWindow.setVisible (false);
alertWindow->setVisible (false);
return ! wasCancelled;
}
@@ -96,13 +101,13 @@ void ThreadWithProgressWindow::timerCallback()
if (! isThreadRunning())
{
// thread has finished normally..
alertWindow.exitModalState (0);
alertWindow.setVisible (false);
alertWindow->exitModalState (0);
alertWindow->setVisible (false);
}
else
{
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();
double progress;
AlertWindow alertWindow;
AlertWindow* alertWindow;
String message;
CriticalSection messageLock;
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_;
}
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,
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,
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. */
void translate (const int deltaX,
const int deltaY) throw();


Loading…
Cancel
Save