| @@ -119,7 +119,6 @@ OBJECTS := \ | |||
| $(OBJDIR)/juce_Primes_32e6603.o \ | |||
| $(OBJDIR)/juce_RSAKey_b60982ae.o \ | |||
| $(OBJDIR)/juce_ActionBroadcaster_7f997786.o \ | |||
| $(OBJDIR)/juce_ActionListenerList_9e099ae4.o \ | |||
| $(OBJDIR)/juce_AsyncUpdater_a7e1cb89.o \ | |||
| $(OBJDIR)/juce_ChangeBroadcaster_3eb8fecc.o \ | |||
| $(OBJDIR)/juce_InterprocessConnection_13086b6d.o \ | |||
| @@ -763,11 +762,6 @@ $(OBJDIR)/juce_ActionBroadcaster_7f997786.o: ../../src/events/juce_ActionBroadca | |||
| @echo "Compiling juce_ActionBroadcaster.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_ActionListenerList_9e099ae4.o: ../../src/events/juce_ActionListenerList.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_ActionListenerList.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_AsyncUpdater_a7e1cb89.o: ../../src/events/juce_AsyncUpdater.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_AsyncUpdater.cpp" | |||
| @@ -88,7 +88,6 @@ | |||
| 12E3CC31875A202D6B30F778 = { isa = PBXBuildFile; fileRef = E9E692847C14AD33CD5FB40B; }; | |||
| CF51988743ED2CD823DFE0B5 = { isa = PBXBuildFile; fileRef = 7AE9331938549244E27A5D0E; }; | |||
| 659D9CD58B6914EB420E6AEC = { isa = PBXBuildFile; fileRef = 31D985CB8646B78460E9D5A7; }; | |||
| 5BE4BAA99FDC6F1B3177096F = { isa = PBXBuildFile; fileRef = 5A46476E16BA4F9DA95E9E6A; }; | |||
| 55737E2F1817DE642AA7DA05 = { isa = PBXBuildFile; fileRef = 1617348BBF5D103619D76911; }; | |||
| 6D2C50B0A69855A7F8C062E7 = { isa = PBXBuildFile; fileRef = B80F8CD026033ACCCE11A1A4; }; | |||
| 70EE7A1273945B62B013DB43 = { isa = PBXBuildFile; fileRef = AE68ECB6E063BD8D4984C0B3; }; | |||
| @@ -554,8 +553,6 @@ | |||
| 31D985CB8646B78460E9D5A7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ActionBroadcaster.cpp; path = ../../src/events/juce_ActionBroadcaster.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 09F7685D1EFF472ECB1F5EF1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ActionBroadcaster.h; path = ../../src/events/juce_ActionBroadcaster.h; sourceTree = SOURCE_ROOT; }; | |||
| 4EF8BD4BF46C4BCB39F96609 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ActionListener.h; path = ../../src/events/juce_ActionListener.h; sourceTree = SOURCE_ROOT; }; | |||
| 5A46476E16BA4F9DA95E9E6A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ActionListenerList.cpp; path = ../../src/events/juce_ActionListenerList.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 8269D9DFAD7923EE13E7EEC7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ActionListenerList.h; path = ../../src/events/juce_ActionListenerList.h; sourceTree = SOURCE_ROOT; }; | |||
| 1617348BBF5D103619D76911 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_AsyncUpdater.cpp; path = ../../src/events/juce_AsyncUpdater.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 44DB44953945417F76199479 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_AsyncUpdater.h; path = ../../src/events/juce_AsyncUpdater.h; sourceTree = SOURCE_ROOT; }; | |||
| D04B6E43A037F985434B2F5A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CallbackMessage.h; path = ../../src/events/juce_CallbackMessage.h; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1282,8 +1279,6 @@ | |||
| 31D985CB8646B78460E9D5A7, | |||
| 09F7685D1EFF472ECB1F5EF1, | |||
| 4EF8BD4BF46C4BCB39F96609, | |||
| 5A46476E16BA4F9DA95E9E6A, | |||
| 8269D9DFAD7923EE13E7EEC7, | |||
| 1617348BBF5D103619D76911, | |||
| 44DB44953945417F76199479, | |||
| D04B6E43A037F985434B2F5A, | |||
| @@ -2008,7 +2003,6 @@ | |||
| 12E3CC31875A202D6B30F778, | |||
| CF51988743ED2CD823DFE0B5, | |||
| 659D9CD58B6914EB420E6AEC, | |||
| 5BE4BAA99FDC6F1B3177096F, | |||
| 55737E2F1817DE642AA7DA05, | |||
| 6D2C50B0A69855A7F8C062E7, | |||
| 70EE7A1273945B62B013DB43, | |||
| @@ -422,8 +422,6 @@ | |||
| <File RelativePath="..\..\src\events\juce_ActionBroadcaster.cpp"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionBroadcaster.h"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionListener.h"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionListenerList.cpp"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionListenerList.h"/> | |||
| <File RelativePath="..\..\src\events\juce_AsyncUpdater.cpp"/> | |||
| <File RelativePath="..\..\src\events\juce_AsyncUpdater.h"/> | |||
| <File RelativePath="..\..\src\events\juce_CallbackMessage.h"/> | |||
| @@ -422,8 +422,6 @@ | |||
| <File RelativePath="..\..\src\events\juce_ActionBroadcaster.cpp"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionBroadcaster.h"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionListener.h"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionListenerList.cpp"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionListenerList.h"/> | |||
| <File RelativePath="..\..\src\events\juce_AsyncUpdater.cpp"/> | |||
| <File RelativePath="..\..\src\events\juce_AsyncUpdater.h"/> | |||
| <File RelativePath="..\..\src\events\juce_CallbackMessage.h"/> | |||
| @@ -424,8 +424,6 @@ | |||
| <File RelativePath="..\..\src\events\juce_ActionBroadcaster.cpp"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionBroadcaster.h"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionListener.h"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionListenerList.cpp"/> | |||
| <File RelativePath="..\..\src\events\juce_ActionListenerList.h"/> | |||
| <File RelativePath="..\..\src\events\juce_AsyncUpdater.cpp"/> | |||
| <File RelativePath="..\..\src\events\juce_AsyncUpdater.h"/> | |||
| <File RelativePath="..\..\src\events\juce_CallbackMessage.h"/> | |||
| @@ -202,7 +202,6 @@ | |||
| <ClCompile Include="..\..\src\cryptography\juce_Primes.cpp"/> | |||
| <ClCompile Include="..\..\src\cryptography\juce_RSAKey.cpp"/> | |||
| <ClCompile Include="..\..\src\events\juce_ActionBroadcaster.cpp"/> | |||
| <ClCompile Include="..\..\src\events\juce_ActionListenerList.cpp"/> | |||
| <ClCompile Include="..\..\src\events\juce_AsyncUpdater.cpp"/> | |||
| <ClCompile Include="..\..\src\events\juce_ChangeBroadcaster.cpp"/> | |||
| <ClCompile Include="..\..\src\events\juce_InterprocessConnection.cpp"/> | |||
| @@ -550,7 +549,6 @@ | |||
| <ClInclude Include="..\..\src\cryptography\juce_RSAKey.h"/> | |||
| <ClInclude Include="..\..\src\events\juce_ActionBroadcaster.h"/> | |||
| <ClInclude Include="..\..\src\events\juce_ActionListener.h"/> | |||
| <ClInclude Include="..\..\src\events\juce_ActionListenerList.h"/> | |||
| <ClInclude Include="..\..\src\events\juce_AsyncUpdater.h"/> | |||
| <ClInclude Include="..\..\src\events\juce_CallbackMessage.h"/> | |||
| <ClInclude Include="..\..\src\events\juce_ChangeBroadcaster.h"/> | |||
| @@ -454,9 +454,6 @@ | |||
| <ClCompile Include="..\..\src\events\juce_ActionBroadcaster.cpp"> | |||
| <Filter>Juce\Source\events</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="..\..\src\events\juce_ActionListenerList.cpp"> | |||
| <Filter>Juce\Source\events</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="..\..\src\events\juce_AsyncUpdater.cpp"> | |||
| <Filter>Juce\Source\events</Filter> | |||
| </ClCompile> | |||
| @@ -1572,9 +1569,6 @@ | |||
| <ClInclude Include="..\..\src\events\juce_ActionListener.h"> | |||
| <Filter>Juce\Source\events</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\events\juce_ActionListenerList.h"> | |||
| <Filter>Juce\Source\events</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\events\juce_AsyncUpdater.h"> | |||
| <Filter>Juce\Source\events</Filter> | |||
| </ClInclude> | |||
| @@ -88,7 +88,6 @@ | |||
| 12E3CC31875A202D6B30F778 = { isa = PBXBuildFile; fileRef = E9E692847C14AD33CD5FB40B; }; | |||
| CF51988743ED2CD823DFE0B5 = { isa = PBXBuildFile; fileRef = 7AE9331938549244E27A5D0E; }; | |||
| 659D9CD58B6914EB420E6AEC = { isa = PBXBuildFile; fileRef = 31D985CB8646B78460E9D5A7; }; | |||
| 5BE4BAA99FDC6F1B3177096F = { isa = PBXBuildFile; fileRef = 5A46476E16BA4F9DA95E9E6A; }; | |||
| 55737E2F1817DE642AA7DA05 = { isa = PBXBuildFile; fileRef = 1617348BBF5D103619D76911; }; | |||
| 6D2C50B0A69855A7F8C062E7 = { isa = PBXBuildFile; fileRef = B80F8CD026033ACCCE11A1A4; }; | |||
| 70EE7A1273945B62B013DB43 = { isa = PBXBuildFile; fileRef = AE68ECB6E063BD8D4984C0B3; }; | |||
| @@ -554,8 +553,6 @@ | |||
| 31D985CB8646B78460E9D5A7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ActionBroadcaster.cpp; path = ../../src/events/juce_ActionBroadcaster.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 09F7685D1EFF472ECB1F5EF1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ActionBroadcaster.h; path = ../../src/events/juce_ActionBroadcaster.h; sourceTree = SOURCE_ROOT; }; | |||
| 4EF8BD4BF46C4BCB39F96609 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ActionListener.h; path = ../../src/events/juce_ActionListener.h; sourceTree = SOURCE_ROOT; }; | |||
| 5A46476E16BA4F9DA95E9E6A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ActionListenerList.cpp; path = ../../src/events/juce_ActionListenerList.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 8269D9DFAD7923EE13E7EEC7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ActionListenerList.h; path = ../../src/events/juce_ActionListenerList.h; sourceTree = SOURCE_ROOT; }; | |||
| 1617348BBF5D103619D76911 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_AsyncUpdater.cpp; path = ../../src/events/juce_AsyncUpdater.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 44DB44953945417F76199479 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_AsyncUpdater.h; path = ../../src/events/juce_AsyncUpdater.h; sourceTree = SOURCE_ROOT; }; | |||
| D04B6E43A037F985434B2F5A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CallbackMessage.h; path = ../../src/events/juce_CallbackMessage.h; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1282,8 +1279,6 @@ | |||
| 31D985CB8646B78460E9D5A7, | |||
| 09F7685D1EFF472ECB1F5EF1, | |||
| 4EF8BD4BF46C4BCB39F96609, | |||
| 5A46476E16BA4F9DA95E9E6A, | |||
| 8269D9DFAD7923EE13E7EEC7, | |||
| 1617348BBF5D103619D76911, | |||
| 44DB44953945417F76199479, | |||
| D04B6E43A037F985434B2F5A, | |||
| @@ -2008,7 +2003,6 @@ | |||
| 12E3CC31875A202D6B30F778, | |||
| CF51988743ED2CD823DFE0B5, | |||
| 659D9CD58B6914EB420E6AEC, | |||
| 5BE4BAA99FDC6F1B3177096F, | |||
| 55737E2F1817DE642AA7DA05, | |||
| 6D2C50B0A69855A7F8C062E7, | |||
| 70EE7A1273945B62B013DB43, | |||
| @@ -491,10 +491,6 @@ | |||
| file="src/events/juce_ActionBroadcaster.h"/> | |||
| <FILE id="Ux4rL61r9" name="juce_ActionListener.h" compile="0" resource="0" | |||
| file="src/events/juce_ActionListener.h"/> | |||
| <FILE id="F703c1Yid" name="juce_ActionListenerList.cpp" compile="1" | |||
| resource="0" file="src/events/juce_ActionListenerList.cpp"/> | |||
| <FILE id="OTsKfiFYq" name="juce_ActionListenerList.h" compile="0" resource="0" | |||
| file="src/events/juce_ActionListenerList.h"/> | |||
| <FILE id="LgjeCwe5N" name="juce_AsyncUpdater.cpp" compile="1" resource="0" | |||
| file="src/events/juce_AsyncUpdater.cpp"/> | |||
| <FILE id="TABmiJS44" name="juce_AsyncUpdater.h" compile="0" resource="0" | |||
| @@ -214,7 +214,6 @@ | |||
| #include "../src/audio/synthesisers/juce_Sampler.cpp" | |||
| #include "../src/audio/synthesisers/juce_Synthesiser.cpp" | |||
| #include "../src/events/juce_ActionBroadcaster.cpp" | |||
| #include "../src/events/juce_ActionListenerList.cpp" | |||
| #include "../src/events/juce_AsyncUpdater.cpp" | |||
| #include "../src/events/juce_ChangeBroadcaster.cpp" | |||
| #include "../src/events/juce_InterprocessConnection.cpp" | |||
| @@ -12159,7 +12159,7 @@ namespace NumberToStringConverters | |||
| else | |||
| { | |||
| #if JUCE_WINDOWS | |||
| #if JUCE_VC8_OR_EARLIER || JUCE_MINGW | |||
| #if JUCE_VC7_OR_EARLIER || JUCE_MINGW | |||
| len = _snwprintf (buffer, numChars, L"%.9g", n); | |||
| #else | |||
| len = _snwprintf_s (buffer, numChars, _TRUNCATE, L"%.9g", n); | |||
| @@ -38287,162 +38287,143 @@ END_JUCE_NAMESPACE | |||
| /*** Start of inlined file: juce_ActionBroadcaster.cpp ***/ | |||
| BEGIN_JUCE_NAMESPACE | |||
| ActionBroadcaster::ActionBroadcaster() throw() | |||
| { | |||
| // are you trying to create this object before or after juce has been intialised?? | |||
| jassert (MessageManager::instance != 0); | |||
| } | |||
| ActionBroadcaster::~ActionBroadcaster() | |||
| { | |||
| // all event-based objects must be deleted BEFORE juce is shut down! | |||
| jassert (MessageManager::instance != 0); | |||
| } | |||
| void ActionBroadcaster::addActionListener (ActionListener* const listener) | |||
| { | |||
| actionListenerList.addActionListener (listener); | |||
| } | |||
| void ActionBroadcaster::removeActionListener (ActionListener* const listener) | |||
| { | |||
| jassert (actionListenerList.isValidMessageListener()); | |||
| if (actionListenerList.isValidMessageListener()) | |||
| actionListenerList.removeActionListener (listener); | |||
| } | |||
| void ActionBroadcaster::removeAllActionListeners() | |||
| { | |||
| actionListenerList.removeAllActionListeners(); | |||
| } | |||
| void ActionBroadcaster::sendActionMessage (const String& message) const | |||
| { | |||
| actionListenerList.sendActionMessage (message); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| /*** End of inlined file: juce_ActionBroadcaster.cpp ***/ | |||
| /*** Start of inlined file: juce_ActionListenerList.cpp ***/ | |||
| BEGIN_JUCE_NAMESPACE | |||
| // special message of our own with a string in it | |||
| class ActionMessage : public Message | |||
| { | |||
| public: | |||
| const String message; | |||
| ActionMessage (const String& messageText, void* const listener_) throw() | |||
| ActionMessage (const String& messageText, ActionListener* const listener_) throw() | |||
| : message (messageText) | |||
| { | |||
| pointerParameter = listener_; | |||
| } | |||
| ~ActionMessage() throw() | |||
| { | |||
| } | |||
| private: | |||
| ActionMessage (const ActionMessage&); | |||
| ActionMessage& operator= (const ActionMessage&); | |||
| }; | |||
| ActionListenerList::ActionListenerList() | |||
| { | |||
| } | |||
| ActionBroadcaster::CallbackReceiver::CallbackReceiver() {} | |||
| ActionListenerList::~ActionListenerList() | |||
| void ActionBroadcaster::CallbackReceiver::handleMessage (const Message& message) | |||
| { | |||
| const ActionMessage& am = static_cast <const ActionMessage&> (message); | |||
| ActionListener* const target = static_cast <ActionListener*> (am.pointerParameter); | |||
| if (owner->actionListeners.contains (target)) | |||
| target->actionListenerCallback (am.message); | |||
| } | |||
| void ActionListenerList::addActionListener (ActionListener* const listener) | |||
| ActionBroadcaster::ActionBroadcaster() | |||
| { | |||
| const ScopedLock sl (actionListenerLock_); | |||
| jassert (listener != 0); | |||
| jassert (! actionListeners_.contains (listener)); // trying to add a listener to the list twice! | |||
| // are you trying to create this object before or after juce has been intialised?? | |||
| jassert (MessageManager::instance != 0); | |||
| if (listener != 0) | |||
| actionListeners_.add (listener); | |||
| callback.owner = this; | |||
| } | |||
| void ActionListenerList::removeActionListener (ActionListener* const listener) | |||
| ActionBroadcaster::~ActionBroadcaster() | |||
| { | |||
| const ScopedLock sl (actionListenerLock_); | |||
| // all event-based objects must be deleted BEFORE juce is shut down! | |||
| jassert (MessageManager::instance != 0); | |||
| } | |||
| jassert (actionListeners_.contains (listener)); // trying to remove a listener that isn't on the list! | |||
| void ActionBroadcaster::addActionListener (ActionListener* const listener) | |||
| { | |||
| const ScopedLock sl (actionListenerLock); | |||
| actionListeners_.removeValue (listener); | |||
| if (listener != 0) | |||
| actionListeners.add (listener); | |||
| } | |||
| void ActionListenerList::removeAllActionListeners() | |||
| void ActionBroadcaster::removeActionListener (ActionListener* const listener) | |||
| { | |||
| const ScopedLock sl (actionListenerLock_); | |||
| actionListeners_.clear(); | |||
| const ScopedLock sl (actionListenerLock); | |||
| actionListeners.removeValue (listener); | |||
| } | |||
| void ActionListenerList::sendActionMessage (const String& message) const | |||
| void ActionBroadcaster::removeAllActionListeners() | |||
| { | |||
| const ScopedLock sl (actionListenerLock_); | |||
| for (int i = actionListeners_.size(); --i >= 0;) | |||
| postMessage (new ActionMessage (message, static_cast <ActionListener*> (actionListeners_.getUnchecked(i)))); | |||
| const ScopedLock sl (actionListenerLock); | |||
| actionListeners.clear(); | |||
| } | |||
| void ActionListenerList::handleMessage (const Message& message) | |||
| void ActionBroadcaster::sendActionMessage (const String& message) const | |||
| { | |||
| const ActionMessage& am = (const ActionMessage&) message; | |||
| const ScopedLock sl (actionListenerLock); | |||
| if (actionListeners_.contains (am.pointerParameter)) | |||
| static_cast <ActionListener*> (am.pointerParameter)->actionListenerCallback (am.message); | |||
| for (int i = actionListeners.size(); --i >= 0;) | |||
| callback.postMessage (new ActionMessage (message, actionListeners.getUnchecked(i))); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| /*** End of inlined file: juce_ActionListenerList.cpp ***/ | |||
| /*** End of inlined file: juce_ActionBroadcaster.cpp ***/ | |||
| /*** Start of inlined file: juce_AsyncUpdater.cpp ***/ | |||
| BEGIN_JUCE_NAMESPACE | |||
| class AsyncUpdater::AsyncUpdaterMessage : public CallbackMessage | |||
| { | |||
| public: | |||
| AsyncUpdaterMessage (AsyncUpdater& owner_) | |||
| : owner (owner_) | |||
| { | |||
| } | |||
| void messageCallback() | |||
| { | |||
| if (owner.pendingMessage.compareAndSetBool (0, this)) | |||
| owner.handleAsyncUpdate(); | |||
| } | |||
| AsyncUpdater& owner; | |||
| }; | |||
| AsyncUpdater::AsyncUpdater() throw() | |||
| : asyncMessagePending (false) | |||
| { | |||
| internalAsyncHandler.owner = this; | |||
| } | |||
| AsyncUpdater::~AsyncUpdater() | |||
| { | |||
| // You're deleting this object with a background thread while there's an update | |||
| // pending on the main event thread - that's pretty dodgy threading, as the callback could | |||
| // happen after this destructor has finished. You should either use a MessageManagerLock while | |||
| // deleting this object, or find some other way to avoid such a race condition. | |||
| jassert (/*(! isUpdatePending()) ||*/ MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| pendingMessage = 0; | |||
| } | |||
| void AsyncUpdater::triggerAsyncUpdate() | |||
| { | |||
| if (! asyncMessagePending) | |||
| if (pendingMessage.value == 0) | |||
| { | |||
| asyncMessagePending = true; | |||
| internalAsyncHandler.postMessage (new Message()); | |||
| ScopedPointer<AsyncUpdaterMessage> pending (new AsyncUpdaterMessage (*this)); | |||
| if (pendingMessage.compareAndSetBool (pending, 0)) | |||
| pending.release()->post(); | |||
| } | |||
| } | |||
| void AsyncUpdater::cancelPendingUpdate() throw() | |||
| { | |||
| asyncMessagePending = false; | |||
| pendingMessage = 0; | |||
| } | |||
| void AsyncUpdater::handleUpdateNowIfNeeded() | |||
| { | |||
| if (asyncMessagePending) | |||
| { | |||
| asyncMessagePending = false; | |||
| // This can only be called by the event thread. | |||
| jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| if (pendingMessage.exchange (0) != 0) | |||
| handleAsyncUpdate(); | |||
| } | |||
| } | |||
| void AsyncUpdater::AsyncUpdaterInternal::handleMessage (const Message&) | |||
| bool AsyncUpdater::isUpdatePending() const throw() | |||
| { | |||
| owner->handleUpdateNowIfNeeded(); | |||
| return pendingMessage.value != 0; | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -38452,40 +38433,24 @@ END_JUCE_NAMESPACE | |||
| /*** Start of inlined file: juce_ChangeBroadcaster.cpp ***/ | |||
| BEGIN_JUCE_NAMESPACE | |||
| class ChangeBroadcaster::ChangeBroadcasterMessage : public CallbackMessage | |||
| { | |||
| public: | |||
| ChangeBroadcasterMessage (ChangeBroadcaster* const owner_) | |||
| : owner (owner_) | |||
| { | |||
| } | |||
| void messageCallback() | |||
| { | |||
| if (owner != 0 && owner->pendingMessage.value == this) | |||
| owner->sendSynchronousChangeMessage(); | |||
| } | |||
| ChangeBroadcaster* owner; | |||
| }; | |||
| ChangeBroadcaster::ChangeBroadcaster() throw() | |||
| { | |||
| // are you trying to create this object before or after juce has been intialised?? | |||
| jassert (MessageManager::instance != 0); | |||
| callback.owner = this; | |||
| } | |||
| ChangeBroadcaster::~ChangeBroadcaster() | |||
| { | |||
| // all event-based objects must be deleted BEFORE juce is shut down! | |||
| jassert (MessageManager::instance != 0); | |||
| invalidatePendingMessage(); | |||
| } | |||
| void ChangeBroadcaster::addChangeListener (ChangeListener* const listener) | |||
| { | |||
| // Listeners can only be safely added when the event thread is locked... | |||
| // Listeners can only be safely added when the event thread is locked | |||
| // You can use a MessageManagerLock if you need to call this from another thread. | |||
| jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| changeListeners.add (listener); | |||
| @@ -38493,7 +38458,8 @@ void ChangeBroadcaster::addChangeListener (ChangeListener* const listener) | |||
| void ChangeBroadcaster::removeChangeListener (ChangeListener* const listener) | |||
| { | |||
| // Listeners can only be safely added when the event thread is locked... | |||
| // Listeners can only be safely added when the event thread is locked | |||
| // You can use a MessageManagerLock if you need to call this from another thread. | |||
| jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| changeListeners.remove (listener); | |||
| @@ -38501,28 +38467,17 @@ void ChangeBroadcaster::removeChangeListener (ChangeListener* const listener) | |||
| void ChangeBroadcaster::removeAllChangeListeners() | |||
| { | |||
| // Listeners can only be safely added when the event thread is locked... | |||
| // Listeners can only be safely added when the event thread is locked | |||
| // You can use a MessageManagerLock if you need to call this from another thread. | |||
| jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| changeListeners.clear(); | |||
| } | |||
| void ChangeBroadcaster::invalidatePendingMessage() | |||
| { | |||
| ChangeBroadcasterMessage* const oldMessage = pendingMessage.exchange (0); | |||
| if (oldMessage != 0) | |||
| oldMessage->owner = 0; | |||
| } | |||
| void ChangeBroadcaster::sendChangeMessage() | |||
| { | |||
| if (pendingMessage.value == 0 && changeListeners.size() > 0) | |||
| { | |||
| ScopedPointer<ChangeBroadcasterMessage> pending (new ChangeBroadcasterMessage (this)); | |||
| if (pendingMessage.compareAndSetBool (pending, 0)) | |||
| pending.release()->post(); | |||
| } | |||
| if (changeListeners.size() > 0) | |||
| callback.triggerAsyncUpdate(); | |||
| } | |||
| void ChangeBroadcaster::sendSynchronousChangeMessage() | |||
| @@ -38530,14 +38485,29 @@ void ChangeBroadcaster::sendSynchronousChangeMessage() | |||
| // This can only be called by the event thread. | |||
| jassert (MessageManager::getInstance()->isThisTheMessageThread()); | |||
| invalidatePendingMessage(); | |||
| changeListeners.call (&ChangeListener::changeListenerCallback, this); | |||
| callback.cancelPendingUpdate(); | |||
| callListeners(); | |||
| } | |||
| void ChangeBroadcaster::dispatchPendingMessages() | |||
| { | |||
| if (pendingMessage.get() != 0) | |||
| sendSynchronousChangeMessage(); | |||
| callback.handleUpdateNowIfNeeded(); | |||
| } | |||
| void ChangeBroadcaster::callListeners() | |||
| { | |||
| changeListeners.call (&ChangeListener::changeListenerCallback, this); | |||
| } | |||
| ChangeBroadcaster::ChangeBroadcasterCallback::ChangeBroadcasterCallback() | |||
| : owner (0) | |||
| { | |||
| } | |||
| void ChangeBroadcaster::ChangeBroadcasterCallback::handleAsyncUpdate() | |||
| { | |||
| jassert (owner != 0); | |||
| owner->callListeners(); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -38955,7 +38925,8 @@ Message::Message() throw() | |||
| : intParameter1 (0), | |||
| intParameter2 (0), | |||
| intParameter3 (0), | |||
| pointerParameter (0) | |||
| pointerParameter (0), | |||
| messageRecipient (0) | |||
| { | |||
| } | |||
| @@ -38966,7 +38937,8 @@ Message::Message (const int intParameter1_, | |||
| : intParameter1 (intParameter1_), | |||
| intParameter2 (intParameter2_), | |||
| intParameter3 (intParameter3_), | |||
| pointerParameter (pointerParameter_) | |||
| pointerParameter (pointerParameter_), | |||
| messageRecipient (0) | |||
| { | |||
| } | |||
| @@ -39037,7 +39009,7 @@ MessageManager::MessageManager() throw() | |||
| MessageManager::~MessageManager() throw() | |||
| { | |||
| broadcastListeners = 0; | |||
| broadcaster = 0; | |||
| doPlatformSpecificShutdown(); | |||
| @@ -39068,47 +39040,40 @@ void MessageManager::postMessageToQueue (Message* const message) | |||
| delete message; | |||
| } | |||
| CallbackMessage::CallbackMessage() throw() {} | |||
| CallbackMessage::~CallbackMessage() {} | |||
| CallbackMessage::CallbackMessage() throw() {} | |||
| CallbackMessage::~CallbackMessage() {} | |||
| void CallbackMessage::post() | |||
| { | |||
| if (MessageManager::instance != 0) | |||
| MessageManager::instance->postCallbackMessage (this); | |||
| } | |||
| void MessageManager::postCallbackMessage (Message* const message) | |||
| { | |||
| message->messageRecipient = 0; | |||
| postMessageToQueue (message); | |||
| MessageManager::instance->postMessageToQueue (this); | |||
| } | |||
| // not for public use.. | |||
| void MessageManager::deliverMessage (Message* const message) | |||
| { | |||
| const ScopedPointer <Message> messageDeleter (message); | |||
| MessageListener* const recipient = message->messageRecipient; | |||
| JUCE_TRY | |||
| { | |||
| if (messageListeners.contains (recipient)) | |||
| { | |||
| recipient->handleMessage (*message); | |||
| } | |||
| else if (recipient == 0) | |||
| const ScopedPointer <Message> messageDeleter (message); | |||
| MessageListener* const recipient = message->messageRecipient; | |||
| if (recipient == 0) | |||
| { | |||
| if (message->intParameter1 == quitMessageId) | |||
| CallbackMessage* const callbackMessage = dynamic_cast <CallbackMessage*> (message); | |||
| if (callbackMessage != 0) | |||
| { | |||
| quitMessageReceived = true; | |||
| callbackMessage->messageCallback(); | |||
| } | |||
| else | |||
| else if (message->intParameter1 == quitMessageId) | |||
| { | |||
| CallbackMessage* const cm = dynamic_cast <CallbackMessage*> (message); | |||
| if (cm != 0) | |||
| cm->messageCallback(); | |||
| quitMessageReceived = true; | |||
| } | |||
| } | |||
| else if (messageListeners.contains (recipient)) | |||
| { | |||
| recipient->handleMessage (*message); | |||
| } | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| } | |||
| @@ -39123,10 +39088,7 @@ void MessageManager::runDispatchLoop() | |||
| void MessageManager::stopDispatchLoop() | |||
| { | |||
| Message* const m = new Message (quitMessageId, 0, 0, 0); | |||
| m->messageRecipient = 0; | |||
| postMessageToQueue (m); | |||
| postMessageToQueue (new Message (quitMessageId, 0, 0, 0)); | |||
| quitMessagePosted = true; | |||
| } | |||
| @@ -39159,22 +39121,22 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||
| void MessageManager::deliverBroadcastMessage (const String& value) | |||
| { | |||
| if (broadcastListeners != 0) | |||
| broadcastListeners->sendActionMessage (value); | |||
| if (broadcaster != 0) | |||
| broadcaster->sendActionMessage (value); | |||
| } | |||
| void MessageManager::registerBroadcastListener (ActionListener* const listener) | |||
| { | |||
| if (broadcastListeners == 0) | |||
| broadcastListeners = new ActionListenerList(); | |||
| if (broadcaster == 0) | |||
| broadcaster = new ActionBroadcaster(); | |||
| broadcastListeners->addActionListener (listener); | |||
| broadcaster->addActionListener (listener); | |||
| } | |||
| void MessageManager::deregisterBroadcastListener (ActionListener* const listener) | |||
| { | |||
| if (broadcastListeners != 0) | |||
| broadcastListeners->removeActionListener (listener); | |||
| if (broadcaster != 0) | |||
| broadcaster->removeActionListener (listener); | |||
| } | |||
| bool MessageManager::isThisTheMessageThread() const throw() | |||
| @@ -39213,7 +39175,6 @@ class MessageManagerLock::SharedEvents : public ReferenceCountedObject | |||
| { | |||
| public: | |||
| SharedEvents() {} | |||
| ~SharedEvents() {} | |||
| /* This class just holds a couple of events to communicate between the BlockingMessage | |||
| and the MessageManagerLock. Because both of these objects may be deleted at any time, | |||
| @@ -39229,7 +39190,6 @@ class MessageManagerLock::BlockingMessage : public CallbackMessage | |||
| { | |||
| public: | |||
| BlockingMessage (MessageManagerLock::SharedEvents* const events_) : events (events_) {} | |||
| ~BlockingMessage() throw() {} | |||
| void messageCallback() | |||
| { | |||
| @@ -64,7 +64,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 93 | |||
| #define JUCE_BUILDNUMBER 94 | |||
| /** Current Juce version number. | |||
| @@ -12281,131 +12281,6 @@ private: | |||
| #ifndef __JUCE_ASYNCUPDATER_JUCEHEADER__ | |||
| #define __JUCE_ASYNCUPDATER_JUCEHEADER__ | |||
| /*** Start of inlined file: juce_MessageListener.h ***/ | |||
| #ifndef __JUCE_MESSAGELISTENER_JUCEHEADER__ | |||
| #define __JUCE_MESSAGELISTENER_JUCEHEADER__ | |||
| /*** Start of inlined file: juce_Message.h ***/ | |||
| #ifndef __JUCE_MESSAGE_JUCEHEADER__ | |||
| #define __JUCE_MESSAGE_JUCEHEADER__ | |||
| class MessageListener; | |||
| class MessageManager; | |||
| /** The base class for objects that can be delivered to a MessageListener. | |||
| The simplest Message object contains a few integer and pointer parameters | |||
| that the user can set, and this is enough for a lot of purposes. For passing more | |||
| complex data, subclasses of Message can also be used. | |||
| @see MessageListener, MessageManager, ActionListener, ChangeListener | |||
| */ | |||
| class JUCE_API Message | |||
| { | |||
| public: | |||
| /** Creates an uninitialised message. | |||
| The class's variables will also be left uninitialised. | |||
| */ | |||
| Message() throw(); | |||
| /** Creates a message object, filling in the member variables. | |||
| The corresponding public member variables will be set from the parameters | |||
| passed in. | |||
| */ | |||
| Message (int intParameter1, | |||
| int intParameter2, | |||
| int intParameter3, | |||
| void* pointerParameter) throw(); | |||
| /** Destructor. */ | |||
| virtual ~Message(); | |||
| // These values can be used for carrying simple data that the application needs to | |||
| // pass around. For more complex messages, just create a subclass. | |||
| int intParameter1; /**< user-defined integer value. */ | |||
| int intParameter2; /**< user-defined integer value. */ | |||
| int intParameter3; /**< user-defined integer value. */ | |||
| void* pointerParameter; /**< user-defined pointer value. */ | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| friend class MessageListener; | |||
| friend class MessageManager; | |||
| MessageListener* messageRecipient; | |||
| Message (const Message&); | |||
| Message& operator= (const Message&); | |||
| }; | |||
| #endif // __JUCE_MESSAGE_JUCEHEADER__ | |||
| /*** End of inlined file: juce_Message.h ***/ | |||
| /** | |||
| MessageListener subclasses can post and receive Message objects. | |||
| @see Message, MessageManager, ActionListener, ChangeListener | |||
| */ | |||
| class JUCE_API MessageListener | |||
| { | |||
| protected: | |||
| /** Creates a MessageListener. */ | |||
| MessageListener() throw(); | |||
| public: | |||
| /** Destructor. | |||
| When a MessageListener is deleted, it removes itself from a global list | |||
| of registered listeners, so that the isValidMessageListener() method | |||
| will no longer return true. | |||
| */ | |||
| virtual ~MessageListener(); | |||
| /** This is the callback method that receives incoming messages. | |||
| This is called by the MessageManager from its dispatch loop. | |||
| @see postMessage | |||
| */ | |||
| virtual void handleMessage (const Message& message) = 0; | |||
| /** Sends a message to the message queue, for asynchronous delivery to this listener | |||
| later on. | |||
| This method can be called safely by any thread. | |||
| @param message the message object to send - this will be deleted | |||
| automatically by the message queue, so don't keep any | |||
| references to it after calling this method. | |||
| @see handleMessage | |||
| */ | |||
| void postMessage (Message* message) const throw(); | |||
| /** Checks whether this MessageListener has been deleted. | |||
| Although not foolproof, this method is safe to call on dangling or null | |||
| pointers. A list of active MessageListeners is kept internally, so this | |||
| checks whether the object is on this list or not. | |||
| Note that it's possible to get a false-positive here, if an object is | |||
| deleted and another is subsequently created that happens to be at the | |||
| exact same memory location, but I can't think of a good way of avoiding | |||
| this. | |||
| */ | |||
| bool isValidMessageListener() const throw(); | |||
| }; | |||
| #endif // __JUCE_MESSAGELISTENER_JUCEHEADER__ | |||
| /*** End of inlined file: juce_MessageListener.h ***/ | |||
| /** | |||
| Has a callback method that is triggered asynchronously. | |||
| @@ -12454,9 +12329,15 @@ public: | |||
| Use this as a kind of "flush" operation - if an update is pending, the | |||
| handleAsyncUpdate() method will be called immediately; if no update is | |||
| pending, then nothing will be done. | |||
| Because this may invoke the callback, this method must only be called on | |||
| the main event thread. | |||
| */ | |||
| void handleUpdateNowIfNeeded(); | |||
| /** Returns true if there's an update callback in the pipeline. */ | |||
| bool isUpdatePending() const throw(); | |||
| /** Called back to do whatever your class needs to do. | |||
| This method is called by the message thread at the next convenient time | |||
| @@ -12466,23 +12347,10 @@ public: | |||
| private: | |||
| class AsyncUpdaterInternal : public MessageListener | |||
| { | |||
| public: | |||
| AsyncUpdaterInternal() {} | |||
| ~AsyncUpdaterInternal() {} | |||
| void handleMessage (const Message&); | |||
| AsyncUpdater* owner; | |||
| private: | |||
| AsyncUpdaterInternal (const AsyncUpdaterInternal&); | |||
| AsyncUpdaterInternal& operator= (const AsyncUpdaterInternal&); | |||
| }; | |||
| class AsyncUpdaterMessage; | |||
| friend class AsyncUpdaterMessage; | |||
| AsyncUpdaterInternal internalAsyncHandler; | |||
| bool asyncMessagePending; | |||
| Atomic<AsyncUpdaterMessage*> pendingMessage; | |||
| }; | |||
| #endif // __JUCE_ASYNCUPDATER_JUCEHEADER__ | |||
| @@ -13099,13 +12967,20 @@ public: | |||
| private: | |||
| class ChangeBroadcasterMessage; | |||
| friend class ChangeBroadcasterMessage; | |||
| class ChangeBroadcasterCallback : public AsyncUpdater | |||
| { | |||
| public: | |||
| ChangeBroadcasterCallback(); | |||
| void handleAsyncUpdate(); | |||
| ChangeBroadcaster* owner; | |||
| }; | |||
| Atomic<ChangeBroadcasterMessage*> pendingMessage; | |||
| friend class ChangeBroadcasterCallback; | |||
| ChangeBroadcasterCallback callback; | |||
| ListenerList <ChangeListener> changeListeners; | |||
| void invalidatePendingMessage(); | |||
| void callListeners(); | |||
| ChangeBroadcaster (const ChangeBroadcaster&); | |||
| ChangeBroadcaster& operator= (const ChangeBroadcaster&); | |||
| @@ -28302,6 +28177,131 @@ struct JUCE_API ApplicationCommandInfo | |||
| #endif // __JUCE_APPLICATIONCOMMANDINFO_JUCEHEADER__ | |||
| /*** End of inlined file: juce_ApplicationCommandInfo.h ***/ | |||
| /*** Start of inlined file: juce_MessageListener.h ***/ | |||
| #ifndef __JUCE_MESSAGELISTENER_JUCEHEADER__ | |||
| #define __JUCE_MESSAGELISTENER_JUCEHEADER__ | |||
| /*** Start of inlined file: juce_Message.h ***/ | |||
| #ifndef __JUCE_MESSAGE_JUCEHEADER__ | |||
| #define __JUCE_MESSAGE_JUCEHEADER__ | |||
| class MessageListener; | |||
| class MessageManager; | |||
| /** The base class for objects that can be delivered to a MessageListener. | |||
| The simplest Message object contains a few integer and pointer parameters | |||
| that the user can set, and this is enough for a lot of purposes. For passing more | |||
| complex data, subclasses of Message can also be used. | |||
| @see MessageListener, MessageManager, ActionListener, ChangeListener | |||
| */ | |||
| class JUCE_API Message | |||
| { | |||
| public: | |||
| /** Creates an uninitialised message. | |||
| The class's variables will also be left uninitialised. | |||
| */ | |||
| Message() throw(); | |||
| /** Creates a message object, filling in the member variables. | |||
| The corresponding public member variables will be set from the parameters | |||
| passed in. | |||
| */ | |||
| Message (int intParameter1, | |||
| int intParameter2, | |||
| int intParameter3, | |||
| void* pointerParameter) throw(); | |||
| /** Destructor. */ | |||
| virtual ~Message(); | |||
| // These values can be used for carrying simple data that the application needs to | |||
| // pass around. For more complex messages, just create a subclass. | |||
| int intParameter1; /**< user-defined integer value. */ | |||
| int intParameter2; /**< user-defined integer value. */ | |||
| int intParameter3; /**< user-defined integer value. */ | |||
| void* pointerParameter; /**< user-defined pointer value. */ | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| friend class MessageListener; | |||
| friend class MessageManager; | |||
| MessageListener* messageRecipient; | |||
| Message (const Message&); | |||
| Message& operator= (const Message&); | |||
| }; | |||
| #endif // __JUCE_MESSAGE_JUCEHEADER__ | |||
| /*** End of inlined file: juce_Message.h ***/ | |||
| /** | |||
| MessageListener subclasses can post and receive Message objects. | |||
| @see Message, MessageManager, ActionListener, ChangeListener | |||
| */ | |||
| class JUCE_API MessageListener | |||
| { | |||
| protected: | |||
| /** Creates a MessageListener. */ | |||
| MessageListener() throw(); | |||
| public: | |||
| /** Destructor. | |||
| When a MessageListener is deleted, it removes itself from a global list | |||
| of registered listeners, so that the isValidMessageListener() method | |||
| will no longer return true. | |||
| */ | |||
| virtual ~MessageListener(); | |||
| /** This is the callback method that receives incoming messages. | |||
| This is called by the MessageManager from its dispatch loop. | |||
| @see postMessage | |||
| */ | |||
| virtual void handleMessage (const Message& message) = 0; | |||
| /** Sends a message to the message queue, for asynchronous delivery to this listener | |||
| later on. | |||
| This method can be called safely by any thread. | |||
| @param message the message object to send - this will be deleted | |||
| automatically by the message queue, so don't keep any | |||
| references to it after calling this method. | |||
| @see handleMessage | |||
| */ | |||
| void postMessage (Message* message) const throw(); | |||
| /** Checks whether this MessageListener has been deleted. | |||
| Although not foolproof, this method is safe to call on dangling or null | |||
| pointers. A list of active MessageListeners is kept internally, so this | |||
| checks whether the object is on this list or not. | |||
| Note that it's possible to get a false-positive here, if an object is | |||
| deleted and another is subsequently created that happens to be at the | |||
| exact same memory location, but I can't think of a good way of avoiding | |||
| this. | |||
| */ | |||
| bool isValidMessageListener() const throw(); | |||
| }; | |||
| #endif // __JUCE_MESSAGELISTENER_JUCEHEADER__ | |||
| /*** End of inlined file: juce_MessageListener.h ***/ | |||
| /** | |||
| A command target publishes a list of command IDs that it can perform. | |||
| @@ -28537,7 +28537,7 @@ private: | |||
| Used by various classes, e.g. buttons when they are pressed, to tell listeners | |||
| about something that's happened. | |||
| @see ActionListenerList, ActionBroadcaster, ChangeListener | |||
| @see ActionBroadcaster, ChangeListener | |||
| */ | |||
| class JUCE_API ActionListener | |||
| { | |||
| @@ -28548,7 +28548,7 @@ public: | |||
| /** Overridden by your subclass to receive the callback. | |||
| @param message the string that was specified when the event was triggered | |||
| by a call to ActionListenerList::sendActionMessage() | |||
| by a call to ActionBroadcaster::sendActionMessage() | |||
| */ | |||
| virtual void actionListenerCallback (const String& message) = 0; | |||
| }; | |||
| @@ -43380,96 +43380,29 @@ private: | |||
| #ifndef __JUCE_ACTIONBROADCASTER_JUCEHEADER__ | |||
| #define __JUCE_ACTIONBROADCASTER_JUCEHEADER__ | |||
| /*** Start of inlined file: juce_ActionListenerList.h ***/ | |||
| #ifndef __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ | |||
| #define __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ | |||
| /** | |||
| A set of ActionListeners. | |||
| Listeners can be added and removed from the list, and messages can be | |||
| broadcast to all the listeners. | |||
| @see ActionListener, ActionBroadcaster | |||
| */ | |||
| class JUCE_API ActionListenerList : public MessageListener | |||
| { | |||
| public: | |||
| /** Creates an empty list. */ | |||
| ActionListenerList(); | |||
| /** Destructor. */ | |||
| ~ActionListenerList(); | |||
| /** Adds a listener to the list. | |||
| (Trying to add a listener that's already on the list will have no effect). | |||
| */ | |||
| void addActionListener (ActionListener* listener); | |||
| /** Removes a listener from the list. | |||
| If the listener isn't on the list, this won't have any effect. | |||
| */ | |||
| void removeActionListener (ActionListener* listener); | |||
| /** Removes all listeners from the list. */ | |||
| void removeAllActionListeners(); | |||
| /** Broadcasts a message to all the registered listeners. | |||
| This sends the message asynchronously. | |||
| If a listener is on the list when this method is called but is removed from | |||
| the list before the message arrives, it won't receive the message. Similarly | |||
| listeners that are added to the list after the message is sent but before it | |||
| arrives won't get the message either. | |||
| */ | |||
| void sendActionMessage (const String& message) const; | |||
| /** @internal */ | |||
| void handleMessage (const Message&); | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| SortedSet <void*> actionListeners_; | |||
| CriticalSection actionListenerLock_; | |||
| ActionListenerList (const ActionListenerList&); | |||
| ActionListenerList& operator= (const ActionListenerList&); | |||
| }; | |||
| #endif // __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ | |||
| /*** End of inlined file: juce_ActionListenerList.h ***/ | |||
| /** Manages a list of ActionListeners, and can send them messages. | |||
| To quickly add methods to your class that can add/remove action | |||
| listeners and broadcast to them, you can derive from this. | |||
| @see ActionListenerList, ActionListener | |||
| @see ActionListener, ChangeListener | |||
| */ | |||
| class JUCE_API ActionBroadcaster | |||
| { | |||
| public: | |||
| /** Creates an ActionBroadcaster. */ | |||
| ActionBroadcaster() throw(); | |||
| ActionBroadcaster(); | |||
| /** Destructor. */ | |||
| virtual ~ActionBroadcaster(); | |||
| /** Adds a listener to the list. | |||
| (Trying to add a listener that's already on the list will have no effect). | |||
| Trying to add a listener that's already on the list will have no effect. | |||
| */ | |||
| void addActionListener (ActionListener* listener); | |||
| /** Removes a listener from the list. | |||
| If the listener isn't on the list, this won't have any effect. | |||
| */ | |||
| void removeActionListener (ActionListener* listener); | |||
| @@ -43478,14 +43411,25 @@ public: | |||
| void removeAllActionListeners(); | |||
| /** Broadcasts a message to all the registered listeners. | |||
| @see ActionListenerList::sendActionMessage | |||
| @see ActionListener::actionListenerCallback | |||
| */ | |||
| void sendActionMessage (const String& message) const; | |||
| private: | |||
| ActionListenerList actionListenerList; | |||
| class CallbackReceiver : public MessageListener | |||
| { | |||
| public: | |||
| CallbackReceiver(); | |||
| void handleMessage (const Message&); | |||
| ActionBroadcaster* owner; | |||
| }; | |||
| friend class CallbackReceiver; | |||
| CallbackReceiver callback; | |||
| SortedSet <ActionListener*> actionListeners; | |||
| CriticalSection actionListenerLock; | |||
| ActionBroadcaster (const ActionBroadcaster&); | |||
| ActionBroadcaster& operator= (const ActionBroadcaster&); | |||
| @@ -43498,9 +43442,6 @@ private: | |||
| #endif | |||
| #ifndef __JUCE_ACTIONLISTENER_JUCEHEADER__ | |||
| #endif | |||
| #ifndef __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ | |||
| #endif | |||
| #ifndef __JUCE_ASYNCUPDATER_JUCEHEADER__ | |||
| @@ -43980,7 +43921,7 @@ private: | |||
| static MessageManager* instance; | |||
| SortedSet <const MessageListener*> messageListeners; | |||
| ScopedPointer <ActionListenerList> broadcastListeners; | |||
| ScopedPointer <ActionBroadcaster> broadcaster; | |||
| friend class JUCEApplication; | |||
| bool quitMessagePosted, quitMessageReceived; | |||
| @@ -43989,7 +43930,6 @@ private: | |||
| static void* exitModalLoopCallback (void*); | |||
| void postMessageToQueue (Message* message); | |||
| void postCallbackMessage (Message* message); | |||
| static void doPlatformSpecificInitialisation(); | |||
| static void doPlatformSpecificShutdown(); | |||
| @@ -28,6 +28,7 @@ | |||
| #include "../gui/components/juce_Component.h" | |||
| #include "juce_ApplicationCommandInfo.h" | |||
| #include "../events/juce_MessageListener.h" | |||
| //============================================================================== | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 93 | |||
| #define JUCE_BUILDNUMBER 94 | |||
| /** Current Juce version number. | |||
| @@ -29,13 +29,45 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_ActionBroadcaster.h" | |||
| #include "juce_MessageManager.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| ActionBroadcaster::ActionBroadcaster() throw() | |||
| // special message of our own with a string in it | |||
| class ActionMessage : public Message | |||
| { | |||
| public: | |||
| const String message; | |||
| ActionMessage (const String& messageText, ActionListener* const listener_) throw() | |||
| : message (messageText) | |||
| { | |||
| pointerParameter = listener_; | |||
| } | |||
| private: | |||
| ActionMessage (const ActionMessage&); | |||
| ActionMessage& operator= (const ActionMessage&); | |||
| }; | |||
| ActionBroadcaster::CallbackReceiver::CallbackReceiver() {} | |||
| void ActionBroadcaster::CallbackReceiver::handleMessage (const Message& message) | |||
| { | |||
| const ActionMessage& am = static_cast <const ActionMessage&> (message); | |||
| ActionListener* const target = static_cast <ActionListener*> (am.pointerParameter); | |||
| if (owner->actionListeners.contains (target)) | |||
| target->actionListenerCallback (am.message); | |||
| } | |||
| //============================================================================== | |||
| ActionBroadcaster::ActionBroadcaster() | |||
| { | |||
| // are you trying to create this object before or after juce has been intialised?? | |||
| jassert (MessageManager::instance != 0); | |||
| callback.owner = this; | |||
| } | |||
| ActionBroadcaster::~ActionBroadcaster() | |||
| @@ -46,25 +78,31 @@ ActionBroadcaster::~ActionBroadcaster() | |||
| void ActionBroadcaster::addActionListener (ActionListener* const listener) | |||
| { | |||
| actionListenerList.addActionListener (listener); | |||
| const ScopedLock sl (actionListenerLock); | |||
| if (listener != 0) | |||
| actionListeners.add (listener); | |||
| } | |||
| void ActionBroadcaster::removeActionListener (ActionListener* const listener) | |||
| { | |||
| jassert (actionListenerList.isValidMessageListener()); | |||
| if (actionListenerList.isValidMessageListener()) | |||
| actionListenerList.removeActionListener (listener); | |||
| const ScopedLock sl (actionListenerLock); | |||
| actionListeners.removeValue (listener); | |||
| } | |||
| void ActionBroadcaster::removeAllActionListeners() | |||
| { | |||
| actionListenerList.removeAllActionListeners(); | |||
| const ScopedLock sl (actionListenerLock); | |||
| actionListeners.clear(); | |||
| } | |||
| void ActionBroadcaster::sendActionMessage (const String& message) const | |||
| { | |||
| actionListenerList.sendActionMessage (message); | |||
| const ScopedLock sl (actionListenerLock); | |||
| for (int i = actionListeners.size(); --i >= 0;) | |||
| callback.postMessage (new ActionMessage (message, actionListeners.getUnchecked(i))); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -26,7 +26,9 @@ | |||
| #ifndef __JUCE_ACTIONBROADCASTER_JUCEHEADER__ | |||
| #define __JUCE_ACTIONBROADCASTER_JUCEHEADER__ | |||
| #include "juce_ActionListenerList.h" | |||
| #include "juce_ActionListener.h" | |||
| #include "juce_MessageListener.h" | |||
| #include "../containers/juce_SortedSet.h" | |||
| //============================================================================== | |||
| @@ -35,27 +37,25 @@ | |||
| To quickly add methods to your class that can add/remove action | |||
| listeners and broadcast to them, you can derive from this. | |||
| @see ActionListenerList, ActionListener | |||
| @see ActionListener, ChangeListener | |||
| */ | |||
| class JUCE_API ActionBroadcaster | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates an ActionBroadcaster. */ | |||
| ActionBroadcaster() throw(); | |||
| ActionBroadcaster(); | |||
| /** Destructor. */ | |||
| virtual ~ActionBroadcaster(); | |||
| //============================================================================== | |||
| /** Adds a listener to the list. | |||
| (Trying to add a listener that's already on the list will have no effect). | |||
| Trying to add a listener that's already on the list will have no effect. | |||
| */ | |||
| void addActionListener (ActionListener* listener); | |||
| /** Removes a listener from the list. | |||
| If the listener isn't on the list, this won't have any effect. | |||
| */ | |||
| void removeActionListener (ActionListener* listener); | |||
| @@ -65,15 +65,26 @@ public: | |||
| //============================================================================== | |||
| /** Broadcasts a message to all the registered listeners. | |||
| @see ActionListenerList::sendActionMessage | |||
| @see ActionListener::actionListenerCallback | |||
| */ | |||
| void sendActionMessage (const String& message) const; | |||
| private: | |||
| //============================================================================== | |||
| ActionListenerList actionListenerList; | |||
| class CallbackReceiver : public MessageListener | |||
| { | |||
| public: | |||
| CallbackReceiver(); | |||
| void handleMessage (const Message&); | |||
| ActionBroadcaster* owner; | |||
| }; | |||
| friend class CallbackReceiver; | |||
| CallbackReceiver callback; | |||
| SortedSet <ActionListener*> actionListeners; | |||
| CriticalSection actionListenerLock; | |||
| ActionBroadcaster (const ActionBroadcaster&); | |||
| ActionBroadcaster& operator= (const ActionBroadcaster&); | |||
| @@ -36,7 +36,7 @@ | |||
| Used by various classes, e.g. buttons when they are pressed, to tell listeners | |||
| about something that's happened. | |||
| @see ActionListenerList, ActionBroadcaster, ChangeListener | |||
| @see ActionBroadcaster, ChangeListener | |||
| */ | |||
| class JUCE_API ActionListener | |||
| { | |||
| @@ -47,7 +47,7 @@ public: | |||
| /** Overridden by your subclass to receive the callback. | |||
| @param message the string that was specified when the event was triggered | |||
| by a call to ActionListenerList::sendActionMessage() | |||
| by a call to ActionBroadcaster::sendActionMessage() | |||
| */ | |||
| virtual void actionListenerCallback (const String& message) = 0; | |||
| }; | |||
| @@ -1,108 +0,0 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-10 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../core/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_ActionListenerList.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| // special message of our own with a string in it | |||
| class ActionMessage : public Message | |||
| { | |||
| public: | |||
| const String message; | |||
| ActionMessage (const String& messageText, void* const listener_) throw() | |||
| : message (messageText) | |||
| { | |||
| pointerParameter = listener_; | |||
| } | |||
| ~ActionMessage() throw() | |||
| { | |||
| } | |||
| private: | |||
| ActionMessage (const ActionMessage&); | |||
| ActionMessage& operator= (const ActionMessage&); | |||
| }; | |||
| //============================================================================== | |||
| ActionListenerList::ActionListenerList() | |||
| { | |||
| } | |||
| ActionListenerList::~ActionListenerList() | |||
| { | |||
| } | |||
| void ActionListenerList::addActionListener (ActionListener* const listener) | |||
| { | |||
| const ScopedLock sl (actionListenerLock_); | |||
| jassert (listener != 0); | |||
| jassert (! actionListeners_.contains (listener)); // trying to add a listener to the list twice! | |||
| if (listener != 0) | |||
| actionListeners_.add (listener); | |||
| } | |||
| void ActionListenerList::removeActionListener (ActionListener* const listener) | |||
| { | |||
| const ScopedLock sl (actionListenerLock_); | |||
| jassert (actionListeners_.contains (listener)); // trying to remove a listener that isn't on the list! | |||
| actionListeners_.removeValue (listener); | |||
| } | |||
| void ActionListenerList::removeAllActionListeners() | |||
| { | |||
| const ScopedLock sl (actionListenerLock_); | |||
| actionListeners_.clear(); | |||
| } | |||
| void ActionListenerList::sendActionMessage (const String& message) const | |||
| { | |||
| const ScopedLock sl (actionListenerLock_); | |||
| for (int i = actionListeners_.size(); --i >= 0;) | |||
| postMessage (new ActionMessage (message, static_cast <ActionListener*> (actionListeners_.getUnchecked(i)))); | |||
| } | |||
| void ActionListenerList::handleMessage (const Message& message) | |||
| { | |||
| const ActionMessage& am = (const ActionMessage&) message; | |||
| if (actionListeners_.contains (am.pointerParameter)) | |||
| static_cast <ActionListener*> (am.pointerParameter)->actionListenerCallback (am.message); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -1,96 +0,0 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-10 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ | |||
| #define __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ | |||
| #include "juce_ActionListener.h" | |||
| #include "juce_MessageListener.h" | |||
| #include "../containers/juce_SortedSet.h" | |||
| #include "../threads/juce_CriticalSection.h" | |||
| //============================================================================== | |||
| /** | |||
| A set of ActionListeners. | |||
| Listeners can be added and removed from the list, and messages can be | |||
| broadcast to all the listeners. | |||
| @see ActionListener, ActionBroadcaster | |||
| */ | |||
| class JUCE_API ActionListenerList : public MessageListener | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates an empty list. */ | |||
| ActionListenerList(); | |||
| /** Destructor. */ | |||
| ~ActionListenerList(); | |||
| //============================================================================== | |||
| /** Adds a listener to the list. | |||
| (Trying to add a listener that's already on the list will have no effect). | |||
| */ | |||
| void addActionListener (ActionListener* listener); | |||
| /** Removes a listener from the list. | |||
| If the listener isn't on the list, this won't have any effect. | |||
| */ | |||
| void removeActionListener (ActionListener* listener); | |||
| /** Removes all listeners from the list. */ | |||
| void removeAllActionListeners(); | |||
| /** Broadcasts a message to all the registered listeners. | |||
| This sends the message asynchronously. | |||
| If a listener is on the list when this method is called but is removed from | |||
| the list before the message arrives, it won't receive the message. Similarly | |||
| listeners that are added to the list after the message is sent but before it | |||
| arrives won't get the message either. | |||
| */ | |||
| void sendActionMessage (const String& message) const; | |||
| //============================================================================== | |||
| /** @internal */ | |||
| void handleMessage (const Message&); | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| SortedSet <void*> actionListeners_; | |||
| CriticalSection actionListenerLock_; | |||
| ActionListenerList (const ActionListenerList&); | |||
| ActionListenerList& operator= (const ActionListenerList&); | |||
| }; | |||
| #endif // __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ | |||
| @@ -28,45 +28,73 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AsyncUpdater.h" | |||
| #include "juce_CallbackMessage.h" | |||
| #include "../containers/juce_ScopedPointer.h" | |||
| #include "juce_MessageManager.h" | |||
| //============================================================================== | |||
| class AsyncUpdater::AsyncUpdaterMessage : public CallbackMessage | |||
| { | |||
| public: | |||
| AsyncUpdaterMessage (AsyncUpdater& owner_) | |||
| : owner (owner_) | |||
| { | |||
| } | |||
| void messageCallback() | |||
| { | |||
| if (owner.pendingMessage.compareAndSetBool (0, this)) | |||
| owner.handleAsyncUpdate(); | |||
| } | |||
| AsyncUpdater& owner; | |||
| }; | |||
| //============================================================================== | |||
| AsyncUpdater::AsyncUpdater() throw() | |||
| : asyncMessagePending (false) | |||
| { | |||
| internalAsyncHandler.owner = this; | |||
| } | |||
| AsyncUpdater::~AsyncUpdater() | |||
| { | |||
| // You're deleting this object with a background thread while there's an update | |||
| // pending on the main event thread - that's pretty dodgy threading, as the callback could | |||
| // happen after this destructor has finished. You should either use a MessageManagerLock while | |||
| // deleting this object, or find some other way to avoid such a race condition. | |||
| jassert (/*(! isUpdatePending()) ||*/ MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| pendingMessage = 0; | |||
| } | |||
| void AsyncUpdater::triggerAsyncUpdate() | |||
| { | |||
| if (! asyncMessagePending) | |||
| if (pendingMessage.value == 0) | |||
| { | |||
| asyncMessagePending = true; | |||
| internalAsyncHandler.postMessage (new Message()); | |||
| ScopedPointer<AsyncUpdaterMessage> pending (new AsyncUpdaterMessage (*this)); | |||
| if (pendingMessage.compareAndSetBool (pending, 0)) | |||
| pending.release()->post(); | |||
| } | |||
| } | |||
| void AsyncUpdater::cancelPendingUpdate() throw() | |||
| { | |||
| asyncMessagePending = false; | |||
| pendingMessage = 0; | |||
| } | |||
| void AsyncUpdater::handleUpdateNowIfNeeded() | |||
| { | |||
| if (asyncMessagePending) | |||
| { | |||
| asyncMessagePending = false; | |||
| // This can only be called by the event thread. | |||
| jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| if (pendingMessage.exchange (0) != 0) | |||
| handleAsyncUpdate(); | |||
| } | |||
| } | |||
| void AsyncUpdater::AsyncUpdaterInternal::handleMessage (const Message&) | |||
| bool AsyncUpdater::isUpdatePending() const throw() | |||
| { | |||
| owner->handleUpdateNowIfNeeded(); | |||
| return pendingMessage.value != 0; | |||
| } | |||
| @@ -26,7 +26,7 @@ | |||
| #ifndef __JUCE_ASYNCUPDATER_JUCEHEADER__ | |||
| #define __JUCE_ASYNCUPDATER_JUCEHEADER__ | |||
| #include "juce_MessageListener.h" | |||
| #include "../core/juce_Atomic.h" | |||
| //============================================================================== | |||
| @@ -79,9 +79,15 @@ public: | |||
| Use this as a kind of "flush" operation - if an update is pending, the | |||
| handleAsyncUpdate() method will be called immediately; if no update is | |||
| pending, then nothing will be done. | |||
| Because this may invoke the callback, this method must only be called on | |||
| the main event thread. | |||
| */ | |||
| void handleUpdateNowIfNeeded(); | |||
| /** Returns true if there's an update callback in the pipeline. */ | |||
| bool isUpdatePending() const throw(); | |||
| //============================================================================== | |||
| /** Called back to do whatever your class needs to do. | |||
| @@ -93,23 +99,10 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| class AsyncUpdaterInternal : public MessageListener | |||
| { | |||
| public: | |||
| AsyncUpdaterInternal() {} | |||
| ~AsyncUpdaterInternal() {} | |||
| void handleMessage (const Message&); | |||
| AsyncUpdater* owner; | |||
| private: | |||
| AsyncUpdaterInternal (const AsyncUpdaterInternal&); | |||
| AsyncUpdaterInternal& operator= (const AsyncUpdaterInternal&); | |||
| }; | |||
| class AsyncUpdaterMessage; | |||
| friend class AsyncUpdaterMessage; | |||
| AsyncUpdaterInternal internalAsyncHandler; | |||
| bool asyncMessagePending; | |||
| Atomic<AsyncUpdaterMessage*> pendingMessage; | |||
| }; | |||
| @@ -31,42 +31,25 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_MessageManager.h" | |||
| //============================================================================== | |||
| class ChangeBroadcaster::ChangeBroadcasterMessage : public CallbackMessage | |||
| { | |||
| public: | |||
| ChangeBroadcasterMessage (ChangeBroadcaster* const owner_) | |||
| : owner (owner_) | |||
| { | |||
| } | |||
| void messageCallback() | |||
| { | |||
| if (owner != 0 && owner->pendingMessage.value == this) | |||
| owner->sendSynchronousChangeMessage(); | |||
| } | |||
| ChangeBroadcaster* owner; | |||
| }; | |||
| //============================================================================== | |||
| ChangeBroadcaster::ChangeBroadcaster() throw() | |||
| { | |||
| // are you trying to create this object before or after juce has been intialised?? | |||
| jassert (MessageManager::instance != 0); | |||
| callback.owner = this; | |||
| } | |||
| ChangeBroadcaster::~ChangeBroadcaster() | |||
| { | |||
| // all event-based objects must be deleted BEFORE juce is shut down! | |||
| jassert (MessageManager::instance != 0); | |||
| invalidatePendingMessage(); | |||
| } | |||
| void ChangeBroadcaster::addChangeListener (ChangeListener* const listener) | |||
| { | |||
| // Listeners can only be safely added when the event thread is locked... | |||
| // Listeners can only be safely added when the event thread is locked | |||
| // You can use a MessageManagerLock if you need to call this from another thread. | |||
| jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| changeListeners.add (listener); | |||
| @@ -74,7 +57,8 @@ void ChangeBroadcaster::addChangeListener (ChangeListener* const listener) | |||
| void ChangeBroadcaster::removeChangeListener (ChangeListener* const listener) | |||
| { | |||
| // Listeners can only be safely added when the event thread is locked... | |||
| // Listeners can only be safely added when the event thread is locked | |||
| // You can use a MessageManagerLock if you need to call this from another thread. | |||
| jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| changeListeners.remove (listener); | |||
| @@ -82,28 +66,17 @@ void ChangeBroadcaster::removeChangeListener (ChangeListener* const listener) | |||
| void ChangeBroadcaster::removeAllChangeListeners() | |||
| { | |||
| // Listeners can only be safely added when the event thread is locked... | |||
| // Listeners can only be safely added when the event thread is locked | |||
| // You can use a MessageManagerLock if you need to call this from another thread. | |||
| jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| changeListeners.clear(); | |||
| } | |||
| void ChangeBroadcaster::invalidatePendingMessage() | |||
| { | |||
| ChangeBroadcasterMessage* const oldMessage = pendingMessage.exchange (0); | |||
| if (oldMessage != 0) | |||
| oldMessage->owner = 0; | |||
| } | |||
| void ChangeBroadcaster::sendChangeMessage() | |||
| { | |||
| if (pendingMessage.value == 0 && changeListeners.size() > 0) | |||
| { | |||
| ScopedPointer<ChangeBroadcasterMessage> pending (new ChangeBroadcasterMessage (this)); | |||
| if (pendingMessage.compareAndSetBool (pending, 0)) | |||
| pending.release()->post(); | |||
| } | |||
| if (changeListeners.size() > 0) | |||
| callback.triggerAsyncUpdate(); | |||
| } | |||
| void ChangeBroadcaster::sendSynchronousChangeMessage() | |||
| @@ -111,14 +84,30 @@ void ChangeBroadcaster::sendSynchronousChangeMessage() | |||
| // This can only be called by the event thread. | |||
| jassert (MessageManager::getInstance()->isThisTheMessageThread()); | |||
| invalidatePendingMessage(); | |||
| changeListeners.call (&ChangeListener::changeListenerCallback, this); | |||
| callback.cancelPendingUpdate(); | |||
| callListeners(); | |||
| } | |||
| void ChangeBroadcaster::dispatchPendingMessages() | |||
| { | |||
| if (pendingMessage.get() != 0) | |||
| sendSynchronousChangeMessage(); | |||
| callback.handleUpdateNowIfNeeded(); | |||
| } | |||
| void ChangeBroadcaster::callListeners() | |||
| { | |||
| changeListeners.call (&ChangeListener::changeListenerCallback, this); | |||
| } | |||
| //============================================================================== | |||
| ChangeBroadcaster::ChangeBroadcasterCallback::ChangeBroadcasterCallback() | |||
| : owner (0) | |||
| { | |||
| } | |||
| void ChangeBroadcaster::ChangeBroadcasterCallback::handleAsyncUpdate() | |||
| { | |||
| jassert (owner != 0); | |||
| owner->callListeners(); | |||
| } | |||
| @@ -28,7 +28,7 @@ | |||
| #include "juce_ChangeListener.h" | |||
| #include "juce_ListenerList.h" | |||
| #include "../core/juce_Atomic.h" | |||
| #include "juce_AsyncUpdater.h" | |||
| //============================================================================== | |||
| @@ -88,13 +88,20 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| class ChangeBroadcasterMessage; | |||
| friend class ChangeBroadcasterMessage; | |||
| class ChangeBroadcasterCallback : public AsyncUpdater | |||
| { | |||
| public: | |||
| ChangeBroadcasterCallback(); | |||
| void handleAsyncUpdate(); | |||
| Atomic<ChangeBroadcasterMessage*> pendingMessage; | |||
| ChangeBroadcaster* owner; | |||
| }; | |||
| friend class ChangeBroadcasterCallback; | |||
| ChangeBroadcasterCallback callback; | |||
| ListenerList <ChangeListener> changeListeners; | |||
| void invalidatePendingMessage(); | |||
| void callListeners(); | |||
| ChangeBroadcaster (const ChangeBroadcaster&); | |||
| ChangeBroadcaster& operator= (const ChangeBroadcaster&); | |||
| @@ -35,7 +35,8 @@ Message::Message() throw() | |||
| : intParameter1 (0), | |||
| intParameter2 (0), | |||
| intParameter3 (0), | |||
| pointerParameter (0) | |||
| pointerParameter (0), | |||
| messageRecipient (0) | |||
| { | |||
| } | |||
| @@ -46,7 +47,8 @@ Message::Message (const int intParameter1_, | |||
| : intParameter1 (intParameter1_), | |||
| intParameter2 (intParameter2_), | |||
| intParameter3 (intParameter3_), | |||
| pointerParameter (pointerParameter_) | |||
| pointerParameter (pointerParameter_), | |||
| messageRecipient (0) | |||
| { | |||
| } | |||
| @@ -28,7 +28,7 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_MessageManager.h" | |||
| #include "juce_ActionListenerList.h" | |||
| #include "juce_ActionBroadcaster.h" | |||
| #include "../application/juce_Application.h" | |||
| #include "../gui/components/juce_Component.h" | |||
| #include "../threads/juce_Thread.h" | |||
| @@ -56,7 +56,7 @@ MessageManager::MessageManager() throw() | |||
| MessageManager::~MessageManager() throw() | |||
| { | |||
| broadcastListeners = 0; | |||
| broadcaster = 0; | |||
| doPlatformSpecificShutdown(); | |||
| @@ -88,48 +88,41 @@ void MessageManager::postMessageToQueue (Message* const message) | |||
| } | |||
| //============================================================================== | |||
| CallbackMessage::CallbackMessage() throw() {} | |||
| CallbackMessage::~CallbackMessage() {} | |||
| CallbackMessage::CallbackMessage() throw() {} | |||
| CallbackMessage::~CallbackMessage() {} | |||
| void CallbackMessage::post() | |||
| { | |||
| if (MessageManager::instance != 0) | |||
| MessageManager::instance->postCallbackMessage (this); | |||
| } | |||
| void MessageManager::postCallbackMessage (Message* const message) | |||
| { | |||
| message->messageRecipient = 0; | |||
| postMessageToQueue (message); | |||
| MessageManager::instance->postMessageToQueue (this); | |||
| } | |||
| //============================================================================== | |||
| // not for public use.. | |||
| void MessageManager::deliverMessage (Message* const message) | |||
| { | |||
| const ScopedPointer <Message> messageDeleter (message); | |||
| MessageListener* const recipient = message->messageRecipient; | |||
| JUCE_TRY | |||
| { | |||
| if (messageListeners.contains (recipient)) | |||
| { | |||
| recipient->handleMessage (*message); | |||
| } | |||
| else if (recipient == 0) | |||
| const ScopedPointer <Message> messageDeleter (message); | |||
| MessageListener* const recipient = message->messageRecipient; | |||
| if (recipient == 0) | |||
| { | |||
| if (message->intParameter1 == quitMessageId) | |||
| CallbackMessage* const callbackMessage = dynamic_cast <CallbackMessage*> (message); | |||
| if (callbackMessage != 0) | |||
| { | |||
| quitMessageReceived = true; | |||
| callbackMessage->messageCallback(); | |||
| } | |||
| else | |||
| else if (message->intParameter1 == quitMessageId) | |||
| { | |||
| CallbackMessage* const cm = dynamic_cast <CallbackMessage*> (message); | |||
| if (cm != 0) | |||
| cm->messageCallback(); | |||
| quitMessageReceived = true; | |||
| } | |||
| } | |||
| else if (messageListeners.contains (recipient)) | |||
| { | |||
| recipient->handleMessage (*message); | |||
| } | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| } | |||
| @@ -145,10 +138,7 @@ void MessageManager::runDispatchLoop() | |||
| void MessageManager::stopDispatchLoop() | |||
| { | |||
| Message* const m = new Message (quitMessageId, 0, 0, 0); | |||
| m->messageRecipient = 0; | |||
| postMessageToQueue (m); | |||
| postMessageToQueue (new Message (quitMessageId, 0, 0, 0)); | |||
| quitMessagePosted = true; | |||
| } | |||
| @@ -182,22 +172,22 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||
| //============================================================================== | |||
| void MessageManager::deliverBroadcastMessage (const String& value) | |||
| { | |||
| if (broadcastListeners != 0) | |||
| broadcastListeners->sendActionMessage (value); | |||
| if (broadcaster != 0) | |||
| broadcaster->sendActionMessage (value); | |||
| } | |||
| void MessageManager::registerBroadcastListener (ActionListener* const listener) | |||
| { | |||
| if (broadcastListeners == 0) | |||
| broadcastListeners = new ActionListenerList(); | |||
| if (broadcaster == 0) | |||
| broadcaster = new ActionBroadcaster(); | |||
| broadcastListeners->addActionListener (listener); | |||
| broadcaster->addActionListener (listener); | |||
| } | |||
| void MessageManager::deregisterBroadcastListener (ActionListener* const listener) | |||
| { | |||
| if (broadcastListeners != 0) | |||
| broadcastListeners->removeActionListener (listener); | |||
| if (broadcaster != 0) | |||
| broadcaster->removeActionListener (listener); | |||
| } | |||
| //============================================================================== | |||
| @@ -239,7 +229,6 @@ class MessageManagerLock::SharedEvents : public ReferenceCountedObject | |||
| { | |||
| public: | |||
| SharedEvents() {} | |||
| ~SharedEvents() {} | |||
| /* This class just holds a couple of events to communicate between the BlockingMessage | |||
| and the MessageManagerLock. Because both of these objects may be deleted at any time, | |||
| @@ -255,7 +244,6 @@ class MessageManagerLock::BlockingMessage : public CallbackMessage | |||
| { | |||
| public: | |||
| BlockingMessage (MessageManagerLock::SharedEvents* const events_) : events (events_) {} | |||
| ~BlockingMessage() throw() {} | |||
| void messageCallback() | |||
| { | |||
| @@ -31,7 +31,7 @@ | |||
| #include "../containers/juce_ScopedPointer.h" | |||
| #include "../threads/juce_Thread.h" | |||
| #include "../threads/juce_ThreadPool.h" | |||
| #include "juce_ActionListenerList.h" | |||
| #include "juce_ActionBroadcaster.h" | |||
| #include "juce_CallbackMessage.h" | |||
| class Component; | |||
| class MessageManagerLock; | |||
| @@ -175,7 +175,7 @@ private: | |||
| static MessageManager* instance; | |||
| SortedSet <const MessageListener*> messageListeners; | |||
| ScopedPointer <ActionListenerList> broadcastListeners; | |||
| ScopedPointer <ActionBroadcaster> broadcaster; | |||
| friend class JUCEApplication; | |||
| bool quitMessagePosted, quitMessageReceived; | |||
| @@ -184,7 +184,6 @@ private: | |||
| static void* exitModalLoopCallback (void*); | |||
| void postMessageToQueue (Message* message); | |||
| void postCallbackMessage (Message* message); | |||
| static void doPlatformSpecificInitialisation(); | |||
| static void doPlatformSpecificShutdown(); | |||
| @@ -317,5 +316,4 @@ private: | |||
| }; | |||
| #endif // __JUCE_MESSAGEMANAGER_JUCEHEADER__ | |||
| @@ -29,7 +29,6 @@ | |||
| #include "../juce_Component.h" | |||
| #include "../mouse/juce_MouseCursor.h" | |||
| #include "../keyboard/juce_TextInputTarget.h" | |||
| #include "../../../events/juce_MessageListener.h" | |||
| #include "../../../text/juce_StringArray.h" | |||
| #include "../../graphics/geometry/juce_RectangleList.h" | |||
| @@ -230,9 +230,6 @@ | |||
| #ifndef __JUCE_ACTIONLISTENER_JUCEHEADER__ | |||
| #include "events/juce_ActionListener.h" | |||
| #endif | |||
| #ifndef __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ | |||
| #include "events/juce_ActionListenerList.h" | |||
| #endif | |||
| #ifndef __JUCE_ASYNCUPDATER_JUCEHEADER__ | |||
| #include "events/juce_AsyncUpdater.h" | |||
| #endif | |||
| @@ -388,7 +388,7 @@ namespace NumberToStringConverters | |||
| else | |||
| { | |||
| #if JUCE_WINDOWS | |||
| #if JUCE_VC8_OR_EARLIER || JUCE_MINGW | |||
| #if JUCE_VC7_OR_EARLIER || JUCE_MINGW | |||
| len = _snwprintf (buffer, numChars, L"%.9g", n); | |||
| #else | |||
| len = _snwprintf_s (buffer, numChars, _TRUNCATE, L"%.9g", n); | |||