diff --git a/build/win32/platform_specific_code/juce_win32_Messaging.cpp b/build/win32/platform_specific_code/juce_win32_Messaging.cpp index 9f5abb0436..2915536967 100644 --- a/build/win32/platform_specific_code/juce_win32_Messaging.cpp +++ b/build/win32/platform_specific_code/juce_win32_Messaging.cpp @@ -162,7 +162,7 @@ static BOOL CALLBACK BroadcastEnumWindowProc (HWND hwnd, LPARAM lParam) return TRUE; } -void MessageManager::broadcastMessage (const String& value) +void MessageManager::broadcastMessage (const String& value) throw() { VoidArray windows; EnumWindows (&BroadcastEnumWindowProc, (LPARAM) &windows); diff --git a/extras/juce demo/src/demos/TreeViewDemo.cpp b/extras/juce demo/src/demos/TreeViewDemo.cpp index fd1443d3bb..f285edd1f4 100644 --- a/extras/juce demo/src/demos/TreeViewDemo.cpp +++ b/extras/juce demo/src/demos/TreeViewDemo.cpp @@ -209,6 +209,7 @@ public: addAndMakeVisible (treeView = new TreeView()); treeView->setRootItem (rootItem); + treeView->setMultiSelectEnabled (true); resized(); } diff --git a/src/juce_appframework/application/juce_ApplicationProperties.cpp b/src/juce_appframework/application/juce_ApplicationProperties.cpp index aa6737f584..61cc43761c 100644 --- a/src/juce_appframework/application/juce_ApplicationProperties.cpp +++ b/src/juce_appframework/application/juce_ApplicationProperties.cpp @@ -43,7 +43,7 @@ juce_ImplementSingleton (ApplicationProperties) //============================================================================== -ApplicationProperties::ApplicationProperties() +ApplicationProperties::ApplicationProperties() throw() : userProps (0), commonProps (0), msBeforeSaving (3000), @@ -62,7 +62,7 @@ void ApplicationProperties::setStorageParameters (const String& applicationName, const String& fileNameSuffix, const String& folderName_, const int millisecondsBeforeSaving, - const int propertiesFileOptions) + const int propertiesFileOptions) throw() { appName = applicationName; fileSuffix = fileNameSuffix; @@ -116,7 +116,7 @@ bool ApplicationProperties::testWriteAccess (const bool testUserSettings, } //============================================================================== -PropertiesFile* ApplicationProperties::getUserSettings() +PropertiesFile* ApplicationProperties::getUserSettings() throw() { if (userProps == 0) { @@ -138,7 +138,7 @@ PropertiesFile* ApplicationProperties::getUserSettings() return userProps; } -PropertiesFile* ApplicationProperties::getCommonSettings() +PropertiesFile* ApplicationProperties::getCommonSettings() throw() { if (commonProps == 0) { diff --git a/src/juce_appframework/application/juce_ApplicationProperties.h b/src/juce_appframework/application/juce_ApplicationProperties.h index 56dbafe036..362bf818f7 100644 --- a/src/juce_appframework/application/juce_ApplicationProperties.h +++ b/src/juce_appframework/application/juce_ApplicationProperties.h @@ -68,7 +68,7 @@ public: Before using it, you must call setStorageParameters() to give it the info it needs to create the property files. */ - ApplicationProperties(); + ApplicationProperties() throw(); /** Destructor. */ @@ -87,7 +87,7 @@ public: const String& fileNameSuffix, const String& folderName, const int millisecondsBeforeSaving, - const int propertiesFileOptions); + const int propertiesFileOptions) throw(); /** Tests whether the files can be successfully written to, and can show an error message if not. @@ -110,7 +110,7 @@ public: @see getCommonSettings */ - PropertiesFile* getUserSettings(); + PropertiesFile* getUserSettings() throw(); /** Returns the common settings file. @@ -121,7 +121,7 @@ public: @see getUserSettings */ - PropertiesFile* getCommonSettings(); + PropertiesFile* getCommonSettings() throw(); //============================================================================== /** Saves both files if they need to be saved. diff --git a/src/juce_appframework/application/juce_PropertiesFile.cpp b/src/juce_appframework/application/juce_PropertiesFile.cpp index d478bdebdf..827621effb 100644 --- a/src/juce_appframework/application/juce_PropertiesFile.cpp +++ b/src/juce_appframework/application/juce_PropertiesFile.cpp @@ -55,7 +55,7 @@ static const tchar* const propertyTagName = T("VALUE"); //============================================================================== PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSaving, - const int options_) + const int options_) throw() : PropertySet (ignoreCaseOfKeyNames), file (f), timerInterval (millisecondsBeforeSaving), diff --git a/src/juce_appframework/application/juce_PropertiesFile.h b/src/juce_appframework/application/juce_PropertiesFile.h index 29b7861a23..9c7835352e 100644 --- a/src/juce_appframework/application/juce_PropertiesFile.h +++ b/src/juce_appframework/application/juce_PropertiesFile.h @@ -85,7 +85,7 @@ public: */ PropertiesFile (const File& file, const int millisecondsBeforeSaving, - const int options); + const int options) throw(); /** Destructor. diff --git a/src/juce_appframework/events/juce_ChangeListenerList.cpp b/src/juce_appframework/events/juce_ChangeListenerList.cpp index 9d32a470ef..66f280958d 100644 --- a/src/juce_appframework/events/juce_ChangeListenerList.cpp +++ b/src/juce_appframework/events/juce_ChangeListenerList.cpp @@ -69,7 +69,7 @@ void ChangeListenerList::removeAllChangeListeners() throw() listeners.clear(); } -void ChangeListenerList::sendChangeMessage (void* objectThatHasChanged) throw() +void ChangeListenerList::sendChangeMessage (void* const objectThatHasChanged) throw() { const ScopedLock sl (lock); @@ -86,7 +86,7 @@ void ChangeListenerList::handleMessage (const Message& message) sendSynchronousChangeMessage (message.pointerParameter); } -void ChangeListenerList::sendSynchronousChangeMessage (void* objectThatHasChanged) +void ChangeListenerList::sendSynchronousChangeMessage (void* const objectThatHasChanged) { const ScopedLock sl (lock); messagePending = false; diff --git a/src/juce_appframework/events/juce_MessageManager.cpp b/src/juce_appframework/events/juce_MessageManager.cpp index 9f2ece0324..1040c4a0e1 100644 --- a/src/juce_appframework/events/juce_MessageManager.cpp +++ b/src/juce_appframework/events/juce_MessageManager.cpp @@ -201,19 +201,14 @@ bool MessageManager::runDispatchLoop() //============================================================================== void MessageManager::postQuitMessage (const bool useMaximumForce) { - if (! quitMessagePosted) - { - Message* const m = new Message (quitMessageId, (useMaximumForce) ? 1 : 0, 0, 0); - m->messageRecipient = 0; - - if (! juce_postMessageToSystemQueue (m)) - delete m; + Message* const m = new Message (quitMessageId, (useMaximumForce) ? 1 : 0, 0, 0); + m->messageRecipient = 0; + postMessageToQueue (m); - quitMessagePosted = true; - } + quitMessagePosted = true; } -bool MessageManager::hasQuitMessageBeenPosted() const +bool MessageManager::hasQuitMessageBeenPosted() const throw() { return quitMessagePosted; } @@ -221,13 +216,11 @@ bool MessageManager::hasQuitMessageBeenPosted() const //============================================================================== void MessageManager::deliverBroadcastMessage (const String& value) { - if (broadcastListeners == 0) - broadcastListeners = new ActionListenerList(); - - broadcastListeners->sendActionMessage (value); + if (broadcastListeners != 0) + broadcastListeners->sendActionMessage (value); } -void MessageManager::registerBroadcastListener (ActionListener* listener) +void MessageManager::registerBroadcastListener (ActionListener* const listener) throw() { if (broadcastListeners == 0) broadcastListeners = new ActionListenerList(); @@ -235,24 +228,22 @@ void MessageManager::registerBroadcastListener (ActionListener* listener) broadcastListeners->addActionListener (listener); } -void MessageManager::deregisterBroadcastListener (ActionListener* listener) +void MessageManager::deregisterBroadcastListener (ActionListener* const listener) throw() { - if (broadcastListeners == 0) - broadcastListeners = new ActionListenerList(); - - broadcastListeners->removeActionListener (listener); + if (broadcastListeners != 0) + broadcastListeners->removeActionListener (listener); } //============================================================================== // This gets called occasionally by the timer thread (to save using an extra thread // for it). -void MessageManager::inactivityCheckCallback() +void MessageManager::inactivityCheckCallback() throw() { if (instance != 0) instance->inactivityCheckCallbackInt(); } -void MessageManager::inactivityCheckCallbackInt() +void MessageManager::inactivityCheckCallbackInt() throw() { const unsigned int now = Time::getApproximateMillisecondCounter(); @@ -277,7 +268,7 @@ void MessageManager::inactivityCheckCallbackInt() } } -void MessageManager::delayWaitCursor() +void MessageManager::delayWaitCursor() throw() { if (instance != 0) { @@ -291,7 +282,7 @@ void MessageManager::delayWaitCursor() } } -void MessageManager::setTimeBeforeShowingWaitCursor (const int millisecs) +void MessageManager::setTimeBeforeShowingWaitCursor (const int millisecs) throw() { // if this is a bit too small you'll get a lot of unwanted hourglass cursors.. jassert (millisecs <= 0 || millisecs > 200); @@ -311,22 +302,22 @@ void MessageManager::timerCallback() ++messageCounter; } -int MessageManager::getTimeBeforeShowingWaitCursor() const +int MessageManager::getTimeBeforeShowingWaitCursor() const throw() { return timeBeforeWaitCursor; } -bool MessageManager::isThisTheMessageThread() const +bool MessageManager::isThisTheMessageThread() const throw() { return Thread::getCurrentThreadId() == messageThreadId; } -void MessageManager::setCurrentMessageThread (const int threadId) +void MessageManager::setCurrentMessageThread (const int threadId) throw() { messageThreadId = threadId; } -bool MessageManager::currentThreadHasLockedMessageManager() const +bool MessageManager::currentThreadHasLockedMessageManager() const throw() { return Thread::getCurrentThreadId() == currentLockingThreadId; } diff --git a/src/juce_appframework/events/juce_MessageManager.h b/src/juce_appframework/events/juce_MessageManager.h index e7514fe761..8a8e47e47f 100644 --- a/src/juce_appframework/events/juce_MessageManager.h +++ b/src/juce_appframework/events/juce_MessageManager.h @@ -106,14 +106,14 @@ public: void* userData); /** Returns true if the caller-thread is the message thread. */ - bool isThisTheMessageThread() const; + bool isThisTheMessageThread() const throw(); /** Called to tell the manager which thread is the one that's running the dispatch loop. (Best to ignore this method unless you really know what you're doing..) @see getCurrentMessageThread */ - void setCurrentMessageThread (const int threadId); + void setCurrentMessageThread (const int threadId) throw(); /** Returns the ID of the current message thread, as set by setCurrentMessageThread(). @@ -129,7 +129,7 @@ public: This will be true if the caller is the message thread, because that automatically gains a lock while a message is being dispatched. */ - bool currentThreadHasLockedMessageManager() const; + bool currentThreadHasLockedMessageManager() const throw(); //============================================================================== /** Sends a message to all other JUCE applications that are running. @@ -138,7 +138,7 @@ public: method of the broadcast listeners in the other app. @see registerBroadcastListener, ActionListener */ - static void broadcastMessage (const String& messageText); + static void broadcastMessage (const String& messageText) throw(); /** Registers a listener to get told about broadcast messages. @@ -147,10 +147,10 @@ public: @see broadcastMessage */ - void registerBroadcastListener (ActionListener* listener); + void registerBroadcastListener (ActionListener* listener) throw(); /** Deregisters a broadcast listener. */ - void deregisterBroadcastListener (ActionListener* listener); + void deregisterBroadcastListener (ActionListener* listener) throw(); //============================================================================== /** Sets a time-limit for the app to be 'busy' before an hourglass cursor will be shown. @@ -160,24 +160,24 @@ public: Mac the system might still decide to show it after a while). @see MouseCursor::showWaitCursor */ - void setTimeBeforeShowingWaitCursor (const int millisecs); + void setTimeBeforeShowingWaitCursor (const int millisecs) throw(); /** Returns the time-out before the 'busy' cursor is shown when the app is busy. @see setTimeBeforeShowingWaitCursor, MouseCursor::showWaitCursor */ - int getTimeBeforeShowingWaitCursor() const; + int getTimeBeforeShowingWaitCursor() const throw(); /** Tells the message manager that the system isn't locked-up, even if the message loop isn't active. Used internally, this is handy when an OS enters its own modal loop. */ - static void delayWaitCursor(); + static void delayWaitCursor() throw(); //============================================================================== /** Returns true if JUCEApplication::quit() has been called. */ - bool hasQuitMessageBeenPosted() const; + bool hasQuitMessageBeenPosted() const throw(); //============================================================================== /** @internal */ @@ -219,8 +219,8 @@ private: static void doPlatformSpecificShutdown(); friend class InternalTimerThread; - static void inactivityCheckCallback(); - void inactivityCheckCallbackInt(); + static void inactivityCheckCallback() throw(); + void inactivityCheckCallbackInt() throw(); friend class MessageManagerLock; CriticalSection messageDispatchLock; diff --git a/src/juce_appframework/gui/components/controls/juce_TreeView.cpp b/src/juce_appframework/gui/components/controls/juce_TreeView.cpp index 13699f261c..2c1793ea50 100644 --- a/src/juce_appframework/gui/components/controls/juce_TreeView.cpp +++ b/src/juce_appframework/gui/components/controls/juce_TreeView.cpp @@ -58,25 +58,19 @@ public: void mouseDown (const MouseEvent& e) { isDragging = false; + needSelectionOnMouseUp = false; Rectangle pos; TreeViewItem* const item = findItemAt (e.y, pos); if (item != 0 && e.x >= pos.getX()) { - if (item->isSelected() && owner->isMultiSelectEnabled() - && (e.mods.isCommandDown() || e.mods.isCtrlDown())) - { - item->setSelected (false, false); - } + if (! owner->isMultiSelectEnabled()) + item->setSelected (true, true); + else if (item->isSelected()) + needSelectionOnMouseUp = ! e.mods.isPopupMenu(); else - { - item->setSelected (true, - ! (owner->isMultiSelectEnabled() - && (e.mods.isCommandDown() - || e.mods.isCtrlDown() - || e.mods.isShiftDown()))); - } + selectBasedOnModifiers (item, e.mods); MouseEvent e2 (e); e2.x -= pos.getX(); @@ -87,16 +81,22 @@ public: void mouseUp (const MouseEvent& e) { - if (e.mouseWasClicked()) - { - Rectangle pos; - TreeViewItem* const item = findItemAt (e.y, pos); + Rectangle pos; + TreeViewItem* const item = findItemAt (e.y, pos); - if (item != 0 - && e.x >= pos.getX() - owner->getIndentSize() - && e.x < pos.getX()) + if (item != 0 && e.mouseWasClicked()) + { + if (needSelectionOnMouseUp) + { + selectBasedOnModifiers (item, e.mods); + } + else if (e.mouseWasClicked()) { - item->setOpen (! item->isOpen()); + if (e.x >= pos.getX() - owner->getIndentSize() + && e.x < pos.getX()) + { + item->setOpen (! item->isOpen()); + } } } } @@ -258,10 +258,19 @@ private: VoidArray rowComponentItems; Array rowComponentIds; VoidArray rowComponents; - bool isDragging; + bool isDragging, needSelectionOnMouseUp; TreeViewContentComponent (const TreeViewContentComponent&); const TreeViewContentComponent& operator= (const TreeViewContentComponent&); + + static void selectBasedOnModifiers (TreeViewItem* const item, const ModifierKeys& modifiers) + { + const bool shft = modifiers.isShiftDown(); + const bool cmd = modifiers.isCommandDown(); + + item->setSelected (shft || (! cmd) || (cmd && ! item->isSelected()), + ! (shft || cmd)); + } }; //============================================================================== diff --git a/src/juce_core/containers/juce_PropertySet.cpp b/src/juce_core/containers/juce_PropertySet.cpp index 3f501cf278..6bac254d7c 100644 --- a/src/juce_core/containers/juce_PropertySet.cpp +++ b/src/juce_core/containers/juce_PropertySet.cpp @@ -40,7 +40,7 @@ BEGIN_JUCE_NAMESPACE //============================================================================== -PropertySet::PropertySet (const bool ignoreCaseOfKeyNames) +PropertySet::PropertySet (const bool ignoreCaseOfKeyNames) throw() : properties (ignoreCaseOfKeyNames), ignoreCaseOfKeys (ignoreCaseOfKeyNames) { diff --git a/src/juce_core/containers/juce_PropertySet.h b/src/juce_core/containers/juce_PropertySet.h index aaa342d68a..a3ef4da45d 100644 --- a/src/juce_core/containers/juce_PropertySet.h +++ b/src/juce_core/containers/juce_PropertySet.h @@ -55,7 +55,7 @@ public: @param ignoreCaseOfKeyNames if true, the names of properties are compared in a case-insensitive way */ - PropertySet (const bool ignoreCaseOfKeyNames = false); + PropertySet (const bool ignoreCaseOfKeyNames = false) throw(); /** Destructor. */ virtual ~PropertySet();