From 2bb0c77216be5b22fc43526ecbc00c0657d73818 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Mon, 20 Dec 2010 16:52:20 +0000 Subject: [PATCH] New class: WeakReference. Used this to clean up and simplify implementation of Component::SafePointer and BailOutChecker. --- Builds/MacOSX/Juce.xcodeproj/project.pbxproj | 4 +- Builds/VisualStudio2005/Juce.vcproj | 1 + Builds/VisualStudio2008/Juce.vcproj | 1 + Builds/VisualStudio2008_DLL/Juce.vcproj | 1 + Builds/VisualStudio2010/Juce.vcxproj | 1 + Builds/VisualStudio2010/Juce.vcxproj.filters | 3 + Builds/iPhone/Juce.xcodeproj/project.pbxproj | 4 +- Juce.jucer | 2 + juce_amalgamated.cpp | 178 ++++++------ juce_amalgamated.h | 265 ++++++++++++++---- src/containers/juce_WeakReference.h | 196 +++++++++++++ src/core/juce_StandardHeader.h | 2 +- src/gui/components/buttons/juce_Button.cpp | 6 +- src/gui/components/buttons/juce_Button.h | 2 +- src/gui/components/controls/juce_Label.cpp | 4 +- src/gui/components/controls/juce_Label.h | 6 +- src/gui/components/controls/juce_Toolbar.cpp | 2 +- src/gui/components/controls/juce_TreeView.cpp | 4 +- .../filebrowser/juce_FileChooser.cpp | 2 +- src/gui/components/juce_Component.cpp | 100 ++++--- src/gui/components/juce_Component.h | 71 ++--- src/gui/components/juce_Desktop.cpp | 2 +- .../components/juce_ModalComponentManager.cpp | 2 +- .../layout/juce_ComponentAnimator.cpp | 4 +- .../layout/juce_ComponentMovementWatcher.h | 2 +- .../layout/juce_ResizableBorderComponent.h | 2 +- .../layout/juce_ResizableCornerComponent.h | 2 +- .../layout/juce_TabbedComponent.cpp | 12 +- .../components/layout/juce_TabbedComponent.h | 4 +- src/gui/components/layout/juce_Viewport.cpp | 2 +- src/gui/components/layout/juce_Viewport.h | 2 +- src/gui/components/menus/juce_PopupMenu.cpp | 8 +- .../mouse/juce_DragAndDropContainer.cpp | 8 +- .../mouse/juce_MouseInputSource.cpp | 4 +- .../components/windows/juce_AlertWindow.cpp | 2 +- .../components/windows/juce_ComponentPeer.cpp | 8 +- .../components/windows/juce_ComponentPeer.h | 2 +- src/juce_core_includes.h | 3 + src/native/linux/juce_linux_Windowing.cpp | 2 +- src/native/mac/juce_mac_OpenGLComponent.mm | 2 +- src/native/windows/juce_win32_Windowing.cpp | 2 +- 41 files changed, 655 insertions(+), 275 deletions(-) create mode 100644 src/containers/juce_WeakReference.h diff --git a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj index ee5e9b7dbe..6375d271e6 100644 --- a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj @@ -516,6 +516,7 @@ 7CABDD863B47D8ADC900A4D8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ValueTree.h; path = ../../src/containers/juce_ValueTree.h; sourceTree = SOURCE_ROOT; }; 4DF9D333038A442870668D31 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Variant.cpp; path = ../../src/containers/juce_Variant.cpp; sourceTree = SOURCE_ROOT; }; A81B4FC81A75E21E5B96E506 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Variant.h; path = ../../src/containers/juce_Variant.h; sourceTree = SOURCE_ROOT; }; + 35D32D0A21ABDB7861E3E5B8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_WeakReference.h; path = ../../src/containers/juce_WeakReference.h; sourceTree = SOURCE_ROOT; }; 149E6ECBA264A264C7BB3FB3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Atomic.h; path = ../../src/core/juce_Atomic.h; sourceTree = SOURCE_ROOT; }; 45AFA4791D59FBB1B548FB2C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ByteOrder.h; path = ../../src/core/juce_ByteOrder.h; sourceTree = SOURCE_ROOT; }; D66C00E06B06EAD3B5257DD6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileLogger.cpp; path = ../../src/core/juce_FileLogger.cpp; sourceTree = SOURCE_ROOT; }; @@ -1240,7 +1241,8 @@ 5D27EE211D9BFF6A58C4DC42, 7CABDD863B47D8ADC900A4D8, 4DF9D333038A442870668D31, - A81B4FC81A75E21E5B96E506 ); name = containers; sourceTree = ""; }; + A81B4FC81A75E21E5B96E506, + 35D32D0A21ABDB7861E3E5B8 ); name = containers; sourceTree = ""; }; 1AF37A533ABDD889670F9349 = { isa = PBXGroup; children = ( 149E6ECBA264A264C7BB3FB3, 45AFA4791D59FBB1B548FB2C, diff --git a/Builds/VisualStudio2005/Juce.vcproj b/Builds/VisualStudio2005/Juce.vcproj index 4e8c3542bb..dbc787e873 100644 --- a/Builds/VisualStudio2005/Juce.vcproj +++ b/Builds/VisualStudio2005/Juce.vcproj @@ -379,6 +379,7 @@ + diff --git a/Builds/VisualStudio2008/Juce.vcproj b/Builds/VisualStudio2008/Juce.vcproj index 3cfa9c6ff9..6718a205e2 100644 --- a/Builds/VisualStudio2008/Juce.vcproj +++ b/Builds/VisualStudio2008/Juce.vcproj @@ -379,6 +379,7 @@ + diff --git a/Builds/VisualStudio2008_DLL/Juce.vcproj b/Builds/VisualStudio2008_DLL/Juce.vcproj index 465db68f8e..d78b575754 100644 --- a/Builds/VisualStudio2008_DLL/Juce.vcproj +++ b/Builds/VisualStudio2008_DLL/Juce.vcproj @@ -381,6 +381,7 @@ + diff --git a/Builds/VisualStudio2010/Juce.vcxproj b/Builds/VisualStudio2010/Juce.vcxproj index e54ecca3ba..18140c2d46 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj +++ b/Builds/VisualStudio2010/Juce.vcxproj @@ -526,6 +526,7 @@ + diff --git a/Builds/VisualStudio2010/Juce.vcxproj.filters b/Builds/VisualStudio2010/Juce.vcxproj.filters index 9088669d98..ef9f9eac66 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj.filters +++ b/Builds/VisualStudio2010/Juce.vcxproj.filters @@ -1500,6 +1500,9 @@ Juce\Source\containers + + Juce\Source\containers + Juce\Source\core diff --git a/Builds/iPhone/Juce.xcodeproj/project.pbxproj b/Builds/iPhone/Juce.xcodeproj/project.pbxproj index 907e9ebff7..f6dd4ddc2a 100644 --- a/Builds/iPhone/Juce.xcodeproj/project.pbxproj +++ b/Builds/iPhone/Juce.xcodeproj/project.pbxproj @@ -516,6 +516,7 @@ 7CABDD863B47D8ADC900A4D8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ValueTree.h; path = ../../src/containers/juce_ValueTree.h; sourceTree = SOURCE_ROOT; }; 4DF9D333038A442870668D31 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Variant.cpp; path = ../../src/containers/juce_Variant.cpp; sourceTree = SOURCE_ROOT; }; A81B4FC81A75E21E5B96E506 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Variant.h; path = ../../src/containers/juce_Variant.h; sourceTree = SOURCE_ROOT; }; + 35D32D0A21ABDB7861E3E5B8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_WeakReference.h; path = ../../src/containers/juce_WeakReference.h; sourceTree = SOURCE_ROOT; }; 149E6ECBA264A264C7BB3FB3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Atomic.h; path = ../../src/core/juce_Atomic.h; sourceTree = SOURCE_ROOT; }; 45AFA4791D59FBB1B548FB2C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ByteOrder.h; path = ../../src/core/juce_ByteOrder.h; sourceTree = SOURCE_ROOT; }; D66C00E06B06EAD3B5257DD6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileLogger.cpp; path = ../../src/core/juce_FileLogger.cpp; sourceTree = SOURCE_ROOT; }; @@ -1240,7 +1241,8 @@ 5D27EE211D9BFF6A58C4DC42, 7CABDD863B47D8ADC900A4D8, 4DF9D333038A442870668D31, - A81B4FC81A75E21E5B96E506 ); name = containers; sourceTree = ""; }; + A81B4FC81A75E21E5B96E506, + 35D32D0A21ABDB7861E3E5B8 ); name = containers; sourceTree = ""; }; 1AF37A533ABDD889670F9349 = { isa = PBXGroup; children = ( 149E6ECBA264A264C7BB3FB3, 45AFA4791D59FBB1B548FB2C, diff --git a/Juce.jucer b/Juce.jucer index a4303b177c..6fb18b7d23 100644 --- a/Juce.jucer +++ b/Juce.jucer @@ -415,6 +415,8 @@ file="src/containers/juce_Variant.cpp"/> + 0) + removeChildComponent (childComponentList_.size() - 1, false, true); + if (parentComponent_ != 0) - { - parentComponent_->removeChildComponent (this); - } + parentComponent_->removeChildComponent (parentComponent_->childComponentList_.indexOf (this), true, false); else if (currentlyFocusedComponent == this || isParentOf (currentlyFocusedComponent)) - { - giveAwayFocus(); - } + giveAwayFocus (currentlyFocusedComponent != this); if (flags.hasHeavyweightPeerFlag) removeFromDesktop(); - for (int i = childComponentList_.size(); --i >= 0;) - childComponentList_.getUnchecked(i)->parentComponent_ = 0; + // Something has added some children to this component during its destructor! Not a smart idea! + jassert (childComponentList_.size() == 0); +} + +const WeakReference::SharedRef& Component::getWeakReference() +{ + return weakReferenceMaster (this); } void Component::setName (const String& name) @@ -40216,7 +40222,7 @@ void Component::setVisible (bool shouldBeVisible) // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. CHECK_MESSAGE_MANAGER_IS_LOCKED - SafePointer safePointer (this); + WeakReference safePointer (this); flags.visibleFlag = shouldBeVisible; @@ -40231,7 +40237,7 @@ void Component::setVisible (bool shouldBeVisible) if (parentComponent_ != 0) parentComponent_->grabKeyboardFocus(); else - giveAwayFocus(); + giveAwayFocus (true); } } @@ -40319,7 +40325,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) if (styleWanted != currentStyleFlags || ! flags.hasHeavyweightPeerFlag) { - SafePointer safePointer (this); + WeakReference safePointer (this); #if JUCE_LINUX // it's wise to give the component a non-zero size before @@ -41077,10 +41083,15 @@ void Component::addAndMakeVisible (Component* const child, int zOrder) void Component::removeChildComponent (Component* const child) { - removeChildComponent (childComponentList_.indexOf (child)); + removeChildComponent (childComponentList_.indexOf (child), true, true); } Component* Component::removeChildComponent (const int index) +{ + return removeChildComponent (index, true, true); +} + +Component* Component::removeChildComponent (const int index, bool sendParentEvents, const bool sendChildEvents) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. @@ -41090,9 +41101,9 @@ Component* Component::removeChildComponent (const int index) if (child != 0) { - const bool childShowing = child->isShowing(); + sendParentEvents = sendParentEvents && child->isShowing(); - if (childShowing) + if (sendParentEvents) { sendFakeMouseMove(); child->repaintParent(); @@ -41104,19 +41115,22 @@ Component* Component::removeChildComponent (const int index) // (NB: there are obscure situations where a childShowing = false, but it still has the focus) if (currentlyFocusedComponent == child || child->isParentOf (currentlyFocusedComponent)) { - SafePointer thisPointer (this); + const WeakReference thisPointer (this); - giveAwayFocus(); + giveAwayFocus (sendChildEvents || currentlyFocusedComponent != child); if (thisPointer == 0) return child; - if (childShowing) + if (sendParentEvents) grabKeyboardFocus(); } - child->internalHierarchyChanged(); - internalChildrenChanged(); + if (sendChildEvents) + child->internalHierarchyChanged(); + + if (sendParentEvents) + internalChildrenChanged(); } return child; @@ -41276,10 +41290,6 @@ void Component::exitModalState (const int returnValue) } else { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED - class ExitModalStateMessage : public CallbackMessage { public: @@ -41288,12 +41298,12 @@ void Component::exitModalState (const int returnValue) void messageCallback() { - if (target.getComponent() != 0) // (getComponent() required for VS2003 bug) + if (target.get() != 0) // (get() required for VS2003 bug) target->exitModalState (result); } private: - Component::SafePointer target; + WeakReference target; int result; }; @@ -41676,7 +41686,7 @@ void Component::sendLookAndFeelChange() { repaint(); - SafePointer safePointer (this); + WeakReference safePointer (this); lookAndFeelChanged(); @@ -41889,10 +41899,6 @@ void Component::paintOverChildren (Graphics&) void Component::postCommandMessage (const int commandId) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED - class CustomCommandMessage : public CallbackMessage { public: @@ -41901,12 +41907,12 @@ void Component::postCommandMessage (const int commandId) void messageCallback() { - if (target != 0) + if (target.get() != 0) // (get() required for VS2003 bug) target->handleCommandMessage (commandId); } private: - Component::SafePointer target; + WeakReference target; int commandId; }; @@ -42270,7 +42276,7 @@ void Component::focusGained (FocusChangeType) void Component::internalFocusGain (const FocusChangeType cause) { - SafePointer safePointer (this); + WeakReference safePointer (this); focusGained (cause); @@ -42285,7 +42291,7 @@ void Component::focusLost (FocusChangeType) void Component::internalFocusLoss (const FocusChangeType cause) { - SafePointer safePointer (this); + WeakReference safePointer (this); focusLost (focusChangedDirectly); @@ -42306,7 +42312,7 @@ void Component::internalChildFocusChange (FocusChangeType cause) { flags.childCompFocusedFlag = childIsNowFocused; - SafePointer safePointer (this); + WeakReference safePointer (this); focusOfChildComponentChanged (cause); if (safePointer == 0) @@ -42338,7 +42344,7 @@ void Component::setEnabled (const bool shouldBeEnabled) void Component::sendEnablementChangeMessage() { - SafePointer safePointer (this); + WeakReference safePointer (this); enablementChanged(); @@ -42425,13 +42431,13 @@ void Component::takeKeyboardFocus (const FocusChangeType cause) if (peer != 0) { - SafePointer safePointer (this); + WeakReference safePointer (this); peer->grabFocus(); if (peer->isFocused() && currentlyFocusedComponent != this) { - SafePointer componentLosingFocus (currentlyFocusedComponent); + WeakReference componentLosingFocus (currentlyFocusedComponent); currentlyFocusedComponent = this; @@ -42541,7 +42547,7 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) { if (nextComp->isCurrentlyBlockedByAnotherModalComponent()) { - SafePointer nextCompPointer (nextComp); + WeakReference nextCompPointer (nextComp); internalModalInputAttempt(); if (nextCompPointer == 0 || nextComp->isCurrentlyBlockedByAnotherModalComponent()) @@ -42568,12 +42574,12 @@ Component* JUCE_CALLTYPE Component::getCurrentlyFocusedComponent() throw() return currentlyFocusedComponent; } -void Component::giveAwayFocus() +void Component::giveAwayFocus (const bool sendFocusLossEvent) { Component* const componentLosingFocus = currentlyFocusedComponent; currentlyFocusedComponent = 0; - if (componentLosingFocus != 0) + if (sendFocusLossEvent && componentLosingFocus != 0) componentLosingFocus->internalFocusLoss (focusChangedDirectly); Desktop::getInstance().triggerFocusCallback(); @@ -42665,15 +42671,21 @@ ComponentPeer* Component::getPeer() const return parentComponent_->getPeer(); } -Component::BailOutChecker::BailOutChecker (Component* const component1, Component* const component2_) - : safePointer1 (component1), safePointer2 (component2_), component2 (component2_) +Component::BailOutChecker::BailOutChecker (Component* const component) + : safePointer1 (component) +{ + jassert (component != 0); +} + +Component::BailOutChecker::BailOutChecker (Component* const component1, Component* const component2) + : safePointer1 (component1), safePointer2 (component2) { jassert (component1 != 0); } bool Component::BailOutChecker::shouldBailOut() const throw() { - return safePointer1 == 0 || safePointer2.getComponent() != component2; + return safePointer1 == 0 || safePointer2.wasObjectDeleted(); } END_JUCE_NAMESPACE @@ -42978,7 +42990,7 @@ void Desktop::handleAsyncUpdate() { // The component may be deleted during this operation, but we'll use a SafePointer rather than a // BailOutChecker so that any remaining listeners will still get a callback (with a null pointer). - Component::SafePointer currentFocus (Component::getCurrentlyFocusedComponent()); + WeakReference currentFocus (Component::getCurrentlyFocusedComponent()); focusListeners.call (&FocusChangeListener::globalFocusChanged, currentFocus); } @@ -43320,7 +43332,7 @@ int ModalComponentManager::runEventLoopForCurrentComponent() if (currentlyModal == 0) return 0; - Component::SafePointer prevFocused (Component::getCurrentlyFocusedComponent()); + WeakReference prevFocused (Component::getCurrentlyFocusedComponent()); int returnValue = 0; bool finished = false; @@ -43509,7 +43521,7 @@ void Button::setToggleState (const bool shouldBeOn, if (sendChangeNotification) { - Component::SafePointer deletionWatcher (this); + WeakReference deletionWatcher (this); sendClickMessage (ModifierKeys()); if (deletionWatcher == 0) @@ -43560,7 +43572,7 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) if (p != 0 && radioGroupId != 0) { - Component::SafePointer deletionWatcher (this); + WeakReference deletionWatcher (this); for (int i = p->getNumChildComponents(); --i >= 0;) { @@ -43815,7 +43827,7 @@ void Button::parentHierarchyChanged() { Component* const newKeySource = (shortcuts.size() == 0) ? 0 : getTopLevelComponent(); - if (newKeySource != keySource.getComponent()) + if (newKeySource != keySource.get()) { if (keySource != 0) keySource->removeKeyListener (this); @@ -48310,7 +48322,7 @@ void Label::hideEditor (const bool discardCurrentEditorContents) { if (editor != 0) { - Component::SafePointer deletionChecker (this); + WeakReference deletionChecker (this); editorAboutToBeHidden (editor); @@ -48490,7 +48502,7 @@ void Label::textEditorReturnKeyPressed (TextEditor& ed) if (changed) { - Component::SafePointer deletionChecker (this); + WeakReference deletionChecker (this); textWasEdited(); if (deletionChecker != 0) @@ -55612,7 +55624,7 @@ void Toolbar::showCustomisationDialog (ToolbarItemFactory& factory, const int op setEditingActive (true); #if JUCE_DEBUG - Component::SafePointer checker (this); + WeakReference checker (this); #endif ToolbarCustomisationDialog dw (factory, this, optionFlags); @@ -56250,10 +56262,10 @@ private: ~RowItem() { - component.deleteAndZero(); + delete component.get(); } - Component::SafePointer component; + WeakReference component; TreeViewItem* item; int uid; bool shouldKeep; @@ -58567,7 +58579,7 @@ bool FileChooser::showDialog (const bool selectsDirectories, const bool selectMultipleFiles, FilePreviewComponent* const previewComponent) { - Component::SafePointer previouslyFocused (Component::getCurrentlyFocusedComponent()); + WeakReference previouslyFocused (Component::getCurrentlyFocusedComponent()); results.clear(); @@ -61347,7 +61359,7 @@ public: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProxyComponent); }; - Component::SafePointer component; + WeakReference component; ScopedPointer proxy; Rectangle destination; @@ -61379,7 +61391,7 @@ ComponentAnimator::~ComponentAnimator() ComponentAnimator::AnimationTask* ComponentAnimator::findTaskFor (Component* const component) const { for (int i = tasks.size(); --i >= 0;) - if (component == tasks.getUnchecked(i)->component.getComponent()) + if (component == tasks.getUnchecked(i)->component.get()) return tasks.getUnchecked(i); return 0; @@ -64202,10 +64214,10 @@ void TabbedComponent::clearTabs() for (int i = contentComponents.size(); --i >= 0;) { - Component::SafePointer& c = *contentComponents.getUnchecked (i); + WeakReference& c = *contentComponents.getUnchecked (i); if (c != 0 && (bool) c->getProperties() [deleteComponentId]) - c.deleteAndZero(); + delete c.get(); } contentComponents.clear(); @@ -64217,7 +64229,7 @@ void TabbedComponent::addTab (const String& tabName, const bool deleteComponentWhenNotNeeded, const int insertIndex) { - contentComponents.insert (insertIndex, new Component::SafePointer (contentComponent)); + contentComponents.insert (insertIndex, new WeakReference (contentComponent)); if (contentComponent != 0) contentComponent->getProperties().set (deleteComponentId, deleteComponentWhenNotNeeded); @@ -64232,12 +64244,12 @@ void TabbedComponent::setTabName (const int tabIndex, const String& newName) void TabbedComponent::removeTab (const int tabIndex) { - Component::SafePointer* c = contentComponents [tabIndex]; + WeakReference* c = contentComponents [tabIndex]; if (c != 0) { if ((bool) ((*c)->getProperties() [deleteComponentId])) - c->deleteAndZero(); + delete c->get(); contentComponents.remove (tabIndex); tabs->removeTab (tabIndex); @@ -64256,7 +64268,7 @@ const StringArray TabbedComponent::getTabNames() const Component* TabbedComponent::getTabContentComponent (const int tabIndex) const throw() { - Component::SafePointer* const c = contentComponents [tabIndex]; + WeakReference* const c = contentComponents [tabIndex]; return c != 0 ? *c : 0; } @@ -64468,7 +64480,7 @@ void Viewport::deleteContentComp() void Viewport::setViewedComponent (Component* const newViewedComponent) { - if (contentComp.getComponent() != newViewedComponent) + if (contentComp.get() != newViewedComponent) { deleteContentComp(); contentComp = newViewedComponent; @@ -69202,7 +69214,7 @@ public: void inputAttemptWhenModal() { - Component::SafePointer deletionChecker (this); + WeakReference deletionChecker (this); timerCallback(); @@ -69392,7 +69404,7 @@ private: Component::SafePointer currentChild; ScopedPointer activeSubMenu; ApplicationCommandManager** managerOfChosenCommand; - Component::SafePointer componentAttachedTo; + WeakReference componentAttachedTo; Component* componentAttachedToOriginal; Rectangle windowPos; Point lastMouse; @@ -70146,8 +70158,8 @@ int PopupMenu::showMenu (const Rectangle& target, { ScopedPointer userCallbackDeleter (userCallback); - Component::SafePointer prevFocused (Component::getCurrentlyFocusedComponent()); - Component::SafePointer prevTopLevel ((prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0); + WeakReference prevFocused (Component::getCurrentlyFocusedComponent()); + WeakReference prevTopLevel ((prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0); Window::wasHiddenBecauseOfAppChange() = false; PopupMenuCompletionCallback* callback = new PopupMenuCompletionCallback(); @@ -70628,7 +70640,7 @@ public: if (owner->shouldDropFilesWhenDraggedExternally (dragDescLocal, source, files, canMoveFiles) && files.size() > 0) { - Component::SafePointer cdw (this); + WeakReference cdw (this); setVisible (false); if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) @@ -70667,11 +70679,11 @@ public: private: Image image; - Component::SafePointer source; - Component::SafePointer mouseDragSource; + WeakReference source; + WeakReference mouseDragSource; DragAndDropContainer* const owner; - Component::SafePointer currentlyOverComp; + WeakReference currentlyOverComp; DragAndDropTarget* getCurrentlyOver() { return dynamic_cast (static_cast (currentlyOverComp)); @@ -71302,7 +71314,7 @@ public: if (newComponent != current) { - Component::SafePointer safeNewComp (newComponent); + WeakReference safeNewComp (newComponent); const ModifierKeys originalButtonState (buttonState); if (current != 0) @@ -71541,7 +71553,7 @@ public: private: MouseInputSource& source; - Component::SafePointer componentUnderMouse; + WeakReference componentUnderMouse; ComponentPeer* lastPeer; Point unboundedMouseOffset; @@ -76949,7 +76961,7 @@ public: String title, message, button1, button2, button3; AlertWindow::AlertIconType iconType; int numButtons, returnValue; - Component::SafePointer associatedComponent; + WeakReference associatedComponent; int showModal() const { @@ -77390,7 +77402,7 @@ bool ComponentPeer::handleKeyPress (const int keyCode, while (target != 0) { - const Component::SafePointer deletionChecker (target); + const WeakReference deletionChecker (target); if (target->keyListeners_ != 0) { @@ -77444,7 +77456,7 @@ bool ComponentPeer::handleKeyUpOrDown (const bool isKeyDown) while (target != 0) { - const Component::SafePointer deletionChecker (target); + const WeakReference deletionChecker (target); keyWasUsed = target->keyStateChanged (isKeyDown); @@ -77520,7 +77532,7 @@ void ComponentPeer::handleMovedOrResized() if (component->flags.hasHeavyweightPeerFlag && ! nowMinimised) { - const Component::SafePointer deletionChecker (component); + const WeakReference deletionChecker (component); const Rectangle newBounds (getBounds()); const bool wasMoved = (component->getPosition() != newBounds.getPosition()); @@ -77737,7 +77749,7 @@ void ComponentPeer::handleFileDragDrop (const StringArray& files, const Point target; + WeakReference target; FileDragAndDropTarget* dropTarget; Point position; StringArray files; @@ -242054,7 +242066,7 @@ public: if (fullScreen != shouldBeFullScreen) { fullScreen = shouldBeFullScreen; - const Component::SafePointer deletionChecker (component); + const WeakReference deletionChecker (component); if (! fullScreen) { @@ -257509,7 +257521,7 @@ public: if (windowH != 0) { - Component::SafePointer deletionChecker (component); + WeakReference deletionChecker (component); wx = x; wy = y; @@ -268204,7 +268216,7 @@ public: } private: - Component::SafePointer component; + WeakReference component; OpenGLPixelFormat pixelFormat; JuceGLView* view; CAEAGLLayer* glLayer; @@ -273822,7 +273834,7 @@ public: } private: - Component::SafePointer component; + WeakReference component; OpenGLPixelFormat pixelFormat; JuceGLView* view; CAEAGLLayer* glLayer; diff --git a/juce_amalgamated.h b/juce_amalgamated.h index a68fd567e7..b84ffc2d83 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 107 +#define JUCE_BUILDNUMBER 108 /** Current Juce version number. @@ -14090,6 +14090,177 @@ private: #endif #ifndef __JUCE_VARIANT_JUCEHEADER__ +#endif +#ifndef __JUCE_WEAKREFERENCE_JUCEHEADER__ + +/*** Start of inlined file: juce_WeakReference.h ***/ +#ifndef __JUCE_WEAKREFERENCE_JUCEHEADER__ +#define __JUCE_WEAKREFERENCE_JUCEHEADER__ + +/** + This class acts as a pointer which will automatically become null if the object + to which it points is deleted. + + To accomplish this, the source object needs to implement a couple of minor tricks. It + must provide a getWeakReference() method and use a WeakReference::Master object to store + a master pointer to itself. It must also clear the pointer when it's getting destroyed. + + E.g. + @code + class MyObject + { + public: + MyObject() + { + // If you're planning on using your WeakReferences in a multi-threaded situation, you may choose + // to call getWeakReference() here in the constructor, to avoid rare race conditions that could + // occur if multiple threads tried to be the first to call it. + } + + ~MyObject() + { + // this will zero all the references - you need to call this in your destructor. + masterReference.clear(); + } + + // Your object must provide a method that matches this signature, and which + // returns the result of the WeakReference::Master::operator() method. + const WeakReference::SharedRef& getWeakReference() + { + return masterReference (this); + } + + private: + WeakReference::Master masterReference; + }; + @endcode + + @see WeakReference::Master +*/ +template +class WeakReference +{ +public: + /** Creates a null SafePointer. */ + WeakReference() throw() {} + + /** Creates a WeakReference that points at the given object. */ + WeakReference (ObjectType* const object) : holder (object != 0 ? object->getWeakReference() : 0) {} + + /** Creates a copy of another WeakReference. */ + WeakReference (const WeakReference& other) throw() : holder (other.holder) {} + + /** Copies another pointer to this one. */ + WeakReference& operator= (const WeakReference& other) { holder = other.holder; return *this; } + + /** Copies another pointer to this one. */ + WeakReference& operator= (ObjectType* const newObject) { holder = newObject != 0 ? newObject->getWeakReference() : 0; return *this; } + + /** Returns the object that this pointer refers to, or null if the object no longer exists. */ + ObjectType* get() const throw() { return holder != 0 ? holder->get() : 0; } + + /** Returns the object that this pointer refers to, or null if the object no longer exists. */ + operator ObjectType*() const throw() { return get(); } + + /** Returns the object that this pointer refers to, or null if the object no longer exists. */ + ObjectType* operator->() throw() { return get(); } + + /** Returns the object that this pointer refers to, or null if the object no longer exists. */ + const ObjectType* operator->() const throw() { return get(); } + + /** This returns true if this reference has been pointing at an object, but that object has + since been deleted. + + If this reference was only ever pointing at a null pointer, this will return false. Using + operator=() to make this refer to a different object will reset this flag to match the status + of the reference from which you're copying. + */ + bool wasObjectDeleted() const throw() { return holder != 0 && holder->get() == 0; } + + bool operator== (ObjectType* const object) const throw() { return get() == object; } + bool operator!= (ObjectType* const object) const throw() { return get() != object; } + + /** This class is used internally by the WeakReference class - don't use it directly + in your code! + @see WeakReference + */ + class SharedPointer : public ReferenceCountedObject + { + public: + explicit SharedPointer (ObjectType* const owner_) throw() : owner (owner_) {} + + inline ObjectType* get() const throw() { return owner; } + void clearPointer() throw() { owner = 0; } + + private: + ObjectType* volatile owner; + + JUCE_DECLARE_NON_COPYABLE (SharedPointer); + }; + + typedef ReferenceCountedObjectPtr SharedRef; + + /** + This class is embedded inside an object to which you want to attach WeakReference pointers. + See the WeakReference class notes for an example of how to use this class. + @see WeakReference + */ + class Master + { + public: + Master() throw() {} + + ~Master() + { + // You must remember to call clear() in your source object's destructor! See the notes + // for the WeakReference class for an example of how to do this. + jassert (sharedPointer == 0 || sharedPointer->get() == 0); + } + + /** The first call to this method will create an internal object that is shared by all weak + references to the object. + You need to call this from your main object's getWeakReference() method - see the WeakReference + class notes for an example. + */ + const SharedRef& operator() (ObjectType* const object) + { + if (sharedPointer == 0) + { + sharedPointer = new SharedPointer (object); + } + else + { + // You're trying to create a weak reference to an object that has already been deleted!! + jassert (sharedPointer->get() != 0); + } + + return sharedPointer; + } + + /** The object that owns this master pointer should call this before it gets destroyed, + to zero all the references to this object that may be out there. See the WeakReference + class notes for an example of how to do this. + */ + void clear() + { + if (sharedPointer != 0) + sharedPointer->clearPointer(); + } + + private: + SharedRef sharedPointer; + + JUCE_DECLARE_NON_COPYABLE (Master); + }; + +private: + SharedRef holder; +}; + +#endif // __JUCE_WEAKREFERENCE_JUCEHEADER__ +/*** End of inlined file: juce_WeakReference.h ***/ + + #endif #ifndef __JUCE_ATOMIC_JUCEHEADER__ @@ -28191,62 +28362,47 @@ public: The ComponentType typedef must be Component, or some subclass of Component. - Note that this class isn't thread-safe, and assumes that all the code that uses - it is running on the message thread. + You may also want to use a WeakReference object for the same purpose. */ template - class SafePointer : private ComponentListener + class SafePointer { public: /** Creates a null SafePointer. */ - SafePointer() : comp (0) {} + SafePointer() throw() {} /** Creates a SafePointer that points at the given component. */ - SafePointer (ComponentType* const component) : comp (component) { attach(); } + SafePointer (ComponentType* const component) : weakRef (component) {} /** Creates a copy of another SafePointer. */ - SafePointer (const SafePointer& other) : comp (other.comp) { attach(); } - - /** Destructor. */ - ~SafePointer() { detach(); } + SafePointer (const SafePointer& other) throw() : weakRef (other.weakRef) {} /** Copies another pointer to this one. */ - SafePointer& operator= (const SafePointer& other) { return operator= (other.comp); } + SafePointer& operator= (const SafePointer& other) { weakRef = other.weakRef; return *this; } /** Copies another pointer to this one. */ - SafePointer& operator= (ComponentType* const newComponent) - { - detach(); - comp = newComponent; - attach(); - return *this; - } + SafePointer& operator= (ComponentType* const newComponent) { weakRef = newComponent; return *this; } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - operator ComponentType*() const throw() { return comp; } + ComponentType* getComponent() const throw() { return dynamic_cast (weakRef.get()); } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - ComponentType* getComponent() const throw() { return comp; } + operator ComponentType*() const throw() { return getComponent(); } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - ComponentType* operator->() throw() { jassert (comp != 0); return comp; } + ComponentType* operator->() throw() { return getComponent(); } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - const ComponentType* operator->() const throw() { jassert (comp != 0); return comp; } + const ComponentType* operator->() const throw() { return getComponent(); } /** If the component is valid, this deletes it and sets this pointer to null. */ - void deleteAndZero() { delete comp; jassert (comp == 0); } + void deleteAndZero() { delete getComponent(); jassert (getComponent() == 0); } - bool operator== (ComponentType* component) const throw() { return comp == component; } - bool operator!= (ComponentType* component) const throw() { return comp != component; } + bool operator== (ComponentType* component) const throw() { return weakRef == component; } + bool operator!= (ComponentType* component) const throw() { return weakRef != component; } private: - - ComponentType* comp; - - void attach() { if (comp != 0) comp->addComponentListener (this); } - void detach() { if (comp != 0) comp->removeComponentListener (this); } - void componentBeingDeleted (Component&) { comp = 0; } + WeakReference weakRef; }; /** A class to keep an eye on one or two components and check for them being deleted. @@ -28258,21 +28414,17 @@ public: class BailOutChecker { public: - /** Creates a checker that watches either one or two components. - component1 must be a valid component; component2 can be null if you only need - to check on one component. - */ - BailOutChecker (Component* component1, - Component* component2 = 0); + /** Creates a checker that watches one component. */ + BailOutChecker (Component* component1); - /** Returns true if either of the two components have been deleted since this - object was created. */ + /** Creates a checker that watches two components. */ + BailOutChecker (Component* component1, Component* component2); + + /** Returns true if either of the two components have been deleted since this object was created. */ bool shouldBailOut() const throw(); private: - typedef SafePointer SafeComponentPtr; - SafeComponentPtr safePointer1, safePointer2; - Component* const component2; + const WeakReference safePointer1, safePointer2; JUCE_DECLARE_NON_COPYABLE (BailOutChecker); }; @@ -28316,6 +28468,10 @@ private: ListenerList componentListeners; NamedValueSet properties; + friend class WeakReference; + WeakReference::Master weakReferenceMaster; + const WeakReference::SharedRef& getWeakReference(); + struct ComponentFlags { bool hasHeavyweightPeerFlag : 1; @@ -28365,6 +28521,7 @@ private: void internalModifierKeysChanged(); void internalChildrenChanged(); void internalHierarchyChanged(); + Component* removeChildComponent (const int index, bool sendParentEvents, bool sendChildEvents); void paintComponentAndChildren (Graphics& g); void paintComponent (Graphics& g); void paintWithinParentContext (Graphics& g); @@ -28373,7 +28530,7 @@ private: void sendFakeMouseMove() const; void takeKeyboardFocus (const FocusChangeType cause); void grabFocusInternal (const FocusChangeType cause, bool canTryParent = true); - static void giveAwayFocus(); + static void giveAwayFocus (bool sendFocusLossEvent); void sendEnablementChangeMessage(); void sendVisibilityChangeMessage(); @@ -36587,7 +36744,7 @@ protected: private: Array shortcuts; - Component::SafePointer keySource; + WeakReference keySource; String text; ListenerList buttonListeners; @@ -37147,7 +37304,7 @@ public: private: - Component::SafePointer contentComp; + WeakReference contentComp; Rectangle lastVisibleArea; int scrollBarThickness; int singleStepX, singleStepY; @@ -38503,9 +38660,9 @@ private: String lastTextValue; Font font; Justification justification; - ScopedPointer editor; - ListenerList listeners; - Component::SafePointer ownerComponent; + ScopedPointer editor; + ListenerList listeners; + WeakReference ownerComponent; int horizontalBorderSize, verticalBorderSize; float minimumHorizontalScale; bool editSingleClick : 1; @@ -51288,7 +51445,7 @@ protected: bool hitTest (int x, int y); private: - Component::SafePointer component; + WeakReference component; ComponentBoundsConstrainer* constrainer; BorderSize borderSize; Rectangle originalBounds; @@ -51359,7 +51516,7 @@ protected: private: - Component::SafePointer component; + WeakReference component; ComponentBoundsConstrainer* constrainer; Rectangle originalBounds; @@ -53042,7 +53199,7 @@ public: private: - Component::SafePointer component; + WeakReference component; ComponentPeer* lastPeer; Array registeredParentComps; bool reentrant; @@ -53608,8 +53765,8 @@ protected: private: - OwnedArray > contentComponents; - Component::SafePointer panelComponent; + OwnedArray > contentComponents; + WeakReference panelComponent; int tabDepth; int outlineThickness, edgeIndent; static const Identifier deleteComponentId; @@ -59586,7 +59743,7 @@ protected: private: - Component::SafePointer lastFocusedComponent, dragAndDropTargetComponent; + WeakReference lastFocusedComponent, dragAndDropTargetComponent; Component* lastDragAndDropCompUnderMouse; bool fakeMouseMessageSent : 1, isWindowMinimised : 1; diff --git a/src/containers/juce_WeakReference.h b/src/containers/juce_WeakReference.h new file mode 100644 index 0000000000..26b4ae26c8 --- /dev/null +++ b/src/containers/juce_WeakReference.h @@ -0,0 +1,196 @@ +/* + ============================================================================== + + 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_WEAKREFERENCE_JUCEHEADER__ +#define __JUCE_WEAKREFERENCE_JUCEHEADER__ + +#include "juce_ReferenceCountedObject.h" + + +//============================================================================== +/** + This class acts as a pointer which will automatically become null if the object + to which it points is deleted. + + To accomplish this, the source object needs to implement a couple of minor tricks. It + must provide a getWeakReference() method and use a WeakReference::Master object to store + a master pointer to itself. It must also clear the pointer when it's getting destroyed. + + E.g. + @code + class MyObject + { + public: + MyObject() + { + // If you're planning on using your WeakReferences in a multi-threaded situation, you may choose + // to call getWeakReference() here in the constructor, to avoid rare race conditions that could + // occur if multiple threads tried to be the first to call it. + } + + ~MyObject() + { + // this will zero all the references - you need to call this in your destructor. + masterReference.clear(); + } + + // Your object must provide a method that matches this signature, and which + // returns the result of the WeakReference::Master::operator() method. + const WeakReference::SharedRef& getWeakReference() + { + return masterReference (this); + } + + private: + WeakReference::Master masterReference; + }; + @endcode + + @see WeakReference::Master +*/ +template +class WeakReference +{ +public: + /** Creates a null SafePointer. */ + WeakReference() throw() {} + + /** Creates a WeakReference that points at the given object. */ + WeakReference (ObjectType* const object) : holder (object != 0 ? object->getWeakReference() : 0) {} + + /** Creates a copy of another WeakReference. */ + WeakReference (const WeakReference& other) throw() : holder (other.holder) {} + + /** Copies another pointer to this one. */ + WeakReference& operator= (const WeakReference& other) { holder = other.holder; return *this; } + + /** Copies another pointer to this one. */ + WeakReference& operator= (ObjectType* const newObject) { holder = newObject != 0 ? newObject->getWeakReference() : 0; return *this; } + + /** Returns the object that this pointer refers to, or null if the object no longer exists. */ + ObjectType* get() const throw() { return holder != 0 ? holder->get() : 0; } + + /** Returns the object that this pointer refers to, or null if the object no longer exists. */ + operator ObjectType*() const throw() { return get(); } + + /** Returns the object that this pointer refers to, or null if the object no longer exists. */ + ObjectType* operator->() throw() { return get(); } + + /** Returns the object that this pointer refers to, or null if the object no longer exists. */ + const ObjectType* operator->() const throw() { return get(); } + + /** This returns true if this reference has been pointing at an object, but that object has + since been deleted. + + If this reference was only ever pointing at a null pointer, this will return false. Using + operator=() to make this refer to a different object will reset this flag to match the status + of the reference from which you're copying. + */ + bool wasObjectDeleted() const throw() { return holder != 0 && holder->get() == 0; } + + bool operator== (ObjectType* const object) const throw() { return get() == object; } + bool operator!= (ObjectType* const object) const throw() { return get() != object; } + + //============================================================================== + /** This class is used internally by the WeakReference class - don't use it directly + in your code! + @see WeakReference + */ + class SharedPointer : public ReferenceCountedObject + { + public: + explicit SharedPointer (ObjectType* const owner_) throw() : owner (owner_) {} + + inline ObjectType* get() const throw() { return owner; } + void clearPointer() throw() { owner = 0; } + + private: + ObjectType* volatile owner; + + JUCE_DECLARE_NON_COPYABLE (SharedPointer); + }; + + typedef ReferenceCountedObjectPtr SharedRef; + + //============================================================================== + /** + This class is embedded inside an object to which you want to attach WeakReference pointers. + See the WeakReference class notes for an example of how to use this class. + @see WeakReference + */ + class Master + { + public: + Master() throw() {} + + ~Master() + { + // You must remember to call clear() in your source object's destructor! See the notes + // for the WeakReference class for an example of how to do this. + jassert (sharedPointer == 0 || sharedPointer->get() == 0); + } + + /** The first call to this method will create an internal object that is shared by all weak + references to the object. + You need to call this from your main object's getWeakReference() method - see the WeakReference + class notes for an example. + */ + const SharedRef& operator() (ObjectType* const object) + { + if (sharedPointer == 0) + { + sharedPointer = new SharedPointer (object); + } + else + { + // You're trying to create a weak reference to an object that has already been deleted!! + jassert (sharedPointer->get() != 0); + } + + return sharedPointer; + } + + /** The object that owns this master pointer should call this before it gets destroyed, + to zero all the references to this object that may be out there. See the WeakReference + class notes for an example of how to do this. + */ + void clear() + { + if (sharedPointer != 0) + sharedPointer->clearPointer(); + } + + private: + SharedRef sharedPointer; + + JUCE_DECLARE_NON_COPYABLE (Master); + }; + +private: + SharedRef holder; +}; + + +#endif // __JUCE_WEAKREFERENCE_JUCEHEADER__ diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 7ef24f3518..e42fdd3c76 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 107 +#define JUCE_BUILDNUMBER 108 /** Current Juce version number. diff --git a/src/gui/components/buttons/juce_Button.cpp b/src/gui/components/buttons/juce_Button.cpp index 3bcce94420..9ecb214e33 100644 --- a/src/gui/components/buttons/juce_Button.cpp +++ b/src/gui/components/buttons/juce_Button.cpp @@ -149,7 +149,7 @@ void Button::setToggleState (const bool shouldBeOn, if (sendChangeNotification) { - Component::SafePointer deletionWatcher (this); + WeakReference deletionWatcher (this); sendClickMessage (ModifierKeys()); if (deletionWatcher == 0) @@ -200,7 +200,7 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) if (p != 0 && radioGroupId != 0) { - Component::SafePointer deletionWatcher (this); + WeakReference deletionWatcher (this); for (int i = p->getNumChildComponents(); --i >= 0;) { @@ -460,7 +460,7 @@ void Button::parentHierarchyChanged() { Component* const newKeySource = (shortcuts.size() == 0) ? 0 : getTopLevelComponent(); - if (newKeySource != keySource.getComponent()) + if (newKeySource != keySource.get()) { if (keySource != 0) keySource->removeKeyListener (this); diff --git a/src/gui/components/buttons/juce_Button.h b/src/gui/components/buttons/juce_Button.h index d7669fae05..1a339633e9 100644 --- a/src/gui/components/buttons/juce_Button.h +++ b/src/gui/components/buttons/juce_Button.h @@ -465,7 +465,7 @@ protected: private: //============================================================================== Array shortcuts; - Component::SafePointer keySource; + WeakReference keySource; String text; ListenerList buttonListeners; diff --git a/src/gui/components/controls/juce_Label.cpp b/src/gui/components/controls/juce_Label.cpp index 05432594c0..be94066e9f 100644 --- a/src/gui/components/controls/juce_Label.cpp +++ b/src/gui/components/controls/juce_Label.cpp @@ -264,7 +264,7 @@ void Label::hideEditor (const bool discardCurrentEditorContents) { if (editor != 0) { - Component::SafePointer deletionChecker (this); + WeakReference deletionChecker (this); editorAboutToBeHidden (editor); @@ -448,7 +448,7 @@ void Label::textEditorReturnKeyPressed (TextEditor& ed) if (changed) { - Component::SafePointer deletionChecker (this); + WeakReference deletionChecker (this); textWasEdited(); if (deletionChecker != 0) diff --git a/src/gui/components/controls/juce_Label.h b/src/gui/components/controls/juce_Label.h index 392e6a4c9a..8af28c48c1 100644 --- a/src/gui/components/controls/juce_Label.h +++ b/src/gui/components/controls/juce_Label.h @@ -317,9 +317,9 @@ private: String lastTextValue; Font font; Justification justification; - ScopedPointer editor; - ListenerList listeners; - Component::SafePointer ownerComponent; + ScopedPointer editor; + ListenerList listeners; + WeakReference ownerComponent; int horizontalBorderSize, verticalBorderSize; float minimumHorizontalScale; bool editSingleClick : 1; diff --git a/src/gui/components/controls/juce_Toolbar.cpp b/src/gui/components/controls/juce_Toolbar.cpp index 3a73854263..7f60676974 100644 --- a/src/gui/components/controls/juce_Toolbar.cpp +++ b/src/gui/components/controls/juce_Toolbar.cpp @@ -843,7 +843,7 @@ void Toolbar::showCustomisationDialog (ToolbarItemFactory& factory, const int op setEditingActive (true); #if JUCE_DEBUG - Component::SafePointer checker (this); + WeakReference checker (this); #endif ToolbarCustomisationDialog dw (factory, this, optionFlags); diff --git a/src/gui/components/controls/juce_TreeView.cpp b/src/gui/components/controls/juce_TreeView.cpp index 80cdfc4970..545bdccbd1 100644 --- a/src/gui/components/controls/juce_TreeView.cpp +++ b/src/gui/components/controls/juce_TreeView.cpp @@ -341,10 +341,10 @@ private: ~RowItem() { - component.deleteAndZero(); + delete component.get(); } - Component::SafePointer component; + WeakReference component; TreeViewItem* item; int uid; bool shouldKeep; diff --git a/src/gui/components/filebrowser/juce_FileChooser.cpp b/src/gui/components/filebrowser/juce_FileChooser.cpp index 3ebb54cc07..8aad9d1f1e 100644 --- a/src/gui/components/filebrowser/juce_FileChooser.cpp +++ b/src/gui/components/filebrowser/juce_FileChooser.cpp @@ -102,7 +102,7 @@ bool FileChooser::showDialog (const bool selectsDirectories, const bool selectMultipleFiles, FilePreviewComponent* const previewComponent) { - Component::SafePointer previouslyFocused (Component::getCurrentlyFocusedComponent()); + WeakReference previouslyFocused (Component::getCurrentlyFocusedComponent()); results.clear(); diff --git a/src/gui/components/juce_Component.cpp b/src/gui/components/juce_Component.cpp index 389d2a7e18..9094a13c18 100644 --- a/src/gui/components/juce_Component.cpp +++ b/src/gui/components/juce_Component.cpp @@ -411,20 +411,26 @@ Component::~Component() componentListeners.call (&ComponentListener::componentBeingDeleted, *this); + weakReferenceMaster.clear(); + + while (childComponentList_.size() > 0) + removeChildComponent (childComponentList_.size() - 1, false, true); + if (parentComponent_ != 0) - { - parentComponent_->removeChildComponent (this); - } + parentComponent_->removeChildComponent (parentComponent_->childComponentList_.indexOf (this), true, false); else if (currentlyFocusedComponent == this || isParentOf (currentlyFocusedComponent)) - { - giveAwayFocus(); - } + giveAwayFocus (currentlyFocusedComponent != this); if (flags.hasHeavyweightPeerFlag) removeFromDesktop(); - for (int i = childComponentList_.size(); --i >= 0;) - childComponentList_.getUnchecked(i)->parentComponent_ = 0; + // Something has added some children to this component during its destructor! Not a smart idea! + jassert (childComponentList_.size() == 0); +} + +const WeakReference::SharedRef& Component::getWeakReference() +{ + return weakReferenceMaster (this); } //============================================================================== @@ -460,7 +466,7 @@ void Component::setVisible (bool shouldBeVisible) // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. CHECK_MESSAGE_MANAGER_IS_LOCKED - SafePointer safePointer (this); + WeakReference safePointer (this); flags.visibleFlag = shouldBeVisible; @@ -475,7 +481,7 @@ void Component::setVisible (bool shouldBeVisible) if (parentComponent_ != 0) parentComponent_->grabKeyboardFocus(); else - giveAwayFocus(); + giveAwayFocus (true); } } @@ -566,7 +572,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) if (styleWanted != currentStyleFlags || ! flags.hasHeavyweightPeerFlag) { - SafePointer safePointer (this); + WeakReference safePointer (this); #if JUCE_LINUX // it's wise to give the component a non-zero size before @@ -1333,10 +1339,15 @@ void Component::addAndMakeVisible (Component* const child, int zOrder) void Component::removeChildComponent (Component* const child) { - removeChildComponent (childComponentList_.indexOf (child)); + removeChildComponent (childComponentList_.indexOf (child), true, true); } Component* Component::removeChildComponent (const int index) +{ + return removeChildComponent (index, true, true); +} + +Component* Component::removeChildComponent (const int index, bool sendParentEvents, const bool sendChildEvents) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. @@ -1346,9 +1357,9 @@ Component* Component::removeChildComponent (const int index) if (child != 0) { - const bool childShowing = child->isShowing(); + sendParentEvents = sendParentEvents && child->isShowing(); - if (childShowing) + if (sendParentEvents) { sendFakeMouseMove(); child->repaintParent(); @@ -1360,19 +1371,22 @@ Component* Component::removeChildComponent (const int index) // (NB: there are obscure situations where a childShowing = false, but it still has the focus) if (currentlyFocusedComponent == child || child->isParentOf (currentlyFocusedComponent)) { - SafePointer thisPointer (this); + const WeakReference thisPointer (this); - giveAwayFocus(); + giveAwayFocus (sendChildEvents || currentlyFocusedComponent != child); if (thisPointer == 0) return child; - if (childShowing) + if (sendParentEvents) grabKeyboardFocus(); } - child->internalHierarchyChanged(); - internalChildrenChanged(); + if (sendChildEvents) + child->internalHierarchyChanged(); + + if (sendParentEvents) + internalChildrenChanged(); } return child; @@ -1536,10 +1550,6 @@ void Component::exitModalState (const int returnValue) } else { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED - class ExitModalStateMessage : public CallbackMessage { public: @@ -1548,12 +1558,12 @@ void Component::exitModalState (const int returnValue) void messageCallback() { - if (target.getComponent() != 0) // (getComponent() required for VS2003 bug) + if (target.get() != 0) // (get() required for VS2003 bug) target->exitModalState (result); } private: - Component::SafePointer target; + WeakReference target; int result; }; @@ -1943,7 +1953,7 @@ void Component::sendLookAndFeelChange() { repaint(); - SafePointer safePointer (this); + WeakReference safePointer (this); lookAndFeelChanged(); @@ -2164,10 +2174,6 @@ void Component::paintOverChildren (Graphics&) //============================================================================== void Component::postCommandMessage (const int commandId) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED - class CustomCommandMessage : public CallbackMessage { public: @@ -2176,12 +2182,12 @@ void Component::postCommandMessage (const int commandId) void messageCallback() { - if (target != 0) + if (target.get() != 0) // (get() required for VS2003 bug) target->handleCommandMessage (commandId); } private: - Component::SafePointer target; + WeakReference target; int commandId; }; @@ -2549,7 +2555,7 @@ void Component::focusGained (FocusChangeType) void Component::internalFocusGain (const FocusChangeType cause) { - SafePointer safePointer (this); + WeakReference safePointer (this); focusGained (cause); @@ -2564,7 +2570,7 @@ void Component::focusLost (FocusChangeType) void Component::internalFocusLoss (const FocusChangeType cause) { - SafePointer safePointer (this); + WeakReference safePointer (this); focusLost (focusChangedDirectly); @@ -2585,7 +2591,7 @@ void Component::internalChildFocusChange (FocusChangeType cause) { flags.childCompFocusedFlag = childIsNowFocused; - SafePointer safePointer (this); + WeakReference safePointer (this); focusOfChildComponentChanged (cause); if (safePointer == 0) @@ -2618,7 +2624,7 @@ void Component::setEnabled (const bool shouldBeEnabled) void Component::sendEnablementChangeMessage() { - SafePointer safePointer (this); + WeakReference safePointer (this); enablementChanged(); @@ -2706,13 +2712,13 @@ void Component::takeKeyboardFocus (const FocusChangeType cause) if (peer != 0) { - SafePointer safePointer (this); + WeakReference safePointer (this); peer->grabFocus(); if (peer->isFocused() && currentlyFocusedComponent != this) { - SafePointer componentLosingFocus (currentlyFocusedComponent); + WeakReference componentLosingFocus (currentlyFocusedComponent); currentlyFocusedComponent = this; @@ -2822,7 +2828,7 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) { if (nextComp->isCurrentlyBlockedByAnotherModalComponent()) { - SafePointer nextCompPointer (nextComp); + WeakReference nextCompPointer (nextComp); internalModalInputAttempt(); if (nextCompPointer == 0 || nextComp->isCurrentlyBlockedByAnotherModalComponent()) @@ -2849,12 +2855,12 @@ Component* JUCE_CALLTYPE Component::getCurrentlyFocusedComponent() throw() return currentlyFocusedComponent; } -void Component::giveAwayFocus() +void Component::giveAwayFocus (const bool sendFocusLossEvent) { Component* const componentLosingFocus = currentlyFocusedComponent; currentlyFocusedComponent = 0; - if (componentLosingFocus != 0) + if (sendFocusLossEvent && componentLosingFocus != 0) componentLosingFocus->internalFocusLoss (focusChangedDirectly); Desktop::getInstance().triggerFocusCallback(); @@ -2951,15 +2957,21 @@ ComponentPeer* Component::getPeer() const } //============================================================================== -Component::BailOutChecker::BailOutChecker (Component* const component1, Component* const component2_) - : safePointer1 (component1), safePointer2 (component2_), component2 (component2_) +Component::BailOutChecker::BailOutChecker (Component* const component) + : safePointer1 (component) +{ + jassert (component != 0); +} + +Component::BailOutChecker::BailOutChecker (Component* const component1, Component* const component2) + : safePointer1 (component1), safePointer2 (component2) { jassert (component1 != 0); } bool Component::BailOutChecker::shouldBailOut() const throw() { - return safePointer1 == 0 || safePointer2.getComponent() != component2; + return safePointer1 == 0 || safePointer2.wasObjectDeleted(); } diff --git a/src/gui/components/juce_Component.h b/src/gui/components/juce_Component.h index 62c4f1eb60..f6b9c3fdfd 100644 --- a/src/gui/components/juce_Component.h +++ b/src/gui/components/juce_Component.h @@ -40,6 +40,7 @@ #include "../../text/juce_StringArray.h" #include "../../containers/juce_Array.h" #include "../../containers/juce_NamedValueSet.h" +#include "../../containers/juce_WeakReference.h" #include "juce_ModalComponentManager.h" class LookAndFeel; @@ -2022,62 +2023,47 @@ public: The ComponentType typedef must be Component, or some subclass of Component. - Note that this class isn't thread-safe, and assumes that all the code that uses - it is running on the message thread. + You may also want to use a WeakReference object for the same purpose. */ template - class SafePointer : private ComponentListener + class SafePointer { public: /** Creates a null SafePointer. */ - SafePointer() : comp (0) {} + SafePointer() throw() {} /** Creates a SafePointer that points at the given component. */ - SafePointer (ComponentType* const component) : comp (component) { attach(); } + SafePointer (ComponentType* const component) : weakRef (component) {} /** Creates a copy of another SafePointer. */ - SafePointer (const SafePointer& other) : comp (other.comp) { attach(); } - - /** Destructor. */ - ~SafePointer() { detach(); } + SafePointer (const SafePointer& other) throw() : weakRef (other.weakRef) {} /** Copies another pointer to this one. */ - SafePointer& operator= (const SafePointer& other) { return operator= (other.comp); } + SafePointer& operator= (const SafePointer& other) { weakRef = other.weakRef; return *this; } /** Copies another pointer to this one. */ - SafePointer& operator= (ComponentType* const newComponent) - { - detach(); - comp = newComponent; - attach(); - return *this; - } + SafePointer& operator= (ComponentType* const newComponent) { weakRef = newComponent; return *this; } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - operator ComponentType*() const throw() { return comp; } + ComponentType* getComponent() const throw() { return dynamic_cast (weakRef.get()); } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - ComponentType* getComponent() const throw() { return comp; } + operator ComponentType*() const throw() { return getComponent(); } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - ComponentType* operator->() throw() { jassert (comp != 0); return comp; } + ComponentType* operator->() throw() { return getComponent(); } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - const ComponentType* operator->() const throw() { jassert (comp != 0); return comp; } + const ComponentType* operator->() const throw() { return getComponent(); } /** If the component is valid, this deletes it and sets this pointer to null. */ - void deleteAndZero() { delete comp; jassert (comp == 0); } + void deleteAndZero() { delete getComponent(); jassert (getComponent() == 0); } - bool operator== (ComponentType* component) const throw() { return comp == component; } - bool operator!= (ComponentType* component) const throw() { return comp != component; } + bool operator== (ComponentType* component) const throw() { return weakRef == component; } + bool operator!= (ComponentType* component) const throw() { return weakRef != component; } private: - //============================================================================== - ComponentType* comp; - - void attach() { if (comp != 0) comp->addComponentListener (this); } - void detach() { if (comp != 0) comp->removeComponentListener (this); } - void componentBeingDeleted (Component&) { comp = 0; } + WeakReference weakRef; }; //============================================================================== @@ -2090,21 +2076,17 @@ public: class BailOutChecker { public: - /** Creates a checker that watches either one or two components. - component1 must be a valid component; component2 can be null if you only need - to check on one component. - */ - BailOutChecker (Component* component1, - Component* component2 = 0); + /** Creates a checker that watches one component. */ + BailOutChecker (Component* component1); - /** Returns true if either of the two components have been deleted since this - object was created. */ + /** Creates a checker that watches two components. */ + BailOutChecker (Component* component1, Component* component2); + + /** Returns true if either of the two components have been deleted since this object was created. */ bool shouldBailOut() const throw(); private: - typedef SafePointer SafeComponentPtr; - SafeComponentPtr safePointer1, safePointer2; - Component* const component2; + const WeakReference safePointer1, safePointer2; JUCE_DECLARE_NON_COPYABLE (BailOutChecker); }; @@ -2150,6 +2132,10 @@ private: ListenerList componentListeners; NamedValueSet properties; + friend class WeakReference; + WeakReference::Master weakReferenceMaster; + const WeakReference::SharedRef& getWeakReference(); + struct ComponentFlags { bool hasHeavyweightPeerFlag : 1; @@ -2200,6 +2186,7 @@ private: void internalModifierKeysChanged(); void internalChildrenChanged(); void internalHierarchyChanged(); + Component* removeChildComponent (const int index, bool sendParentEvents, bool sendChildEvents); void paintComponentAndChildren (Graphics& g); void paintComponent (Graphics& g); void paintWithinParentContext (Graphics& g); @@ -2208,7 +2195,7 @@ private: void sendFakeMouseMove() const; void takeKeyboardFocus (const FocusChangeType cause); void grabFocusInternal (const FocusChangeType cause, bool canTryParent = true); - static void giveAwayFocus(); + static void giveAwayFocus (bool sendFocusLossEvent); void sendEnablementChangeMessage(); void sendVisibilityChangeMessage(); diff --git a/src/gui/components/juce_Desktop.cpp b/src/gui/components/juce_Desktop.cpp index 5e8100dccc..b96e6c55ab 100644 --- a/src/gui/components/juce_Desktop.cpp +++ b/src/gui/components/juce_Desktop.cpp @@ -320,7 +320,7 @@ void Desktop::handleAsyncUpdate() { // The component may be deleted during this operation, but we'll use a SafePointer rather than a // BailOutChecker so that any remaining listeners will still get a callback (with a null pointer). - Component::SafePointer currentFocus (Component::getCurrentlyFocusedComponent()); + WeakReference currentFocus (Component::getCurrentlyFocusedComponent()); focusListeners.call (&FocusChangeListener::globalFocusChanged, currentFocus); } diff --git a/src/gui/components/juce_ModalComponentManager.cpp b/src/gui/components/juce_ModalComponentManager.cpp index 5f4e654bf2..4aa574f73a 100644 --- a/src/gui/components/juce_ModalComponentManager.cpp +++ b/src/gui/components/juce_ModalComponentManager.cpp @@ -268,7 +268,7 @@ int ModalComponentManager::runEventLoopForCurrentComponent() if (currentlyModal == 0) return 0; - Component::SafePointer prevFocused (Component::getCurrentlyFocusedComponent()); + WeakReference prevFocused (Component::getCurrentlyFocusedComponent()); int returnValue = 0; bool finished = false; diff --git a/src/gui/components/layout/juce_ComponentAnimator.cpp b/src/gui/components/layout/juce_ComponentAnimator.cpp index 95c95923bb..e31ec9cdf6 100644 --- a/src/gui/components/layout/juce_ComponentAnimator.cpp +++ b/src/gui/components/layout/juce_ComponentAnimator.cpp @@ -178,7 +178,7 @@ public: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProxyComponent); }; - Component::SafePointer component; + WeakReference component; ScopedPointer proxy; Rectangle destination; @@ -212,7 +212,7 @@ ComponentAnimator::~ComponentAnimator() ComponentAnimator::AnimationTask* ComponentAnimator::findTaskFor (Component* const component) const { for (int i = tasks.size(); --i >= 0;) - if (component == tasks.getUnchecked(i)->component.getComponent()) + if (component == tasks.getUnchecked(i)->component.get()) return tasks.getUnchecked(i); return 0; diff --git a/src/gui/components/layout/juce_ComponentMovementWatcher.h b/src/gui/components/layout/juce_ComponentMovementWatcher.h index e7bc71094e..f2035d592f 100644 --- a/src/gui/components/layout/juce_ComponentMovementWatcher.h +++ b/src/gui/components/layout/juce_ComponentMovementWatcher.h @@ -72,7 +72,7 @@ public: private: //============================================================================== - Component::SafePointer component; + WeakReference component; ComponentPeer* lastPeer; Array registeredParentComps; bool reentrant; diff --git a/src/gui/components/layout/juce_ResizableBorderComponent.h b/src/gui/components/layout/juce_ResizableBorderComponent.h index 307340dffe..2f8b5dfab5 100644 --- a/src/gui/components/layout/juce_ResizableBorderComponent.h +++ b/src/gui/components/layout/juce_ResizableBorderComponent.h @@ -187,7 +187,7 @@ protected: bool hitTest (int x, int y); private: - Component::SafePointer component; + WeakReference component; ComponentBoundsConstrainer* constrainer; BorderSize borderSize; Rectangle originalBounds; diff --git a/src/gui/components/layout/juce_ResizableCornerComponent.h b/src/gui/components/layout/juce_ResizableCornerComponent.h index 8101dace90..462d566387 100644 --- a/src/gui/components/layout/juce_ResizableCornerComponent.h +++ b/src/gui/components/layout/juce_ResizableCornerComponent.h @@ -83,7 +83,7 @@ protected: private: //============================================================================== - Component::SafePointer component; + WeakReference component; ComponentBoundsConstrainer* constrainer; Rectangle originalBounds; diff --git a/src/gui/components/layout/juce_TabbedComponent.cpp b/src/gui/components/layout/juce_TabbedComponent.cpp index dff889c76b..00f9e3b6c0 100644 --- a/src/gui/components/layout/juce_TabbedComponent.cpp +++ b/src/gui/components/layout/juce_TabbedComponent.cpp @@ -129,10 +129,10 @@ void TabbedComponent::clearTabs() for (int i = contentComponents.size(); --i >= 0;) { - Component::SafePointer& c = *contentComponents.getUnchecked (i); + WeakReference& c = *contentComponents.getUnchecked (i); if (c != 0 && (bool) c->getProperties() [deleteComponentId]) - c.deleteAndZero(); + delete c.get(); } contentComponents.clear(); @@ -144,7 +144,7 @@ void TabbedComponent::addTab (const String& tabName, const bool deleteComponentWhenNotNeeded, const int insertIndex) { - contentComponents.insert (insertIndex, new Component::SafePointer (contentComponent)); + contentComponents.insert (insertIndex, new WeakReference (contentComponent)); if (contentComponent != 0) contentComponent->getProperties().set (deleteComponentId, deleteComponentWhenNotNeeded); @@ -159,12 +159,12 @@ void TabbedComponent::setTabName (const int tabIndex, const String& newName) void TabbedComponent::removeTab (const int tabIndex) { - Component::SafePointer* c = contentComponents [tabIndex]; + WeakReference* c = contentComponents [tabIndex]; if (c != 0) { if ((bool) ((*c)->getProperties() [deleteComponentId])) - c->deleteAndZero(); + delete c->get(); contentComponents.remove (tabIndex); tabs->removeTab (tabIndex); @@ -183,7 +183,7 @@ const StringArray TabbedComponent::getTabNames() const Component* TabbedComponent::getTabContentComponent (const int tabIndex) const throw() { - Component::SafePointer* const c = contentComponents [tabIndex]; + WeakReference* const c = contentComponents [tabIndex]; return c != 0 ? *c : 0; } diff --git a/src/gui/components/layout/juce_TabbedComponent.h b/src/gui/components/layout/juce_TabbedComponent.h index 32e8118023..2b258cdb08 100644 --- a/src/gui/components/layout/juce_TabbedComponent.h +++ b/src/gui/components/layout/juce_TabbedComponent.h @@ -225,8 +225,8 @@ protected: private: //============================================================================== - OwnedArray > contentComponents; - Component::SafePointer panelComponent; + OwnedArray > contentComponents; + WeakReference panelComponent; int tabDepth; int outlineThickness, edgeIndent; static const Identifier deleteComponentId; diff --git a/src/gui/components/layout/juce_Viewport.cpp b/src/gui/components/layout/juce_Viewport.cpp index 35340fa27c..dc599e42af 100644 --- a/src/gui/components/layout/juce_Viewport.cpp +++ b/src/gui/components/layout/juce_Viewport.cpp @@ -77,7 +77,7 @@ void Viewport::deleteContentComp() void Viewport::setViewedComponent (Component* const newViewedComponent) { - if (contentComp.getComponent() != newViewedComponent) + if (contentComp.get() != newViewedComponent) { deleteContentComp(); contentComp = newViewedComponent; diff --git a/src/gui/components/layout/juce_Viewport.h b/src/gui/components/layout/juce_Viewport.h index bdc09c9854..242f8c8bae 100644 --- a/src/gui/components/layout/juce_Viewport.h +++ b/src/gui/components/layout/juce_Viewport.h @@ -253,7 +253,7 @@ public: private: //============================================================================== - Component::SafePointer contentComp; + WeakReference contentComp; Rectangle lastVisibleArea; int scrollBarThickness; int singleStepX, singleStepY; diff --git a/src/gui/components/menus/juce_PopupMenu.cpp b/src/gui/components/menus/juce_PopupMenu.cpp index 2a3bc1291a..2ba4c9a039 100644 --- a/src/gui/components/menus/juce_PopupMenu.cpp +++ b/src/gui/components/menus/juce_PopupMenu.cpp @@ -492,7 +492,7 @@ public: void inputAttemptWhenModal() { - Component::SafePointer deletionChecker (this); + WeakReference deletionChecker (this); timerCallback(); @@ -684,7 +684,7 @@ private: Component::SafePointer currentChild; ScopedPointer activeSubMenu; ApplicationCommandManager** managerOfChosenCommand; - Component::SafePointer componentAttachedTo; + WeakReference componentAttachedTo; Component* componentAttachedToOriginal; Rectangle windowPos; Point lastMouse; @@ -1448,8 +1448,8 @@ int PopupMenu::showMenu (const Rectangle& target, { ScopedPointer userCallbackDeleter (userCallback); - Component::SafePointer prevFocused (Component::getCurrentlyFocusedComponent()); - Component::SafePointer prevTopLevel ((prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0); + WeakReference prevFocused (Component::getCurrentlyFocusedComponent()); + WeakReference prevTopLevel ((prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0); Window::wasHiddenBecauseOfAppChange() = false; PopupMenuCompletionCallback* callback = new PopupMenuCompletionCallback(); diff --git a/src/gui/components/mouse/juce_DragAndDropContainer.cpp b/src/gui/components/mouse/juce_DragAndDropContainer.cpp index 865e626057..68e5906b59 100644 --- a/src/gui/components/mouse/juce_DragAndDropContainer.cpp +++ b/src/gui/components/mouse/juce_DragAndDropContainer.cpp @@ -240,7 +240,7 @@ public: if (owner->shouldDropFilesWhenDraggedExternally (dragDescLocal, source, files, canMoveFiles) && files.size() > 0) { - Component::SafePointer cdw (this); + WeakReference cdw (this); setVisible (false); if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) @@ -279,11 +279,11 @@ public: private: Image image; - Component::SafePointer source; - Component::SafePointer mouseDragSource; + WeakReference source; + WeakReference mouseDragSource; DragAndDropContainer* const owner; - Component::SafePointer currentlyOverComp; + WeakReference currentlyOverComp; DragAndDropTarget* getCurrentlyOver() { return dynamic_cast (static_cast (currentlyOverComp)); diff --git a/src/gui/components/mouse/juce_MouseInputSource.cpp b/src/gui/components/mouse/juce_MouseInputSource.cpp index 97dadd73d8..cc40a08ad4 100644 --- a/src/gui/components/mouse/juce_MouseInputSource.cpp +++ b/src/gui/components/mouse/juce_MouseInputSource.cpp @@ -192,7 +192,7 @@ public: if (newComponent != current) { - Component::SafePointer safeNewComp (newComponent); + WeakReference safeNewComp (newComponent); const ModifierKeys originalButtonState (buttonState); if (current != 0) @@ -437,7 +437,7 @@ public: private: MouseInputSource& source; - Component::SafePointer componentUnderMouse; + WeakReference componentUnderMouse; ComponentPeer* lastPeer; Point unboundedMouseOffset; diff --git a/src/gui/components/windows/juce_AlertWindow.cpp b/src/gui/components/windows/juce_AlertWindow.cpp index 035754f68a..f1e4105e5b 100644 --- a/src/gui/components/windows/juce_AlertWindow.cpp +++ b/src/gui/components/windows/juce_AlertWindow.cpp @@ -617,7 +617,7 @@ public: String title, message, button1, button2, button3; AlertWindow::AlertIconType iconType; int numButtons, returnValue; - Component::SafePointer associatedComponent; + WeakReference associatedComponent; int showModal() const { diff --git a/src/gui/components/windows/juce_ComponentPeer.cpp b/src/gui/components/windows/juce_ComponentPeer.cpp index a87cd3ba63..a260dce3e4 100644 --- a/src/gui/components/windows/juce_ComponentPeer.cpp +++ b/src/gui/components/windows/juce_ComponentPeer.cpp @@ -174,7 +174,7 @@ bool ComponentPeer::handleKeyPress (const int keyCode, while (target != 0) { - const Component::SafePointer deletionChecker (target); + const WeakReference deletionChecker (target); if (target->keyListeners_ != 0) { @@ -228,7 +228,7 @@ bool ComponentPeer::handleKeyUpOrDown (const bool isKeyDown) while (target != 0) { - const Component::SafePointer deletionChecker (target); + const WeakReference deletionChecker (target); keyWasUsed = target->keyStateChanged (isKeyDown); @@ -305,7 +305,7 @@ void ComponentPeer::handleMovedOrResized() if (component->flags.hasHeavyweightPeerFlag && ! nowMinimised) { - const Component::SafePointer deletionChecker (component); + const WeakReference deletionChecker (component); const Rectangle newBounds (getBounds()); const bool wasMoved = (component->getPosition() != newBounds.getPosition()); @@ -523,7 +523,7 @@ void ComponentPeer::handleFileDragDrop (const StringArray& files, const Point target; + WeakReference target; FileDragAndDropTarget* dropTarget; Point position; StringArray files; diff --git a/src/gui/components/windows/juce_ComponentPeer.h b/src/gui/components/windows/juce_ComponentPeer.h index 4791c878fb..f68cc00a4e 100644 --- a/src/gui/components/windows/juce_ComponentPeer.h +++ b/src/gui/components/windows/juce_ComponentPeer.h @@ -368,7 +368,7 @@ protected: private: //============================================================================== - Component::SafePointer lastFocusedComponent, dragAndDropTargetComponent; + WeakReference lastFocusedComponent, dragAndDropTargetComponent; Component* lastDragAndDropCompUnderMouse; bool fakeMouseMessageSent : 1, isWindowMinimised : 1; diff --git a/src/juce_core_includes.h b/src/juce_core_includes.h index 3a160f91f0..a72d830be8 100644 --- a/src/juce_core_includes.h +++ b/src/juce_core_includes.h @@ -92,6 +92,9 @@ #ifndef __JUCE_VARIANT_JUCEHEADER__ #include "containers/juce_Variant.h" #endif +#ifndef __JUCE_WEAKREFERENCE_JUCEHEADER__ + #include "containers/juce_WeakReference.h" +#endif #ifndef __JUCE_ATOMIC_JUCEHEADER__ #include "core/juce_Atomic.h" #endif diff --git a/src/native/linux/juce_linux_Windowing.cpp b/src/native/linux/juce_linux_Windowing.cpp index ef271e96f4..1b92aa6758 100644 --- a/src/native/linux/juce_linux_Windowing.cpp +++ b/src/native/linux/juce_linux_Windowing.cpp @@ -825,7 +825,7 @@ public: if (windowH != 0) { - Component::SafePointer deletionChecker (component); + WeakReference deletionChecker (component); wx = x; wy = y; diff --git a/src/native/mac/juce_mac_OpenGLComponent.mm b/src/native/mac/juce_mac_OpenGLComponent.mm index e9ed8b2c7d..b558e6c74a 100644 --- a/src/native/mac/juce_mac_OpenGLComponent.mm +++ b/src/native/mac/juce_mac_OpenGLComponent.mm @@ -498,7 +498,7 @@ public: //============================================================================== private: - Component::SafePointer component; + WeakReference component; OpenGLPixelFormat pixelFormat; JuceGLView* view; CAEAGLLayer* glLayer; diff --git a/src/native/windows/juce_win32_Windowing.cpp b/src/native/windows/juce_win32_Windowing.cpp index b93e115aeb..1699ed4cdf 100644 --- a/src/native/windows/juce_win32_Windowing.cpp +++ b/src/native/windows/juce_win32_Windowing.cpp @@ -702,7 +702,7 @@ public: if (fullScreen != shouldBeFullScreen) { fullScreen = shouldBeFullScreen; - const Component::SafePointer deletionChecker (component); + const WeakReference deletionChecker (component); if (! fullScreen) {