From 5fecb8a35337da1b68b219ca35d38cc629458bb7 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Thu, 25 Feb 2010 22:33:44 +0000 Subject: [PATCH] Created a new class Component::SafePointer that keeps a pointer to a component and automatically nulls it if the component is deleted - this makes it a much more elegant replacement for the old ComponentDeletionWatcher class. Removed Component::getComponentUnderMouse(), which doesn't fit with multi-touch interfaces - for similar functionality, use the Desktop::getMouseInputSource() methods to find out what MouseInputSources are available, and ask them about the component they are over or dragging. --- .../ui/jucer_ComponentOverlayComponent.cpp | 7 +- .../src/ui/jucer_ComponentOverlayComponent.h | 3 +- juce_amalgamated.cpp | 802 +++++++++--------- juce_amalgamated.h | 570 +++++++------ .../juce_ApplicationCommandManager.cpp | 1 + src/containers/juce_OwnedArray.h | 6 +- src/gui/components/buttons/juce_Button.cpp | 31 +- .../components/buttons/juce_ToggleButton.cpp | 1 - src/gui/components/controls/juce_ComboBox.cpp | 4 +- src/gui/components/controls/juce_Label.cpp | 17 +- src/gui/components/controls/juce_Label.h | 6 +- .../components/controls/juce_TextEditor.cpp | 5 +- src/gui/components/controls/juce_TreeView.cpp | 24 +- ...juce_DirectoryContentsDisplayComponent.cpp | 13 +- .../juce_DirectoryContentsDisplayComponent.h | 1 + .../filebrowser/juce_FileBrowserComponent.cpp | 15 +- .../filebrowser/juce_FileChooser.cpp | 10 +- src/gui/components/juce_Component.cpp | 296 +++---- src/gui/components/juce_Component.h | 76 +- src/gui/components/juce_ComponentListener.cpp | 32 +- src/gui/components/juce_ComponentListener.h | 10 + src/gui/components/juce_Desktop.cpp | 35 +- src/gui/components/juce_Desktop.h | 39 +- .../layout/juce_ComponentAnimator.cpp | 10 +- .../layout/juce_ComponentAnimator.h | 1 - .../juce_ComponentBoundsConstrainer.cpp | 1 + .../layout/juce_ComponentMovementWatcher.cpp | 16 +- .../layout/juce_ComponentMovementWatcher.h | 6 +- .../lookandfeel/juce_LookAndFeel.cpp | 1 + .../menus/juce_MenuBarComponent.cpp | 13 +- src/gui/components/menus/juce_PopupMenu.cpp | 28 +- .../mouse/juce_DragAndDropContainer.cpp | 218 +++-- .../mouse/juce_MouseInputSource.cpp | 11 +- .../components/special/juce_DropShadower.cpp | 2 +- .../special/juce_MagnifierComponent.cpp | 1 + .../special/juce_OpenGLComponent.cpp | 1 + .../components/windows/juce_AlertWindow.cpp | 1 + .../components/windows/juce_ComponentPeer.cpp | 36 +- .../components/windows/juce_ComponentPeer.h | 6 +- .../windows/juce_DocumentWindow.cpp | 1 + .../windows/juce_ResizableWindow.cpp | 1 + .../components/windows/juce_SplashScreen.cpp | 1 + .../components/windows/juce_TooltipWindow.cpp | 1 + .../windows/juce_TopLevelWindow.cpp | 1 + src/native/juce_linux_NativeCode.cpp | 2 +- src/native/juce_mac_NativeCode.mm | 1 + src/native/juce_win32_NativeCode.cpp | 1 + src/native/linux/juce_linux_Windowing.cpp | 4 +- src/native/windows/juce_win32_Windowing.cpp | 4 +- 49 files changed, 1236 insertions(+), 1137 deletions(-) diff --git a/extras/the jucer/src/ui/jucer_ComponentOverlayComponent.cpp b/extras/the jucer/src/ui/jucer_ComponentOverlayComponent.cpp index f31ee0e150..7ce38d633c 100644 --- a/extras/the jucer/src/ui/jucer_ComponentOverlayComponent.cpp +++ b/extras/the jucer/src/ui/jucer_ComponentOverlayComponent.cpp @@ -32,7 +32,6 @@ ComponentOverlayComponent::ComponentOverlayComponent (Component* const target_, ComponentLayout& layout_) : target (target_), borderThickness (4), - deletionWatcher (target_), layout (layout_), selected (false), dragging (false), @@ -58,7 +57,7 @@ ComponentOverlayComponent::~ComponentOverlayComponent() { layout.getSelectedSet().removeChangeListener (this); - if (! deletionWatcher.hasBeenDeleted()) + if (target != 0) target->removeComponentListener (this); delete border; @@ -78,7 +77,7 @@ void ComponentOverlayComponent::changeListenerCallback (void*) void ComponentOverlayComponent::paint (Graphics& g) { - jassert (! deletionWatcher.hasBeenDeleted()); + jassert (target != 0); if (selected) { @@ -94,7 +93,7 @@ void ComponentOverlayComponent::paint (Graphics& g) void ComponentOverlayComponent::resized() { - jassert (! deletionWatcher.hasBeenDeleted()); + jassert (target != 0); border->setBounds (0, 0, getWidth(), getHeight()); } diff --git a/extras/the jucer/src/ui/jucer_ComponentOverlayComponent.h b/extras/the jucer/src/ui/jucer_ComponentOverlayComponent.h index f70c16b1ef..8dd2e990d5 100644 --- a/extras/the jucer/src/ui/jucer_ComponentOverlayComponent.h +++ b/extras/the jucer/src/ui/jucer_ComponentOverlayComponent.h @@ -75,7 +75,7 @@ public: void applyBoundsToComponent (Component* component, const Rectangle& bounds); //============================================================================== - Component* const target; + Component::SafePointer target; const int borderThickness; //============================================================================== @@ -84,7 +84,6 @@ public: private: ResizableBorderComponent* border; - ComponentDeletionWatcher deletionWatcher; ComponentLayout& layout; bool selected, dragging, mouseDownSelectStatus; diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 8918d7075d..ee2775bec0 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -38492,7 +38492,6 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_Component.cpp ***/ BEGIN_JUCE_NAMESPACE -Component* Component::componentUnderMouse = 0; Component* Component::currentlyFocusedComponent = 0; static Array modalComponentStack, modalComponentReturnValueKeys; @@ -38536,6 +38535,17 @@ Component::Component (const String& name) throw() Component::~Component() { + if (componentListeners_ != 0) + { + for (int i = componentListeners_->size(); --i >= 0;) + { + ((ComponentListener*) componentListeners_->getUnchecked (i)) + ->componentBeingDeleted (*this); + + i = jmin (i, componentListeners_->size()); + } + } + if (parentComponent_ != 0) { parentComponent_->removeChildComponent (this); @@ -38546,9 +38556,6 @@ Component::~Component() giveAwayFocus(); } - if (componentUnderMouse == this) - componentUnderMouse = 0; - if (flags.hasHeavyweightPeerFlag) removeFromDesktop(); @@ -38584,14 +38591,14 @@ void Component::setName (const String& name) if (componentListeners_ != 0) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); for (int i = componentListeners_->size(); --i >= 0;) { ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentNameChanged (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -38609,7 +38616,7 @@ void Component::setVisible (bool shouldBeVisible) // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. checkMessageManagerIsLocked - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); flags.visibleFlag = shouldBeVisible; @@ -38631,7 +38638,7 @@ void Component::setVisible (bool shouldBeVisible) sendVisibilityChangeMessage(); - if ((! deletionChecker.hasBeenDeleted()) && flags.hasHeavyweightPeerFlag) + if (safePointer != 0 && flags.hasHeavyweightPeerFlag) { ComponentPeer* const peer = getPeer(); @@ -38651,18 +38658,18 @@ void Component::visibilityChanged() void Component::sendVisibilityChangeMessage() { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); visibilityChanged(); - if ((! deletionChecker.hasBeenDeleted()) && componentListeners_ != 0) + if (safePointer != 0 && componentListeners_ != 0) { for (int i = componentListeners_->size(); --i >= 0;) { ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentVisibilityChanged (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -38837,7 +38844,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) if (styleWanted != currentStyleFlags || ! flags.hasHeavyweightPeerFlag) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); #if JUCE_LINUX // it's wise to give the component a non-zero size before @@ -38869,7 +38876,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) if (parentComponent_ != 0) parentComponent_->removeChildComponent (this); - if (! deletionChecker.hasBeenDeleted()) + if (safePointer != 0) { flags.hasHeavyweightPeerFlag = true; @@ -39334,14 +39341,14 @@ void Component::sendMovedResizedMessages (const bool wasMoved, const bool wasRes if (componentListeners_ != 0) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); for (int i = componentListeners_->size(); --i >= 0;) { ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentMovedOrResized (*this, wasMoved, wasResized); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -39731,14 +39738,14 @@ void Component::childrenChanged() void Component::internalChildrenChanged() { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); const bool hasListeners = componentListeners_ != 0; childrenChanged(); if (hasListeners) { - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; for (int i = componentListeners_->size(); --i >= 0;) @@ -39746,7 +39753,7 @@ void Component::internalChildrenChanged() ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentChildrenChanged (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -39758,7 +39765,7 @@ void Component::internalHierarchyChanged() { parentHierarchyChanged(); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (componentListeners_ != 0) { @@ -39767,7 +39774,7 @@ void Component::internalHierarchyChanged() ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentParentHierarchyChanged (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -39780,8 +39787,8 @@ void Component::internalHierarchyChanged() // you really shouldn't delete the parent component during a callback telling you // that it's changed.. - jassert (! deletionChecker.hasBeenDeleted()); - if (deletionChecker.hasBeenDeleted()) + jassert (safePointer != 0); + if (safePointer == 0) return; i = jmin (i, childComponentList_.size()); @@ -39803,11 +39810,7 @@ int Component::runModalLoop() ->callFunctionOnMessageThread (&runModalLoopCallback, (void*) this); } - Component* const prevFocused = getCurrentlyFocusedComponent(); - - ScopedPointer deletionChecker; - if (prevFocused != 0) - deletionChecker = new ComponentDeletionWatcher (prevFocused); + SafePointer prevFocused (getCurrentlyFocusedComponent()); if (! isCurrentlyModal()) enterModalState(); @@ -39848,7 +39851,7 @@ int Component::runModalLoop() modalComponentStack.removeValue (this); - if (deletionChecker != 0 && ! deletionChecker->hasBeenDeleted()) + if (prevFocused != 0) prevFocused->grabKeyboardFocus(); return returnValue; @@ -40245,13 +40248,13 @@ void Component::sendLookAndFeelChange() // during the lookAndFeelChanged() callback) jassert (isValidComponent()); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); for (int i = childComponentList_.size(); --i >= 0;) { childComponentList_.getUnchecked (i)->sendLookAndFeelChange(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, childComponentList_.size()); @@ -40616,7 +40619,7 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& flags.mouseOverFlag = true; flags.draggingFlag = false; - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (flags.repaintOnMouseActivityFlag) repaint(); @@ -40627,7 +40630,7 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& mouseEnter (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; Desktop::getInstance().resetTimer(); @@ -40636,7 +40639,7 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& { ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseEnter (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, Desktop::getInstance().mouseListeners.size()); @@ -40648,24 +40651,24 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& { ((MouseListener*) mouseListeners_->getUnchecked(i))->mouseEnter (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked(i)))->mouseEnter (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -40678,13 +40681,13 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& void Component::internalMouseExit (MouseInputSource& source, const Point& relativePos, const Time& time) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (flags.draggingFlag) { internalMouseUp (source, relativePos, time, source.getCurrentModifiers().getRawFlags()); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; } @@ -40702,7 +40705,7 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r time, 0, false); mouseExit (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; Desktop::getInstance().resetTimer(); @@ -40711,7 +40714,7 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r { ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseExit (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, Desktop::getInstance().mouseListeners.size()); @@ -40723,24 +40726,24 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseExit (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseExit (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -40769,7 +40772,7 @@ public: Desktop& desktop = Desktop::getInstance(); int numMiceDown = 0; - for (int i = desktop.getNumMouseInputSources(); --i >= 0;) + for (int i = desktop.getNumMouseSources(); --i >= 0;) { MouseInputSource* const source = desktop.getMouseSource(i); if (source->isDragging()) @@ -40809,13 +40812,13 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r { Desktop& desktop = Desktop::getInstance(); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (isCurrentlyBlockedByAnotherModalComponent()) { internalModalInputAttempt(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; // If processing the input attempt has exited the modal loop, we'll allow the event @@ -40833,7 +40836,7 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r { ((MouseListener*) desktop.mouseListeners[i])->mouseDown (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -40852,7 +40855,7 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r { c->toFront (true); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; } @@ -40861,67 +40864,69 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r } if (! flags.dontFocusOnMouseClickFlag) + { grabFocusInternal (focusChangedByMouseClick); - if (! deletionChecker.hasBeenDeleted()) - { - flags.draggingFlag = true; - flags.mouseOverFlag = true; + if (safePointer == 0) + return; + } - if (flags.repaintOnMouseActivityFlag) - repaint(); + flags.draggingFlag = true; + flags.mouseOverFlag = true; - const MouseEvent me (source, relativePos, source.getCurrentModifiers(), - this, time, relativePos, time, - source.getNumberOfMultipleClicks(), false); - mouseDown (me); + if (flags.repaintOnMouseActivityFlag) + repaint(); - if (deletionChecker.hasBeenDeleted()) - return; + const MouseEvent me (source, relativePos, source.getCurrentModifiers(), + this, time, relativePos, time, + source.getNumberOfMultipleClicks(), false); + mouseDown (me); - desktop.resetTimer(); + if (safePointer == 0) + return; - for (int i = desktop.mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) desktop.mouseListeners[i])->mouseDown (me); + desktop.resetTimer(); - if (deletionChecker.hasBeenDeleted()) - return; + for (int i = desktop.mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) desktop.mouseListeners[i])->mouseDown (me); - i = jmin (i, desktop.mouseListeners.size()); - } + if (safePointer == 0) + return; - if (mouseListeners_ != 0) + i = jmin (i, desktop.mouseListeners.size()); + } + + if (mouseListeners_ != 0) + { + for (int i = mouseListeners_->size(); --i >= 0;) { - for (int i = mouseListeners_->size(); --i >= 0;) - { - ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDown (me); + ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDown (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (safePointer == 0) + return; - i = jmin (i, mouseListeners_->size()); - } + i = jmin (i, mouseListeners_->size()); } + } - const Component* p = parentComponent_; - - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + Component* p = parentComponent_; - for (int i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDown (me); + while (p != 0) + { + SafePointer parentPointer (p); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + for (int i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDown (me); - i = jmin (i, p->numDeepMouseListeners); - } + if (safePointer == 0 || parentPointer == 0) + return; - p = p->parentComponent_; + i = jmin (i, p->numDeepMouseListeners); } + + p = p->parentComponent_; } } @@ -40933,7 +40938,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel flags.draggingFlag = false; - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (flags.repaintOnMouseActivityFlag) repaint(); @@ -40947,7 +40952,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel mouseUp (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; desktop.resetTimer(); @@ -40956,7 +40961,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel { ((MouseListener*) desktop.mouseListeners[i])->mouseUp (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -40968,7 +40973,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseUp (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); @@ -40976,17 +40981,17 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel } { - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseUp (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -41008,7 +41013,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel { ((MouseListener*) desktop.mouseListeners[i])->mouseDoubleClick (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -41016,7 +41021,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel for (i = numListeners; --i >= 0;) { - if (deletionChecker.hasBeenDeleted() || mouseListeners_ == 0) + if (safePointer == 0 || mouseListeners_ == 0) return; MouseListener* const ml = (MouseListener*)((*mouseListeners_)[i]); @@ -41024,20 +41029,20 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel ml->mouseDoubleClick (me); } - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDoubleClick (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -41057,7 +41062,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r flags.mouseOverFlag = reallyContains (relativePos.getX(), relativePos.getY(), false); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); const MouseEvent me (source, relativePos, source.getCurrentModifiers(), this, time, @@ -41068,7 +41073,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r mouseDrag (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; desktop.resetTimer(); @@ -41077,7 +41082,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r { ((MouseListener*) desktop.mouseListeners[i])->mouseDrag (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -41089,24 +41094,24 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDrag (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDrag (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -41119,7 +41124,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r void Component::internalMouseMove (MouseInputSource& source, const Point& relativePos, const Time& time) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (isValidComponent()) { @@ -41140,7 +41145,7 @@ void Component::internalMouseMove (MouseInputSource& source, const Point& r mouseMove (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; desktop.resetTimer(); @@ -41149,7 +41154,7 @@ void Component::internalMouseMove (MouseInputSource& source, const Point& r { ((MouseListener*) desktop.mouseListeners[i])->mouseMove (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -41161,24 +41166,24 @@ void Component::internalMouseMove (MouseInputSource& source, const Point& r { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseMove (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseMove (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -41194,7 +41199,7 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point& const Time& time, const float amountX, const float amountY) { Desktop& desktop = Desktop::getInstance(); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); const float wheelIncrementX = amountX * (1.0f / 256.0f); const float wheelIncrementY = amountY * (1.0f / 256.0f); @@ -41209,7 +41214,7 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point& { ((MouseListener*) desktop.mouseListeners[i])->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -41219,14 +41224,14 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point& { mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; for (int i = desktop.mouseListeners.size(); --i >= 0;) { ((MouseListener*) desktop.mouseListeners[i])->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -41238,24 +41243,24 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point& { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -41282,10 +41287,10 @@ void Component::internalBroughtToFront() if (flags.hasHeavyweightPeerFlag) Desktop::getInstance().componentBroughtToFront (this); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); broughtToFront(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; if (componentListeners_ != 0) @@ -41295,7 +41300,7 @@ void Component::internalBroughtToFront() ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentBroughtToFront (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -41319,11 +41324,11 @@ void Component::focusGained (FocusChangeType) void Component::internalFocusGain (const FocusChangeType cause) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); focusGained (cause); - if (! deletionChecker.hasBeenDeleted()) + if (safePointer != 0) internalChildFocusChange (cause); } @@ -41334,11 +41339,11 @@ void Component::focusLost (FocusChangeType) void Component::internalFocusLoss (const FocusChangeType cause) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); focusLost (focusChangedDirectly); - if (! deletionChecker.hasBeenDeleted()) + if (safePointer != 0) internalChildFocusChange (cause); } @@ -41355,10 +41360,10 @@ void Component::internalChildFocusChange (FocusChangeType cause) { flags.childCompFocusedFlag = childIsNowFocused; - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); focusOfChildComponentChanged (cause); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; } @@ -41387,11 +41392,11 @@ void Component::setEnabled (const bool shouldBeEnabled) void Component::sendEnablementChangeMessage() { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); enablementChanged(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; for (int i = getNumChildComponents(); --i >= 0;) @@ -41402,7 +41407,7 @@ void Component::sendEnablementChangeMessage() { c->sendEnablementChangeMessage(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; } } @@ -41472,7 +41477,7 @@ void Component::takeKeyboardFocus (const FocusChangeType cause) if (peer != 0) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); peer->grabFocus(); @@ -41493,7 +41498,7 @@ void Component::takeKeyboardFocus (const FocusChangeType cause) { focusGained (cause); - if (! deletionChecker.hasBeenDeleted()) + if (safePointer != 0) internalChildFocusChange (cause); } } @@ -41588,11 +41593,10 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) { if (nextComp->isCurrentlyBlockedByAnotherModalComponent()) { - const ComponentDeletionWatcher deletionChecker (nextComp); + SafePointer safePointer (this); internalModalInputAttempt(); - if (deletionChecker.hasBeenDeleted() - || nextComp->isCurrentlyBlockedByAnotherModalComponent()) + if (safePointer == 0 || nextComp->isCurrentlyBlockedByAnotherModalComponent()) return; } @@ -41652,11 +41656,6 @@ const Point Component::getMouseXYRelative() const return globalPositionToRelative (Desktop::getMousePosition()); } -Component* JUCE_CALLTYPE Component::getComponentUnderMouse() throw() -{ - return componentUnderMouse; -} - const Rectangle Component::getParentMonitorArea() const throw() { return Desktop::getInstance() @@ -41740,29 +41739,13 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_ComponentListener.cpp ***/ BEGIN_JUCE_NAMESPACE -void ComponentListener::componentMovedOrResized (Component&, bool, bool) -{ -} - -void ComponentListener::componentBroughtToFront (Component&) -{ -} - -void ComponentListener::componentVisibilityChanged (Component&) -{ -} - -void ComponentListener::componentChildrenChanged (Component&) -{ -} - -void ComponentListener::componentParentHierarchyChanged (Component&) -{ -} - -void ComponentListener::componentNameChanged (Component&) -{ -} +void ComponentListener::componentMovedOrResized (Component&, bool, bool) {} +void ComponentListener::componentBroughtToFront (Component&) {} +void ComponentListener::componentVisibilityChanged (Component&) {} +void ComponentListener::componentChildrenChanged (Component&) {} +void ComponentListener::componentParentHierarchyChanged (Component&) {} +void ComponentListener::componentNameChanged (Component&) {} +void ComponentListener::componentBeingDeleted (Component& component) {} END_JUCE_NAMESPACE /*** End of inlined file: juce_ComponentListener.cpp ***/ @@ -41953,6 +41936,35 @@ void Desktop::incrementMouseClickCounter() throw() ++mouseClickCounter; } +int Desktop::getNumDraggingMouseSources() const throw() +{ + int num = 0; + for (int i = mouseSources.size(); --i >= 0;) + if (mouseSources.getUnchecked(i)->isDragging()) + ++num; + + return num; +} + +MouseInputSource* Desktop::getDraggingMouseSource (int index) const throw() +{ + int num = 0; + for (int i = mouseSources.size(); --i >= 0;) + { + MouseInputSource* const mi = mouseSources.getUnchecked(i); + + if (mi->isDragging()) + { + if (index == num) + return mi; + + ++num; + } + } + + return 0; +} + void Desktop::addGlobalMouseListener (MouseListener* const listener) throw() { jassert (listener != 0); @@ -42015,7 +42027,7 @@ void Desktop::sendMouseMove() if (target != 0) { - ComponentDeletionWatcher deletionChecker (target); + Component::SafePointer deletionChecker (target); const Point pos (target->globalPositionToRelative (lastFakeMouseMove)); const Time now (Time::getCurrentTime()); @@ -42029,7 +42041,7 @@ void Desktop::sendMouseMove() else ((MouseListener*) mouseListeners[i])->mouseMove (me); - if (deletionChecker.hasBeenDeleted()) + if (deletionChecker == 0) return; i = jmin (i, mouseListeners.size()); @@ -42245,16 +42257,20 @@ void Button::setToggleState (const bool shouldBeOn, { if (shouldBeOn != lastToggleState) { - const ComponentDeletionWatcher deletionWatcher (this); - isOn = shouldBeOn; lastToggleState = shouldBeOn; repaint(); if (sendChangeNotification) + { + Component::SafePointer deletionWatcher (this); sendClickMessage (ModifierKeys()); - if ((! deletionWatcher.hasBeenDeleted()) && lastToggleState) + if (deletionWatcher == 0) + return; + } + + if (lastToggleState) turnOffOtherButtonsInGroup (sendChangeNotification); } } @@ -42298,7 +42314,7 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) if (p != 0 && radioGroupId != 0) { - const ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); for (int i = p->getNumChildComponents(); --i >= 0;) { @@ -42312,7 +42328,7 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) { b->setToggleState (false, sendChangeNotification); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; } } @@ -42462,7 +42478,7 @@ void Button::removeButtonListener (ButtonListener* const listener) void Button::sendClickMessage (const ModifierKeys& modifiers) { - const ComponentDeletionWatcher cdw (this); + Component::SafePointer deletionWatcher (this); if (commandManagerToUse != 0 && commandID != 0) { @@ -42475,7 +42491,7 @@ void Button::sendClickMessage (const ModifierKeys& modifiers) clicked (modifiers); - if (! cdw.hasBeenDeleted()) + if (deletionWatcher != 0) { for (int i = buttonListeners.size(); --i >= 0;) { @@ -42485,7 +42501,7 @@ void Button::sendClickMessage (const ModifierKeys& modifiers) { bl->buttonClicked (this); - if (cdw.hasBeenDeleted()) + if (deletionWatcher == 0) return; } } @@ -42494,11 +42510,11 @@ void Button::sendClickMessage (const ModifierKeys& modifiers) void Button::sendStateMessage() { - const ComponentDeletionWatcher cdw (this); + Component::SafePointer deletionWatcher (this); buttonStateChanged(); - if (cdw.hasBeenDeleted()) + if (deletionWatcher == 0) return; for (int i = buttonListeners.size(); --i >= 0;) @@ -42509,7 +42525,7 @@ void Button::sendStateMessage() { bl->buttonStateChanged (this); - if (cdw.hasBeenDeleted()) + if (deletionWatcher == 0) return; } } @@ -42785,13 +42801,13 @@ void Button::repeatTimerCallback() lastTimeCallbackTime = now; - const ComponentDeletionWatcher cdw (this); + Component::SafePointer deletionWatcher (this); for (int i = numTimesToCallback; --i >= 0;) { internalClickCallback (ModifierKeys::getCurrentModifiers()); - if (cdw.hasBeenDeleted() || ! isDown()) + if (deletionWatcher == 0 || ! isDown()) return; } } @@ -46745,7 +46761,7 @@ void ComboBox::showPopup() if (! menuActive) { const int selectedId = getSelectedId(); - ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); PopupMenu menu; @@ -46773,7 +46789,7 @@ void ComboBox::showPopup() const int resultId = menu.showAt (this, selectedId, getWidth(), 1, itemHeight); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; menuActive = false; @@ -46875,7 +46891,7 @@ Label::~Label() { textValue.removeListener (this); - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + if (ownerComponent != 0) ownerComponent->removeComponentListener (this); editor = 0; @@ -46894,7 +46910,7 @@ void Label::setText (const String& newText, textWasChanged(); - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + if (ownerComponent != 0) componentMovedOrResized (*ownerComponent, true, true); if (broadcastChangeMessage) @@ -46951,21 +46967,23 @@ void Label::setBorderSize (int h, int v) repaint(); } +Component* Label::getAttachedComponent() const +{ + return const_cast (static_cast (ownerComponent)); +} + void Label::attachToComponent (Component* owner, const bool onLeft) { - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + if (ownerComponent != 0) ownerComponent->removeComponentListener (this); - deletionWatcher = 0; ownerComponent = owner; leftOfOwnerComp = onLeft; if (ownerComponent != 0) { - deletionWatcher = new ComponentDeletionWatcher (owner); - setVisible (owner->isVisible()); ownerComponent->addComponentListener (this); componentParentHierarchyChanged (*ownerComponent); @@ -47054,7 +47072,7 @@ bool Label::updateFromTextEditorContents() textWasChanged(); - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + if (ownerComponent != 0) componentMovedOrResized (*ownerComponent, true, true); return true; @@ -53246,7 +53264,7 @@ void TextEditor::resized() void TextEditor::handleCommandMessage (const int commandId) { - const ComponentDeletionWatcher deletionChecker (this); + Component::SafePointer deletionChecker (this); for (int i = listeners.size(); --i >= 0;) { @@ -53277,7 +53295,7 @@ void TextEditor::handleCommandMessage (const int commandId) break; } - if (i > 0 && deletionChecker.hasBeenDeleted()) + if (deletionChecker == 0) return; } } @@ -55028,6 +55046,24 @@ public: void paint (Graphics& g); TreeViewItem* findItemAt (int y, Rectangle& itemPosition) const; + static bool isMouseDraggingInChildCompOf (Component* const comp) + { + for (int i = Desktop::getInstance().getNumMouseSources(); --i >= 0;) + { + MouseInputSource* source = Desktop::getInstance().getMouseSource(i); + + if (source->isDragging()) + { + Component* const underMouse = source->getComponentUnderMouse(); + + if (underMouse != 0 && (comp == underMouse || comp->isParentOf (underMouse))) + return true; + } + } + + return false; + } + void updateComponents() { const int visibleTop = -getY(); @@ -55089,10 +55125,7 @@ public: } } - if ((! keep) - && Component::isMouseButtonDownAnywhere() - && (comp == Component::getComponentUnderMouse() - || comp->isParentOf (Component::getComponentUnderMouse()))) + if ((! keep) && isMouseDraggingInChildCompOf (comp)) { keep = true; comp->setSize (0, 0); @@ -56657,13 +56690,13 @@ void DirectoryContentsDisplayComponent::removeListener (FileBrowserListener* con void DirectoryContentsDisplayComponent::sendSelectionChangeMessage() { - const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); + Component::SafePointer deletionWatcher (dynamic_cast (this)); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->selectionChanged(); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -56674,13 +56707,13 @@ void DirectoryContentsDisplayComponent::sendMouseClickMessage (const File& file, { if (fileList.getDirectory().exists()) { - const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); + Component::SafePointer deletionWatcher (dynamic_cast (this)); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->fileClicked (file, e); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -56692,13 +56725,13 @@ void DirectoryContentsDisplayComponent::sendDoubleClickMessage (const File& file { if (fileList.getDirectory().exists()) { - const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); + Component::SafePointer deletionWatcher (dynamic_cast (this)); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->fileDoubleClicked (file); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -57243,18 +57276,19 @@ void FileBrowserComponent::resized() void FileBrowserComponent::sendListenerChangeMessage() { - ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); if (previewComp != 0) previewComp->selectedFileChanged (getSelectedFile (0)); - jassert (! deletionWatcher.hasBeenDeleted()); + // You shouldn't delete the browser when the file gets changed! + jassert (deletionWatcher != 0); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->selectionChanged(); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -57291,13 +57325,13 @@ void FileBrowserComponent::selectionChanged() void FileBrowserComponent::fileClicked (const File& f, const MouseEvent& e) { - ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->fileClicked (f, e); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -57312,13 +57346,13 @@ void FileBrowserComponent::fileDoubleClicked (const File& f) } else { - ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->fileDoubleClicked (f); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -57576,11 +57610,7 @@ bool FileChooser::showDialog (const bool selectsDirectories, const bool selectMultipleFiles, FilePreviewComponent* const previewComponent) { - ScopedPointer currentlyFocusedChecker; - Component* const currentlyFocused = Component::getCurrentlyFocusedComponent(); - - if (currentlyFocused != 0) - currentlyFocusedChecker = new ComponentDeletionWatcher (currentlyFocused); + Component::SafePointer previouslyFocused (Component::getCurrentlyFocusedComponent()); results.clear(); @@ -57634,8 +57664,8 @@ bool FileChooser::showDialog (const bool selectsDirectories, } } - if (currentlyFocused != 0 && ! currentlyFocusedChecker->hasBeenDeleted()) - currentlyFocused->grabKeyboardFocus(); + if (previouslyFocused != 0) + previouslyFocused->grabKeyboardFocus(); return results.size() > 0; } @@ -60223,13 +60253,11 @@ BEGIN_JUCE_NAMESPACE struct AnimationTask { AnimationTask (Component* const comp) - : component (comp), - watcher (comp) + : component (comp) { } - Component* component; - ComponentDeletionWatcher watcher; + Component::SafePointer component; Rectangle destination; int msElapsed, msTotal; double startSpeed, midSpeed, endSpeed, lastProgress; @@ -60237,7 +60265,7 @@ struct AnimationTask bool useTimeslice (const int elapsed) { - if (watcher.hasBeenDeleted()) + if (component == 0) return false; msElapsed += elapsed; @@ -60276,7 +60304,7 @@ struct AnimationTask void moveToFinalDestination() { - if (! watcher.hasBeenDeleted()) + if (component != 0) component->setBounds (destination); } @@ -60763,10 +60791,6 @@ ComponentMovementWatcher::ComponentMovementWatcher (Component* const component_) { jassert (component != 0); // can't use this with a null pointer.. -#ifdef JUCE_DEBUG - deletionWatcher = new ComponentDeletionWatcher (component_); -#endif - component->addComponentListener (this); registerWithParentComps(); @@ -60781,10 +60805,8 @@ ComponentMovementWatcher::~ComponentMovementWatcher() void ComponentMovementWatcher::componentParentHierarchyChanged (Component&) { -#ifdef JUCE_DEBUG // agh! don't delete the target component without deleting this object first! - jassert (! deletionWatcher->hasBeenDeleted()); -#endif + jassert (component != 0); if (! reentrant) { @@ -60794,11 +60816,9 @@ void ComponentMovementWatcher::componentParentHierarchyChanged (Component&) if (peer != lastPeer) { - ComponentDeletionWatcher watcher (component); - componentPeerChanged(); - if (watcher.hasBeenDeleted()) + if (component == 0) return; lastPeer = peer; @@ -60815,10 +60835,8 @@ void ComponentMovementWatcher::componentParentHierarchyChanged (Component&) void ComponentMovementWatcher::componentMovedOrResized (Component&, bool wasMoved, bool wasResized) { -#ifdef JUCE_DEBUG // agh! don't delete the target component without deleting this object first! - jassert (! deletionWatcher->hasBeenDeleted()); -#endif + jassert (component != 0); if (wasMoved) { @@ -67491,13 +67509,8 @@ void MenuBarComponent::showMenu (int index) currentPopup = 0; menuBarItemsChanged (0); - Component* const prevFocused = getCurrentlyFocusedComponent(); - - ScopedPointer prevCompDeletionChecker; - if (prevFocused != 0) - prevCompDeletionChecker = new ComponentDeletionWatcher (prevFocused); - - ComponentDeletionWatcher deletionChecker (this); + Component::SafePointer prevFocused (getCurrentlyFocusedComponent()); + Component::SafePointer deletionChecker (this); enterModalState (false); inModalState = true; @@ -67542,7 +67555,7 @@ void MenuBarComponent::showMenu (int index) // be stuck behind other comps that are already modal.. result = currentPopup->runModalLoop(); - if (deletionChecker.hasBeenDeleted()) + if (deletionChecker == 0) return; const int lastPopupIndex = currentPopupIndex; @@ -67574,7 +67587,7 @@ void MenuBarComponent::showMenu (int index) inModalState = false; exitModalState (0); - if (prevCompDeletionChecker != 0 && ! prevCompDeletionChecker->hasBeenDeleted()) + if (prevFocused != 0) prevFocused->grabKeyboardFocus(); const Point mousePos (getMouseXYRelative()); @@ -68048,7 +68061,6 @@ public: activeSubMenu (0), menuBarComponent (0), managerOfChosenCommand (0), - componentAttachedTo (0), minimumWidth (0), maximumNumColumns (7), standardItemHeight (0), @@ -68087,7 +68099,6 @@ public: activeSubMenu = 0; deleteAllChildren(); - attachedCompWatcher = 0; } static Window* create (const PopupMenu& menu, @@ -68130,7 +68141,6 @@ public: mw->menuBarComponent = menuBarComponent; mw->managerOfChosenCommand = managerOfChosenCommand; mw->componentAttachedTo = componentAttachedTo; - mw->attachedCompWatcher = componentAttachedTo != 0 ? new ComponentDeletionWatcher (componentAttachedTo) : 0; mw->calculateWindowPos (minX, maxX, minY, maxY, alignToRectangle); mw->setTopLeftPosition (mw->windowPos.getX(), @@ -68335,7 +68345,7 @@ public: if (! isOverAnyMenu()) { - if (componentAttachedTo != 0 && ! attachedCompWatcher->hasBeenDeleted()) + if (componentAttachedTo != 0) { // we want to dismiss the menu, but if we do it synchronously, then // the mouse-click will be allowed to pass through. That's good, except @@ -68369,7 +68379,7 @@ public: if (! isVisible()) return; - if (attachedCompWatcher != 0 && attachedCompWatcher->hasBeenDeleted()) + if (componentAttachedTo == 0) { dismissMenu (0); return; @@ -68521,8 +68531,7 @@ private: ScopedPointer activeSubMenu; Component* menuBarComponent; ApplicationCommandManager** managerOfChosenCommand; - Component* componentAttachedTo; - ScopedPointer attachedCompWatcher; + Component::SafePointer componentAttachedTo; Rectangle windowPos; Point lastMouse; int minimumWidth, maximumNumColumns, standardItemHeight; @@ -69308,16 +69317,8 @@ int PopupMenu::showMenu (const int x, const int y, const int w, const int h, const bool alignToRectangle, Component* const componentAttachedTo) { - Component* const prevFocused = Component::getCurrentlyFocusedComponent(); - - ScopedPointer deletionChecker[2]; - if (prevFocused != 0) - deletionChecker[0] = new ComponentDeletionWatcher (prevFocused); - - Component* const prevTopLevel = (prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0; - - if (prevTopLevel != 0) - deletionChecker[1] = new ComponentDeletionWatcher (prevTopLevel); + Component::SafePointer prevFocused (Component::getCurrentlyFocusedComponent()); + Component::SafePointer prevTopLevel ((prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0); Window::wasHiddenBecauseOfAppChange() = false; @@ -69344,10 +69345,10 @@ int PopupMenu::showMenu (const int x, const int y, const int w, const int h, if (! Window::wasHiddenBecauseOfAppChange()) { - if (deletionChecker[1] != 0 && ! deletionChecker[1]->hasBeenDeleted()) + if (prevTopLevel != 0) prevTopLevel->toFront (true); - if (deletionChecker[0] != 0 && ! deletionChecker[0]->hasBeenDeleted()) + if (prevFocused != 0) prevFocused->grabKeyboardFocus(); } } @@ -69630,13 +69631,14 @@ class DragImageComponent : public Component, public: DragImageComponent (Image* const im, const String& desc, - Component* const s, + Component* const sourceComponent, + Component* const mouseDragSource_, DragAndDropContainer* const o, const Point& imageOffset_) : image (im), - source (s), + source (sourceComponent), + mouseDragSource (mouseDragSource_), owner (o), - currentlyOver (0), dragDesc (desc), imageOffset (imageOffset_), hasCheckedForExternalDrag (false), @@ -69644,14 +69646,9 @@ public: { setSize (im->getWidth(), im->getHeight()); - sourceWatcher = new ComponentDeletionWatcher (source); - - mouseDragSource = Component::getComponentUnderMouse(); - if (mouseDragSource == 0) mouseDragSource = source; - mouseDragSourceWatcher = new ComponentDeletionWatcher (mouseDragSource); mouseDragSource->addMouseListener (this, false); startTimer (200); @@ -69665,13 +69662,12 @@ public: if (owner->dragImageComponent == this) owner->dragImageComponent.release(); - if (! mouseDragSourceWatcher->hasBeenDeleted()) + if (mouseDragSource != 0) { mouseDragSource->removeMouseListener (this); - if (currentlyOverWatcher != 0 && ! currentlyOverWatcher->hasBeenDeleted()) - if (currentlyOver->isInterestedInDragSource (dragDesc, source)) - currentlyOver->itemDragExit (dragDesc, source); + if (getCurrentlyOver() != 0 && getCurrentlyOver()->isInterestedInDragSource (dragDesc, source)) + getCurrentlyOver()->itemDragExit (dragDesc, source); } } @@ -69687,8 +69683,7 @@ public: } } - DragAndDropTarget* findTarget (const Point& screenPos, - Point& relativePos) const + DragAndDropTarget* findTarget (const Point& screenPos, Point& relativePos) { Component* hit = getParentComponent(); @@ -69726,7 +69721,7 @@ public: { if (e.originalComponent != this) { - if (! mouseDragSourceWatcher->hasBeenDeleted()) + if (mouseDragSource != 0) mouseDragSource->removeMouseListener (this); bool dropAccepted = false; @@ -69744,7 +69739,7 @@ public: setVisible (true); - if (dropAccepted || sourceWatcher->hasBeenDeleted()) + if (dropAccepted || source == 0) { fadeOutComponent (120); } @@ -69771,8 +69766,7 @@ public: // a modal loop and deletes this object before the method completes) const String dragDescLocal (dragDesc); - currentlyOverWatcher = 0; - currentlyOver = 0; + currentlyOverComp = 0; ddt->itemDropped (dragDescLocal, source, relPos.getX(), relPos.getY()); } @@ -69798,46 +69792,28 @@ public: Point relPos; DragAndDropTarget* const ddt = findTarget (screenPos, relPos); + Component* ddtComp = dynamic_cast (ddt); drawImage = (ddt == 0) || ddt->shouldDrawDragImageWhenOver(); - if (ddt != currentlyOver) + if (ddtComp != currentlyOverComp) { - if (currentlyOverWatcher != 0 && ! currentlyOverWatcher->hasBeenDeleted()) + if (currentlyOverComp != 0 && source != 0 + && getCurrentlyOver()->isInterestedInDragSource (dragDescLocal, source)) { - Component* const over = dynamic_cast (currentlyOver); - - if (over != 0 - && over->isValidComponent() - && ! (sourceWatcher->hasBeenDeleted()) - && currentlyOver->isInterestedInDragSource (dragDescLocal, source)) - { - currentlyOver->itemDragExit (dragDescLocal, source); - } + getCurrentlyOver()->itemDragExit (dragDescLocal, source); } - currentlyOver = ddt; - currentlyOverWatcher = 0; + currentlyOverComp = ddtComp; - if (ddt != 0) - { - currentlyOverWatcher = new ComponentDeletionWatcher (dynamic_cast (ddt)); - - if (currentlyOver->isInterestedInDragSource (dragDescLocal, source)) - currentlyOver->itemDragEnter (dragDescLocal, source, relPos.getX(), relPos.getY()); - } - } - else if (currentlyOverWatcher != 0 && currentlyOverWatcher->hasBeenDeleted()) - { - currentlyOver = 0; - currentlyOverWatcher = 0; + if (ddt != 0 && ddt->isInterestedInDragSource (dragDescLocal, source)) + ddt->itemDragEnter (dragDescLocal, source, relPos.getX(), relPos.getY()); } - if (currentlyOver != 0 - && currentlyOver->isInterestedInDragSource (dragDescLocal, source)) - currentlyOver->itemDragMove (dragDescLocal, source, relPos.getX(), relPos.getY()); + if (getCurrentlyOver() != 0 && getCurrentlyOver()->isInterestedInDragSource (dragDescLocal, source)) + getCurrentlyOver()->itemDragMove (dragDescLocal, source, relPos.getX(), relPos.getY()); - if (currentlyOver == 0 + if (getCurrentlyOver() == 0 && canDoExternalDrag && ! hasCheckedForExternalDrag) { @@ -69850,13 +69826,13 @@ public: if (owner->shouldDropFilesWhenDraggedExternally (dragDescLocal, source, files, canMoveFiles) && files.size() > 0) { - ComponentDeletionWatcher cdw (this); + Component::SafePointer cdw (this); setVisible (false); if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles); - if (! cdw.hasBeenDeleted()) + if (cdw != 0) delete this; return; @@ -69874,13 +69850,13 @@ public: void timerCallback() { - if (sourceWatcher->hasBeenDeleted()) + if (source == 0) { delete this; } else if (! isMouseButtonDownAnywhere()) { - if (! mouseDragSourceWatcher->hasBeenDeleted()) + if (mouseDragSource != 0) mouseDragSource->removeMouseListener (this); delete this; @@ -69889,12 +69865,15 @@ public: private: ScopedPointer image; - Component* const source; + Component::SafePointer source; + Component::SafePointer mouseDragSource; DragAndDropContainer* const owner; - ScopedPointer sourceWatcher, mouseDragSourceWatcher, currentlyOverWatcher; - Component* mouseDragSource; - DragAndDropTarget* currentlyOver; + Component::SafePointer currentlyOverComp; + DragAndDropTarget* getCurrentlyOver() + { + return dynamic_cast (static_cast (currentlyOverComp)); + } String dragDesc; const Point imageOffset; @@ -69925,90 +69904,95 @@ void DragAndDropContainer::startDragging (const String& sourceDescription, { Component* const thisComp = dynamic_cast (this); - if (thisComp != 0) + if (thisComp == 0) { - const Point lastMouseDown (Desktop::getLastMouseDownPosition()); - Point imageOffset; + jassertfalse; // Your DragAndDropContainer needs to be a Component! + return; + } + + MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource (0); + + if (draggingSource == 0 || ! draggingSource->isDragging()) + { + jassertfalse; // You must call startDragging() from within a mouseDown or mouseDrag callback! + return; + } - if (dragImage == 0) + const Point lastMouseDown (Desktop::getLastMouseDownPosition()); + Point imageOffset; + + if (dragImage == 0) + { + dragImage = sourceComponent->createComponentSnapshot (Rectangle (0, 0, sourceComponent->getWidth(), sourceComponent->getHeight())); + + if (dragImage->getFormat() != Image::ARGB) { - dragImage = sourceComponent->createComponentSnapshot (Rectangle (0, 0, sourceComponent->getWidth(), sourceComponent->getHeight())); + Image* newIm = Image::createNativeImage (Image::ARGB, dragImage->getWidth(), dragImage->getHeight(), true); + Graphics g2 (*newIm); + g2.drawImageAt (dragImage, 0, 0); - if (dragImage->getFormat() != Image::ARGB) - { - Image* newIm = Image::createNativeImage (Image::ARGB, dragImage->getWidth(), dragImage->getHeight(), true); - Graphics g2 (*newIm); - g2.drawImageAt (dragImage, 0, 0); + dragImage = newIm; + } - dragImage = newIm; - } + dragImage->multiplyAllAlphas (0.6f); - dragImage->multiplyAllAlphas (0.6f); + const int lo = 150; + const int hi = 400; - const int lo = 150; - const int hi = 400; + Point relPos (sourceComponent->globalPositionToRelative (lastMouseDown)); + Point clipped (Rectangle (0, 0, dragImage->getWidth(), dragImage->getHeight()) + .getConstrainedPoint (relPos)); - Point relPos (sourceComponent->globalPositionToRelative (lastMouseDown)); - Point clipped (Rectangle (0, 0, dragImage->getWidth(), dragImage->getHeight()) - .getConstrainedPoint (relPos)); + for (int y = dragImage->getHeight(); --y >= 0;) + { + const double dy = (y - clipped.getY()) * (y - clipped.getY()); - for (int y = dragImage->getHeight(); --y >= 0;) + for (int x = dragImage->getWidth(); --x >= 0;) { - const double dy = (y - clipped.getY()) * (y - clipped.getY()); + const int dx = x - clipped.getX(); + const int distance = roundToInt (sqrt (dx * dx + dy)); - for (int x = dragImage->getWidth(); --x >= 0;) + if (distance > lo) { - const int dx = x - clipped.getX(); - const int distance = roundToInt (sqrt (dx * dx + dy)); - - if (distance > lo) - { - const float alpha = (distance > hi) ? 0 - : (hi - distance) / (float) (hi - lo) - + Random::getSystemRandom().nextFloat() * 0.008f; + const float alpha = (distance > hi) ? 0 + : (hi - distance) / (float) (hi - lo) + + Random::getSystemRandom().nextFloat() * 0.008f; - dragImage->multiplyAlphaAt (x, y, alpha); - } + dragImage->multiplyAlphaAt (x, y, alpha); } } - - imageOffset = -clipped; - } - else - { - if (imageOffsetFromMouse == 0) - imageOffset = Point (dragImage->getWidth() / -2, - dragImage->getHeight() / -2); - else - imageOffset = *imageOffsetFromMouse; } - dragImageComponent = new DragImageComponent (dragImage.release(), sourceDescription, sourceComponent, - this, imageOffset); + imageOffset = -clipped; + } + else + { + if (imageOffsetFromMouse == 0) + imageOffset = Point (dragImage->getWidth() / -2, + dragImage->getHeight() / -2); + else + imageOffset = *imageOffsetFromMouse; + } - currentDragDesc = sourceDescription; + dragImageComponent = new DragImageComponent (dragImage.release(), sourceDescription, sourceComponent, + draggingSource->getComponentUnderMouse(), this, imageOffset); - if (allowDraggingToExternalWindows) - { - if (! Desktop::canUseSemiTransparentWindows()) - dragImageComponent->setOpaque (true); + currentDragDesc = sourceDescription; - dragImageComponent->addToDesktop (ComponentPeer::windowIgnoresMouseClicks - | ComponentPeer::windowIsTemporary - | ComponentPeer::windowIgnoresKeyPresses); - } - else - thisComp->addChildComponent (dragImageComponent); + if (allowDraggingToExternalWindows) + { + if (! Desktop::canUseSemiTransparentWindows()) + dragImageComponent->setOpaque (true); - static_cast (static_cast (dragImageComponent))->updateLocation (false, lastMouseDown); - dragImageComponent->setVisible (true); + dragImageComponent->addToDesktop (ComponentPeer::windowIgnoresMouseClicks + | ComponentPeer::windowIsTemporary + | ComponentPeer::windowIgnoresKeyPresses); } else - { - // this class must only be implemented by an object that - // is also a Component. - jassertfalse - } + thisComp->addChildComponent (dragImageComponent); + + static_cast (static_cast (dragImageComponent))->updateLocation (false, lastMouseDown); + dragImageComponent->setVisible (true); } } @@ -70365,7 +70349,7 @@ public: Component* getComponentUnderMouse() const { - return componentUnderMouse != 0 ? const_cast (componentUnderMouse->getComponent()) : 0; + return const_cast (static_cast (componentUnderMouse)); } const ModifierKeys getCurrentModifiers() const @@ -70449,7 +70433,7 @@ public: if (newComponent != current) { - ScopedPointer newCompWatcher (newComponent != 0 ? new ComponentDeletionWatcher (newComponent) : 0); + Component::SafePointer safeNewComp (newComponent); const ModifierKeys originalButtonState (buttonState); if (current != 0) @@ -70459,9 +70443,8 @@ public: buttonState = originalButtonState; } - componentUnderMouse = newCompWatcher; + componentUnderMouse = safeNewComp; current = getComponentUnderMouse(); - Component::componentUnderMouse = current; if (current != 0) current->internalMouseEnter (source, current->globalPositionToRelative (screenPos), time); @@ -70705,7 +70688,7 @@ public: private: MouseInputSource& source; - ScopedPointer componentUnderMouse; + Component::SafePointer componentUnderMouse; ComponentPeer* lastPeer; Point unboundedMouseOffset; @@ -76454,7 +76437,7 @@ bool ComponentPeer::handleKeyPress (const int keyCode, while (target != 0) { - const ComponentDeletionWatcher deletionChecker (target); + const Component::SafePointer deletionChecker (target); if (target->keyListeners_ != 0) { @@ -76462,7 +76445,7 @@ bool ComponentPeer::handleKeyPress (const int keyCode, { keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyPressed (keyInfo, target); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) + if (keyWasUsed || deletionChecker == 0) return keyWasUsed; i = jmin (i, target->keyListeners_->size()); @@ -76471,7 +76454,7 @@ bool ComponentPeer::handleKeyPress (const int keyCode, keyWasUsed = target->keyPressed (keyInfo); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) + if (keyWasUsed || deletionChecker == 0) break; if (keyInfo.isKeyCode (KeyPress::tabKey) && Component::getCurrentlyFocusedComponent() != 0) @@ -76508,11 +76491,11 @@ bool ComponentPeer::handleKeyUpOrDown (const bool isKeyDown) while (target != 0) { - const ComponentDeletionWatcher deletionChecker (target); + const Component::SafePointer deletionChecker (target); keyWasUsed = target->keyStateChanged (isKeyDown); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) + if (keyWasUsed || deletionChecker == 0) break; if (target->keyListeners_ != 0) @@ -76521,7 +76504,7 @@ bool ComponentPeer::handleKeyUpOrDown (const bool isKeyDown) { keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyStateChanged (isKeyDown, target); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) + if (keyWasUsed || deletionChecker == 0) return keyWasUsed; i = jmin (i, target->keyListeners_->size()); @@ -76581,7 +76564,7 @@ void ComponentPeer::handleMovedOrResized() if (component->flags.hasHeavyweightPeerFlag && ! nowMinimised) { - const ComponentDeletionWatcher deletionChecker (component); + const Component::SafePointer deletionChecker (component); const Rectangle newBounds (getBounds()); const bool wasMoved = (component->getPosition() != newBounds.getPosition()); @@ -76596,7 +76579,7 @@ void ComponentPeer::handleMovedOrResized() component->sendMovedResizedMessages (wasMoved, wasResized); - if (deletionChecker.hasBeenDeleted()) + if (deletionChecker == 0) return; } } @@ -76694,10 +76677,8 @@ void ComponentPeer::handleFileDragMove (const StringArray& files, const PointhasBeenDeleted()) - lastTarget = const_cast (dynamic_cast (dragAndDropTargetComponent->getComponent())); + FileDragAndDropTarget* lastTarget + = const_cast (dynamic_cast (static_cast (dragAndDropTargetComponent))); FileDragAndDropTarget* newTarget = 0; @@ -76717,10 +76698,8 @@ void ComponentPeer::handleFileDragMove (const StringArray& files, const Point (newTarget); - const Point pos (component->relativePositionToOtherComponent (targetComp, position)); - - dragAndDropTargetComponent = new ComponentDeletionWatcher (dynamic_cast (newTarget)); + dragAndDropTargetComponent = dynamic_cast (newTarget); + const Point pos (component->relativePositionToOtherComponent (dragAndDropTargetComponent, position)); newTarget->fileDragEnter (files, pos.getX(), pos.getY()); } } @@ -76751,9 +76730,10 @@ void ComponentPeer::handleFileDragDrop (const StringArray& files, const PointhasBeenDeleted()) + if (dragAndDropTargetComponent != 0) { - FileDragAndDropTarget* const target = const_cast (dynamic_cast (dragAndDropTargetComponent->getComponent())); + FileDragAndDropTarget* const target + = const_cast (dynamic_cast (static_cast (dragAndDropTargetComponent))); dragAndDropTargetComponent = 0; lastDragAndDropCompUnderMouse = 0; @@ -214826,7 +214806,7 @@ public: if (fullScreen != shouldBeFullScreen) { fullScreen = shouldBeFullScreen; - const ComponentDeletionWatcher deletionChecker (component); + const Component::SafePointer deletionChecker (component); if (! fullScreen) { @@ -214852,7 +214832,7 @@ public: SendMessageW (hwnd, WM_SETTINGCHANGE, 0, 0); } - if (! deletionChecker.hasBeenDeleted()) + if (deletionChecker != 0) handleMovedOrResized(); } } @@ -232007,7 +231987,7 @@ public: if (windowH != 0) { - const ComponentDeletionWatcher deletionChecker (component); + Component::SafePointer deletionChecker (component); wx = x; wy = y; @@ -232038,7 +232018,7 @@ public: wx - windowBorder.getLeft(), wy - windowBorder.getTop(), ww, wh); - if (! deletionChecker.hasBeenDeleted()) + if (deletionChecker != 0) { updateBorderSize(); handleMovedOrResized(); diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 9371453c1e..aac3030e83 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -3451,7 +3451,7 @@ public: { const ScopedLockType lock (getLock()); return (((unsigned int) index) < (unsigned int) numUsed) ? data.elements [index] - : (ObjectClass*) 0; + : static_cast (0); } inline ObjectClass* getUnchecked (const int index) const throw() @@ -3465,14 +3465,14 @@ public: { const ScopedLockType lock (getLock()); return numUsed > 0 ? data.elements [0] - : (ObjectClass*) 0; + : static_cast (0); } inline ObjectClass* getLast() const throw() { const ScopedLockType lock (getLock()); return numUsed > 0 ? data.elements [numUsed - 1] - : (ObjectClass*) 0; + : static_cast (0); } int indexOf (const ObjectClass* const objectToLookFor) const throw() @@ -9326,6 +9326,8 @@ public: virtual void componentParentHierarchyChanged (Component& component); virtual void componentNameChanged (Component& component); + + virtual void componentBeingDeleted (Component& component); }; #endif // __JUCE_COMPONENTLISTENER_JUCEHEADER__ @@ -11970,224 +11972,10 @@ private: #endif // __JUCE_BORDERSIZE_JUCEHEADER__ /*** End of inlined file: juce_BorderSize.h ***/ - -/*** Start of inlined file: juce_ComponentPeer.h ***/ -#ifndef __JUCE_COMPONENTPEER_JUCEHEADER__ -#define __JUCE_COMPONENTPEER_JUCEHEADER__ - -class Component; -class Graphics; - - -/*** Start of inlined file: juce_TextInputTarget.h ***/ -#ifndef __JUCE_TEXTINPUTTARGET_JUCEHEADER__ -#define __JUCE_TEXTINPUTTARGET_JUCEHEADER__ - -class JUCE_API TextInputTarget -{ -public: - - TextInputTarget() {} - - virtual ~TextInputTarget() {} - - virtual const Range getHighlightedRegion() const = 0; - - virtual void setHighlightedRegion (const Range& newRange) = 0; - - virtual const String getTextInRange (const Range& range) const = 0; - - virtual void insertTextAtCaret (const String& textToInsert) = 0; -}; - -#endif // __JUCE_TEXTINPUTTARGET_JUCEHEADER__ -/*** End of inlined file: juce_TextInputTarget.h ***/ - -class ComponentBoundsConstrainer; -class ComponentDeletionWatcher; - -class JUCE_API ComponentPeer -{ -public: - - enum StyleFlags - { - windowAppearsOnTaskbar = (1 << 0), /**< Indicates that the window should have a corresponding - entry on the taskbar (ignored on MacOSX) */ - windowIsTemporary = (1 << 1), /**< Indicates that the window is a temporary popup, like a menu, - tooltip, etc. */ - windowIgnoresMouseClicks = (1 << 2), /**< Indicates that the window should let mouse clicks pass - through it (may not be possible on some platforms). */ - windowHasTitleBar = (1 << 3), /**< Indicates that the window should have a normal OS-specific - title bar and frame\. if not specified, the window will be - borderless. */ - windowIsResizable = (1 << 4), /**< Indicates that the window should have a resizable border. */ - windowHasMinimiseButton = (1 << 5), /**< Indicates that if the window has a title bar, it should have a - minimise button on it. */ - windowHasMaximiseButton = (1 << 6), /**< Indicates that if the window has a title bar, it should have a - maximise button on it. */ - windowHasCloseButton = (1 << 7), /**< Indicates that if the window has a title bar, it should have a - close button on it. */ - windowHasDropShadow = (1 << 8), /**< Indicates that the window should have a drop-shadow (this may - not be possible on all platforms). */ - windowRepaintedExplictly = (1 << 9), /**< Not intended for public use - this tells a window not to - do its own repainting, but only to repaint when the - performAnyPendingRepaintsNow() method is called. */ - windowIgnoresKeyPresses = (1 << 10), /**< Tells the window not to catch any keypresses. This can - be used for things like plugin windows, to stop them interfering - with the host's shortcut keys */ - windowIsSemiTransparent = (1 << 31) /**< Not intended for public use - makes a window transparent. */ - - }; - - ComponentPeer (Component* const component, - const int styleFlags) throw(); - - virtual ~ComponentPeer(); - - Component* getComponent() const throw() { return component; } - - int getStyleFlags() const throw() { return styleFlags; } - - virtual void* getNativeHandle() const = 0; - - virtual void setVisible (bool shouldBeVisible) = 0; - - virtual void setTitle (const String& title) = 0; - - virtual void setPosition (int x, int y) = 0; - - virtual void setSize (int w, int h) = 0; - - virtual void setBounds (int x, int y, int w, int h, const bool isNowFullScreen) = 0; - - virtual const Rectangle getBounds() const = 0; - - virtual const Point getScreenPosition() const = 0; - - virtual const Point relativePositionToGlobal (const Point& relativePosition) = 0; - - virtual const Point globalPositionToRelative (const Point& screenPosition) = 0; - - virtual void setMinimised (bool shouldBeMinimised) = 0; - - virtual bool isMinimised() const = 0; - - virtual void setFullScreen (bool shouldBeFullScreen) = 0; - - virtual bool isFullScreen() const = 0; - - void setNonFullScreenBounds (const Rectangle& newBounds) throw(); - - const Rectangle& getNonFullScreenBounds() const throw(); - - virtual void setIcon (const Image& newIcon) = 0; - - void setConstrainer (ComponentBoundsConstrainer* const newConstrainer) throw(); - - ComponentBoundsConstrainer* getConstrainer() const throw() { return constrainer; } - - virtual bool contains (const Point& position, bool trueIfInAChildWindow) const = 0; - - virtual const BorderSize getFrameSize() const = 0; - - void handleMovedOrResized(); - - void handleScreenSizeChange(); - - void handlePaint (LowLevelGraphicsContext& contextToPaintTo); - - virtual bool setAlwaysOnTop (bool alwaysOnTop) = 0; - - virtual void toFront (bool makeActive) = 0; - - virtual void toBehind (ComponentPeer* other) = 0; - - void handleBroughtToFront(); - - virtual bool isFocused() const = 0; - - virtual void grabFocus() = 0; - - virtual void textInputRequired (const Point& position) = 0; - - void handleFocusGain(); - void handleFocusLoss(); - - Component* getLastFocusedSubcomponent() const throw(); - - bool handleKeyPress (const int keyCode, - const juce_wchar textCharacter); - - bool handleKeyUpOrDown (const bool isKeyDown); - - void handleModifierKeysChange(); - - TextInputTarget* findCurrentTextInputTarget(); - - virtual void repaint (int x, int y, int w, int h) = 0; - - virtual void performAnyPendingRepaintsNow() = 0; - - void handleMouseEvent (const Point& positionWithinPeer, const ModifierKeys& newMods, const int64 time); - void handleMouseWheel (const Point& positionWithinPeer, const int64 time, float x, float y); - - void handleUserClosingWindow(); - - void handleFileDragMove (const StringArray& files, const Point& position); - void handleFileDragExit (const StringArray& files); - void handleFileDragDrop (const StringArray& files, const Point& position); - - void clearMaskedRegion() throw(); - - void addMaskedRegion (int x, int y, int w, int h) throw(); - - static int getNumPeers() throw(); - - static ComponentPeer* getPeer (const int index) throw(); - - static bool isValidPeer (const ComponentPeer* const peer) throw(); - - static void bringModalComponentToFront(); - - virtual const StringArray getAvailableRenderingEngines() throw(); - virtual int getCurrentRenderingEngine() throw(); - virtual void setCurrentRenderingEngine (int index) throw(); - - juce_UseDebuggingNewOperator - -protected: - Component* const component; - const int styleFlags; - RectangleList maskedRegion; - Rectangle lastNonFullscreenBounds; - uint32 lastPaintTime; - ComponentBoundsConstrainer* constrainer; - - static void updateCurrentModifiers() throw(); - -private: - - Component* lastFocusedComponent; - ScopedPointer dragAndDropTargetComponent; - Component* lastDragAndDropCompUnderMouse; - bool fakeMouseMessageSent : 1, isWindowMinimised : 1; - - friend class Component; - static ComponentPeer* getPeerFor (const Component* const component) throw(); - - void setLastDragDropTarget (Component* comp); - - ComponentPeer (const ComponentPeer&); - ComponentPeer& operator= (const ComponentPeer&); -}; - -#endif // __JUCE_COMPONENTPEER_JUCEHEADER__ -/*** End of inlined file: juce_ComponentPeer.h ***/ - class LookAndFeel; class MouseInputSource; class MouseInputSourceInternal; +class ComponentPeer; class JUCE_API Component : public MouseListener, protected MessageListener @@ -12511,8 +12299,6 @@ public: const Point getMouseXYRelative() const; - static Component* JUCE_CALLTYPE getComponentUnderMouse() throw(); - virtual void resized(); virtual void moved(); @@ -12569,6 +12355,48 @@ public: uint32 getComponentUID() const throw() { return componentUID; } + template + class JUCE_API SafePointer : private ComponentListener + { + public: + SafePointer() : comp (0) {} + + SafePointer (ComponentType* const component) : comp (component) { attach(); } + + SafePointer (const SafePointer& other) : comp (other.comp) { attach(); } + + ~SafePointer() { detach(); } + + SafePointer& operator= (const SafePointer& other) { return operator= (other.comp); } + + SafePointer& operator= (ComponentType* const newComponent) + { + detach(); + comp = newComponent; + attach(); + return *this; + } + + operator ComponentType*() throw() { return comp; } + + operator const ComponentType*() const throw() { return comp; } + + /** Returns the component that this pointer refers to, or null if the component no longer exists. */ + ComponentType* operator->() throw() { jassert (comp != 0); return comp; } + + /** 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; } + + juce_UseDebuggingNewOperator + + private: + ComponentType* comp; + + void attach() { if (comp != 0) comp->addComponentListener (this); } + void detach() { if (comp != 0) comp->removeComponentListener (this); } + void componentBeingDeleted (Component&) { comp = 0; } + }; + juce_UseDebuggingNewOperator private: @@ -12579,7 +12407,6 @@ private: friend class MouseInputSourceInternal; static Component* currentlyFocusedComponent; - static Component* componentUnderMouse; String componentName_; Component* parentComponent_; @@ -13086,16 +12913,22 @@ public: Component* findComponentAt (const Point& screenPosition) const; + int getNumMouseSources() const throw() { return mouseSources.size(); } + + MouseInputSource* getMouseSource (int index) const throw() { return mouseSources [index]; } + + MouseInputSource& getMainMouseSource() const throw() { return *mouseSources.getUnchecked(0); } + + int getNumDraggingMouseSources() const throw(); + + MouseInputSource* getDraggingMouseSource (int index) const throw(); + juce_UseDebuggingNewOperator void refreshMonitorSizes() throw(); static bool canUseSemiTransparentWindows() throw(); - int getNumMouseInputSources() const throw() { return mouseSources.size(); } - MouseInputSource* getMouseSource (int index) const throw() { return mouseSources [index]; } - MouseInputSource& getMainMouseSource() const throw() { return *mouseSources.getUnchecked(0); } - private: static Desktop* instance; @@ -15623,39 +15456,9 @@ protected: #define __JUCE_LABEL_JUCEHEADER__ -/*** Start of inlined file: juce_ComponentDeletionWatcher.h ***/ -#ifndef __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ -#define __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ - -class JUCE_API ComponentDeletionWatcher -{ -public: - - ComponentDeletionWatcher (const Component* const componentToWatch) throw(); - - ~ComponentDeletionWatcher() throw(); - - bool hasBeenDeleted() const throw(); - - const Component* getComponent() const throw(); - - juce_UseDebuggingNewOperator - -private: - const Component* const componentToWatch; - const uint32 componentUID; - - ComponentDeletionWatcher (const ComponentDeletionWatcher&); - ComponentDeletionWatcher& operator= (const ComponentDeletionWatcher&); -}; - -#endif // __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ -/*** End of inlined file: juce_ComponentDeletionWatcher.h ***/ - - -/*** Start of inlined file: juce_TextEditor.h ***/ -#ifndef __JUCE_TEXTEDITOR_JUCEHEADER__ -#define __JUCE_TEXTEDITOR_JUCEHEADER__ +/*** Start of inlined file: juce_TextEditor.h ***/ +#ifndef __JUCE_TEXTEDITOR_JUCEHEADER__ +#define __JUCE_TEXTEDITOR_JUCEHEADER__ /*** Start of inlined file: juce_Viewport.h ***/ @@ -16303,6 +16106,31 @@ private: #endif // __JUCE_POPUPMENU_JUCEHEADER__ /*** End of inlined file: juce_PopupMenu.h ***/ + +/*** Start of inlined file: juce_TextInputTarget.h ***/ +#ifndef __JUCE_TEXTINPUTTARGET_JUCEHEADER__ +#define __JUCE_TEXTINPUTTARGET_JUCEHEADER__ + +class JUCE_API TextInputTarget +{ +public: + + TextInputTarget() {} + + virtual ~TextInputTarget() {} + + virtual const Range getHighlightedRegion() const = 0; + + virtual void setHighlightedRegion (const Range& newRange) = 0; + + virtual const String getTextInRange (const Range& range) const = 0; + + virtual void insertTextAtCaret (const String& textToInsert) = 0; +}; + +#endif // __JUCE_TEXTINPUTTARGET_JUCEHEADER__ +/*** End of inlined file: juce_TextInputTarget.h ***/ + class TextEditor; class TextHolderComponent; @@ -16663,7 +16491,7 @@ public: void attachToComponent (Component* owner, const bool onLeft); - Component* getAttachedComponent() const throw() { return ownerComponent; } + Component* getAttachedComponent() const; bool isAttachedOnLeft() const throw() { return leftOfOwnerComp; } @@ -16731,8 +16559,7 @@ private: Justification justification; ScopedPointer editor; SortedSet listeners; - Component* ownerComponent; - ScopedPointer deletionWatcher; + Component::SafePointer ownerComponent; int horizontalBorderSize, verticalBorderSize; float minimumHorizontalScale; bool editSingleClick : 1; @@ -23409,6 +23236,36 @@ private: #endif #ifndef __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ +/*** Start of inlined file: juce_ComponentDeletionWatcher.h ***/ +#ifndef __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ +#define __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ + +class JUCE_API ComponentDeletionWatcher +{ +public: + + ComponentDeletionWatcher (const Component* const componentToWatch) throw(); + + ~ComponentDeletionWatcher() throw(); + + bool hasBeenDeleted() const throw(); + + const Component* getComponent() const throw(); + + juce_UseDebuggingNewOperator + +private: + const Component* const componentToWatch; + const uint32 componentUID; + + ComponentDeletionWatcher (const ComponentDeletionWatcher&); + ComponentDeletionWatcher& operator= (const ComponentDeletionWatcher&); +}; + +#endif // __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ +/*** End of inlined file: juce_ComponentDeletionWatcher.h ***/ + + #endif #ifndef __JUCE_COMPONENTLISTENER_JUCEHEADER__ @@ -23618,14 +23475,11 @@ public: private: - Component* const component; + Component::SafePointer component; ComponentPeer* lastPeer; VoidArray registeredParentComps; bool reentrant; Rectangle lastBounds; -#ifdef JUCE_DEBUG - ScopedPointer deletionWatcher; -#endif void unregister() throw(); void registerWithParentComps() throw(); @@ -26956,6 +26810,192 @@ private: #endif #ifndef __JUCE_COMPONENTPEER_JUCEHEADER__ +/*** Start of inlined file: juce_ComponentPeer.h ***/ +#ifndef __JUCE_COMPONENTPEER_JUCEHEADER__ +#define __JUCE_COMPONENTPEER_JUCEHEADER__ + +class ComponentBoundsConstrainer; + +class JUCE_API ComponentPeer +{ +public: + + enum StyleFlags + { + windowAppearsOnTaskbar = (1 << 0), /**< Indicates that the window should have a corresponding + entry on the taskbar (ignored on MacOSX) */ + windowIsTemporary = (1 << 1), /**< Indicates that the window is a temporary popup, like a menu, + tooltip, etc. */ + windowIgnoresMouseClicks = (1 << 2), /**< Indicates that the window should let mouse clicks pass + through it (may not be possible on some platforms). */ + windowHasTitleBar = (1 << 3), /**< Indicates that the window should have a normal OS-specific + title bar and frame\. if not specified, the window will be + borderless. */ + windowIsResizable = (1 << 4), /**< Indicates that the window should have a resizable border. */ + windowHasMinimiseButton = (1 << 5), /**< Indicates that if the window has a title bar, it should have a + minimise button on it. */ + windowHasMaximiseButton = (1 << 6), /**< Indicates that if the window has a title bar, it should have a + maximise button on it. */ + windowHasCloseButton = (1 << 7), /**< Indicates that if the window has a title bar, it should have a + close button on it. */ + windowHasDropShadow = (1 << 8), /**< Indicates that the window should have a drop-shadow (this may + not be possible on all platforms). */ + windowRepaintedExplictly = (1 << 9), /**< Not intended for public use - this tells a window not to + do its own repainting, but only to repaint when the + performAnyPendingRepaintsNow() method is called. */ + windowIgnoresKeyPresses = (1 << 10), /**< Tells the window not to catch any keypresses. This can + be used for things like plugin windows, to stop them interfering + with the host's shortcut keys */ + windowIsSemiTransparent = (1 << 31) /**< Not intended for public use - makes a window transparent. */ + + }; + + ComponentPeer (Component* const component, + const int styleFlags) throw(); + + virtual ~ComponentPeer(); + + Component* getComponent() const throw() { return component; } + + int getStyleFlags() const throw() { return styleFlags; } + + virtual void* getNativeHandle() const = 0; + + virtual void setVisible (bool shouldBeVisible) = 0; + + virtual void setTitle (const String& title) = 0; + + virtual void setPosition (int x, int y) = 0; + + virtual void setSize (int w, int h) = 0; + + virtual void setBounds (int x, int y, int w, int h, const bool isNowFullScreen) = 0; + + virtual const Rectangle getBounds() const = 0; + + virtual const Point getScreenPosition() const = 0; + + virtual const Point relativePositionToGlobal (const Point& relativePosition) = 0; + + virtual const Point globalPositionToRelative (const Point& screenPosition) = 0; + + virtual void setMinimised (bool shouldBeMinimised) = 0; + + virtual bool isMinimised() const = 0; + + virtual void setFullScreen (bool shouldBeFullScreen) = 0; + + virtual bool isFullScreen() const = 0; + + void setNonFullScreenBounds (const Rectangle& newBounds) throw(); + + const Rectangle& getNonFullScreenBounds() const throw(); + + virtual void setIcon (const Image& newIcon) = 0; + + void setConstrainer (ComponentBoundsConstrainer* const newConstrainer) throw(); + + ComponentBoundsConstrainer* getConstrainer() const throw() { return constrainer; } + + virtual bool contains (const Point& position, bool trueIfInAChildWindow) const = 0; + + virtual const BorderSize getFrameSize() const = 0; + + void handleMovedOrResized(); + + void handleScreenSizeChange(); + + void handlePaint (LowLevelGraphicsContext& contextToPaintTo); + + virtual bool setAlwaysOnTop (bool alwaysOnTop) = 0; + + virtual void toFront (bool makeActive) = 0; + + virtual void toBehind (ComponentPeer* other) = 0; + + void handleBroughtToFront(); + + virtual bool isFocused() const = 0; + + virtual void grabFocus() = 0; + + virtual void textInputRequired (const Point& position) = 0; + + void handleFocusGain(); + void handleFocusLoss(); + + Component* getLastFocusedSubcomponent() const throw(); + + bool handleKeyPress (const int keyCode, + const juce_wchar textCharacter); + + bool handleKeyUpOrDown (const bool isKeyDown); + + void handleModifierKeysChange(); + + TextInputTarget* findCurrentTextInputTarget(); + + virtual void repaint (int x, int y, int w, int h) = 0; + + virtual void performAnyPendingRepaintsNow() = 0; + + void handleMouseEvent (const Point& positionWithinPeer, const ModifierKeys& newMods, const int64 time); + void handleMouseWheel (const Point& positionWithinPeer, const int64 time, float x, float y); + + void handleUserClosingWindow(); + + void handleFileDragMove (const StringArray& files, const Point& position); + void handleFileDragExit (const StringArray& files); + void handleFileDragDrop (const StringArray& files, const Point& position); + + void clearMaskedRegion() throw(); + + void addMaskedRegion (int x, int y, int w, int h) throw(); + + static int getNumPeers() throw(); + + static ComponentPeer* getPeer (const int index) throw(); + + static bool isValidPeer (const ComponentPeer* const peer) throw(); + + static void bringModalComponentToFront(); + + virtual const StringArray getAvailableRenderingEngines() throw(); + virtual int getCurrentRenderingEngine() throw(); + virtual void setCurrentRenderingEngine (int index) throw(); + + juce_UseDebuggingNewOperator + +protected: + Component* const component; + const int styleFlags; + RectangleList maskedRegion; + Rectangle lastNonFullscreenBounds; + uint32 lastPaintTime; + ComponentBoundsConstrainer* constrainer; + + static void updateCurrentModifiers() throw(); + +private: + + Component* lastFocusedComponent; + Component::SafePointer dragAndDropTargetComponent; + Component* lastDragAndDropCompUnderMouse; + bool fakeMouseMessageSent : 1, isWindowMinimised : 1; + + friend class Component; + static ComponentPeer* getPeerFor (const Component* const component) throw(); + + void setLastDragDropTarget (Component* comp); + + ComponentPeer (const ComponentPeer&); + ComponentPeer& operator= (const ComponentPeer&); +}; + +#endif // __JUCE_COMPONENTPEER_JUCEHEADER__ +/*** End of inlined file: juce_ComponentPeer.h ***/ + + #endif #ifndef __JUCE_DIALOGWINDOW_JUCEHEADER__ diff --git a/src/application/juce_ApplicationCommandManager.cpp b/src/application/juce_ApplicationCommandManager.cpp index 61f0517363..6b419d7057 100644 --- a/src/application/juce_ApplicationCommandManager.cpp +++ b/src/application/juce_ApplicationCommandManager.cpp @@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_ApplicationCommandManager.h" #include "juce_Application.h" +#include "../gui/components/windows/juce_ComponentPeer.h" #include "../gui/components/keyboard/juce_KeyPressMappingSet.h" #include "../gui/components/windows/juce_ResizableWindow.h" #include "../gui/components/juce_Desktop.h" diff --git a/src/containers/juce_OwnedArray.h b/src/containers/juce_OwnedArray.h index 21ddca4f21..ae5c34e702 100644 --- a/src/containers/juce_OwnedArray.h +++ b/src/containers/juce_OwnedArray.h @@ -111,7 +111,7 @@ public: { const ScopedLockType lock (getLock()); return (((unsigned int) index) < (unsigned int) numUsed) ? data.elements [index] - : (ObjectClass*) 0; + : static_cast (0); } /** Returns a pointer to the object at this index in the array, without checking whether the index is in-range. @@ -135,7 +135,7 @@ public: { const ScopedLockType lock (getLock()); return numUsed > 0 ? data.elements [0] - : (ObjectClass*) 0; + : static_cast (0); } /** Returns a pointer to the last object in the array. @@ -147,7 +147,7 @@ public: { const ScopedLockType lock (getLock()); return numUsed > 0 ? data.elements [numUsed - 1] - : (ObjectClass*) 0; + : static_cast (0); } //============================================================================== diff --git a/src/gui/components/buttons/juce_Button.cpp b/src/gui/components/buttons/juce_Button.cpp index 933921c478..813463ff4f 100644 --- a/src/gui/components/buttons/juce_Button.cpp +++ b/src/gui/components/buttons/juce_Button.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_Button.h" -#include "../juce_ComponentDeletionWatcher.h" #include "../keyboard/juce_KeyPressMappingSet.h" #include "../../../text/juce_LocalisedStrings.h" #include "../../../events/juce_Timer.h" @@ -145,16 +144,20 @@ void Button::setToggleState (const bool shouldBeOn, { if (shouldBeOn != lastToggleState) { - const ComponentDeletionWatcher deletionWatcher (this); - isOn = shouldBeOn; lastToggleState = shouldBeOn; repaint(); if (sendChangeNotification) + { + Component::SafePointer deletionWatcher (this); sendClickMessage (ModifierKeys()); - if ((! deletionWatcher.hasBeenDeleted()) && lastToggleState) + if (deletionWatcher == 0) + return; + } + + if (lastToggleState) turnOffOtherButtonsInGroup (sendChangeNotification); } } @@ -198,7 +201,7 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) if (p != 0 && radioGroupId != 0) { - const ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); for (int i = p->getNumChildComponents(); --i >= 0;) { @@ -212,7 +215,7 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) { b->setToggleState (false, sendChangeNotification); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; } } @@ -365,7 +368,7 @@ void Button::removeButtonListener (ButtonListener* const listener) void Button::sendClickMessage (const ModifierKeys& modifiers) { - const ComponentDeletionWatcher cdw (this); + Component::SafePointer deletionWatcher (this); if (commandManagerToUse != 0 && commandID != 0) { @@ -378,7 +381,7 @@ void Button::sendClickMessage (const ModifierKeys& modifiers) clicked (modifiers); - if (! cdw.hasBeenDeleted()) + if (deletionWatcher != 0) { for (int i = buttonListeners.size(); --i >= 0;) { @@ -388,7 +391,7 @@ void Button::sendClickMessage (const ModifierKeys& modifiers) { bl->buttonClicked (this); - if (cdw.hasBeenDeleted()) + if (deletionWatcher == 0) return; } } @@ -397,11 +400,11 @@ void Button::sendClickMessage (const ModifierKeys& modifiers) void Button::sendStateMessage() { - const ComponentDeletionWatcher cdw (this); + Component::SafePointer deletionWatcher (this); buttonStateChanged(); - if (cdw.hasBeenDeleted()) + if (deletionWatcher == 0) return; for (int i = buttonListeners.size(); --i >= 0;) @@ -412,7 +415,7 @@ void Button::sendStateMessage() { bl->buttonStateChanged (this); - if (cdw.hasBeenDeleted()) + if (deletionWatcher == 0) return; } } @@ -694,13 +697,13 @@ void Button::repeatTimerCallback() lastTimeCallbackTime = now; - const ComponentDeletionWatcher cdw (this); + Component::SafePointer deletionWatcher (this); for (int i = numTimesToCallback; --i >= 0;) { internalClickCallback (ModifierKeys::getCurrentModifiers()); - if (cdw.hasBeenDeleted() || ! isDown()) + if (deletionWatcher == 0 || ! isDown()) return; } } diff --git a/src/gui/components/buttons/juce_ToggleButton.cpp b/src/gui/components/buttons/juce_ToggleButton.cpp index 97b9bbc2d2..f4c3cb5640 100644 --- a/src/gui/components/buttons/juce_ToggleButton.cpp +++ b/src/gui/components/buttons/juce_ToggleButton.cpp @@ -29,7 +29,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_ToggleButton.h" #include "../lookandfeel/juce_LookAndFeel.h" -#include "../juce_ComponentDeletionWatcher.h" //============================================================================== diff --git a/src/gui/components/controls/juce_ComboBox.cpp b/src/gui/components/controls/juce_ComboBox.cpp index b3def530a6..5c677618a8 100644 --- a/src/gui/components/controls/juce_ComboBox.cpp +++ b/src/gui/components/controls/juce_ComboBox.cpp @@ -525,7 +525,7 @@ void ComboBox::showPopup() if (! menuActive) { const int selectedId = getSelectedId(); - ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); PopupMenu menu; @@ -553,7 +553,7 @@ void ComboBox::showPopup() const int resultId = menu.showAt (this, selectedId, getWidth(), 1, itemHeight); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; menuActive = false; diff --git a/src/gui/components/controls/juce_Label.cpp b/src/gui/components/controls/juce_Label.cpp index a0e96f2713..c33c8d7644 100644 --- a/src/gui/components/controls/juce_Label.cpp +++ b/src/gui/components/controls/juce_Label.cpp @@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_Label.h" #include "../lookandfeel/juce_LookAndFeel.h" +#include "../windows/juce_ComponentPeer.h" //============================================================================== @@ -58,7 +59,7 @@ Label::~Label() { textValue.removeListener (this); - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + if (ownerComponent != 0) ownerComponent->removeComponentListener (this); editor = 0; @@ -78,7 +79,7 @@ void Label::setText (const String& newText, textWasChanged(); - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + if (ownerComponent != 0) componentMovedOrResized (*ownerComponent, true, true); if (broadcastChangeMessage) @@ -137,21 +138,23 @@ void Label::setBorderSize (int h, int v) } //============================================================================== +Component* Label::getAttachedComponent() const +{ + return const_cast (static_cast (ownerComponent)); +} + void Label::attachToComponent (Component* owner, const bool onLeft) { - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + if (ownerComponent != 0) ownerComponent->removeComponentListener (this); - deletionWatcher = 0; ownerComponent = owner; leftOfOwnerComp = onLeft; if (ownerComponent != 0) { - deletionWatcher = new ComponentDeletionWatcher (owner); - setVisible (owner->isVisible()); ownerComponent->addComponentListener (this); componentParentHierarchyChanged (*ownerComponent); @@ -241,7 +244,7 @@ bool Label::updateFromTextEditorContents() textWasChanged(); - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + if (ownerComponent != 0) componentMovedOrResized (*ownerComponent, true, true); return true; diff --git a/src/gui/components/controls/juce_Label.h b/src/gui/components/controls/juce_Label.h index 9b15c07022..25395ca5fa 100644 --- a/src/gui/components/controls/juce_Label.h +++ b/src/gui/components/controls/juce_Label.h @@ -26,7 +26,6 @@ #ifndef __JUCE_LABEL_JUCEHEADER__ #define __JUCE_LABEL_JUCEHEADER__ -#include "../juce_ComponentDeletionWatcher.h" #include "juce_TextEditor.h" class Label; @@ -178,7 +177,7 @@ public: Returns 0 if the label is not attached. */ - Component* getAttachedComponent() const throw() { return ownerComponent; } + Component* getAttachedComponent() const; /** If the label is attached to the left of another component, this returns true. @@ -329,8 +328,7 @@ private: Justification justification; ScopedPointer editor; SortedSet listeners; - Component* ownerComponent; - ScopedPointer deletionWatcher; + Component::SafePointer ownerComponent; int horizontalBorderSize, verticalBorderSize; float minimumHorizontalScale; bool editSingleClick : 1; diff --git a/src/gui/components/controls/juce_TextEditor.cpp b/src/gui/components/controls/juce_TextEditor.cpp index 7b3d9d535b..c654174baa 100644 --- a/src/gui/components/controls/juce_TextEditor.cpp +++ b/src/gui/components/controls/juce_TextEditor.cpp @@ -28,6 +28,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_TextEditor.h" +#include "../windows/juce_ComponentPeer.h" #include "../../graphics/fonts/juce_GlyphArrangement.h" #include "../../../utilities/juce_SystemClipboard.h" #include "../../../core/juce_Time.h" @@ -2165,7 +2166,7 @@ void TextEditor::resized() void TextEditor::handleCommandMessage (const int commandId) { - const ComponentDeletionWatcher deletionChecker (this); + Component::SafePointer deletionChecker (this); for (int i = listeners.size(); --i >= 0;) { @@ -2196,7 +2197,7 @@ void TextEditor::handleCommandMessage (const int commandId) break; } - if (i > 0 && deletionChecker.hasBeenDeleted()) + if (deletionChecker == 0) return; } } diff --git a/src/gui/components/controls/juce_TreeView.cpp b/src/gui/components/controls/juce_TreeView.cpp index 2d1bcf3b60..b2b28ba45f 100644 --- a/src/gui/components/controls/juce_TreeView.cpp +++ b/src/gui/components/controls/juce_TreeView.cpp @@ -31,6 +31,7 @@ BEGIN_JUCE_NAMESPACE #include "../lookandfeel/juce_LookAndFeel.h" #include "../../../containers/juce_BitArray.h" #include "../mouse/juce_DragAndDropContainer.h" +#include "../mouse/juce_MouseInputSource.h" #include "../../graphics/imaging/juce_Image.h" @@ -168,6 +169,24 @@ public: void paint (Graphics& g); TreeViewItem* findItemAt (int y, Rectangle& itemPosition) const; + static bool isMouseDraggingInChildCompOf (Component* const comp) + { + for (int i = Desktop::getInstance().getNumMouseSources(); --i >= 0;) + { + MouseInputSource* source = Desktop::getInstance().getMouseSource(i); + + if (source->isDragging()) + { + Component* const underMouse = source->getComponentUnderMouse(); + + if (underMouse != 0 && (comp == underMouse || comp->isParentOf (underMouse))) + return true; + } + } + + return false; + } + void updateComponents() { const int visibleTop = -getY(); @@ -229,10 +248,7 @@ public: } } - if ((! keep) - && Component::isMouseButtonDownAnywhere() - && (comp == Component::getComponentUnderMouse() - || comp->isParentOf (Component::getComponentUnderMouse()))) + if ((! keep) && isMouseDraggingInChildCompOf (comp)) { keep = true; comp->setSize (0, 0); diff --git a/src/gui/components/filebrowser/juce_DirectoryContentsDisplayComponent.cpp b/src/gui/components/filebrowser/juce_DirectoryContentsDisplayComponent.cpp index c29af793e7..e2f14153bb 100644 --- a/src/gui/components/filebrowser/juce_DirectoryContentsDisplayComponent.cpp +++ b/src/gui/components/filebrowser/juce_DirectoryContentsDisplayComponent.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_DirectoryContentsDisplayComponent.h" -#include "../juce_ComponentDeletionWatcher.h" //============================================================================== @@ -61,13 +60,13 @@ void DirectoryContentsDisplayComponent::removeListener (FileBrowserListener* con void DirectoryContentsDisplayComponent::sendSelectionChangeMessage() { - const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); + Component::SafePointer deletionWatcher (dynamic_cast (this)); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->selectionChanged(); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -78,13 +77,13 @@ void DirectoryContentsDisplayComponent::sendMouseClickMessage (const File& file, { if (fileList.getDirectory().exists()) { - const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); + Component::SafePointer deletionWatcher (dynamic_cast (this)); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->fileClicked (file, e); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -96,13 +95,13 @@ void DirectoryContentsDisplayComponent::sendDoubleClickMessage (const File& file { if (fileList.getDirectory().exists()) { - const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); + Component::SafePointer deletionWatcher (dynamic_cast (this)); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->fileDoubleClicked (file); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); diff --git a/src/gui/components/filebrowser/juce_DirectoryContentsDisplayComponent.h b/src/gui/components/filebrowser/juce_DirectoryContentsDisplayComponent.h index 6ea066221c..0d44a38837 100644 --- a/src/gui/components/filebrowser/juce_DirectoryContentsDisplayComponent.h +++ b/src/gui/components/filebrowser/juce_DirectoryContentsDisplayComponent.h @@ -26,6 +26,7 @@ #ifndef __JUCE_DIRECTORYCONTENTSDISPLAYCOMPONENT_JUCEHEADER__ #define __JUCE_DIRECTORYCONTENTSDISPLAYCOMPONENT_JUCEHEADER__ +#include "../juce_Component.h" #include "juce_DirectoryContentsList.h" #include "juce_FileBrowserListener.h" diff --git a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp index 24e7d6a73d..0d247de7ac 100644 --- a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp +++ b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp @@ -302,18 +302,19 @@ void FileBrowserComponent::resized() //============================================================================== void FileBrowserComponent::sendListenerChangeMessage() { - ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); if (previewComp != 0) previewComp->selectedFileChanged (getSelectedFile (0)); - jassert (! deletionWatcher.hasBeenDeleted()); + // You shouldn't delete the browser when the file gets changed! + jassert (deletionWatcher != 0); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->selectionChanged(); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -350,13 +351,13 @@ void FileBrowserComponent::selectionChanged() void FileBrowserComponent::fileClicked (const File& f, const MouseEvent& e) { - ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->fileClicked (f, e); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); @@ -371,13 +372,13 @@ void FileBrowserComponent::fileDoubleClicked (const File& f) } else { - ComponentDeletionWatcher deletionWatcher (this); + Component::SafePointer deletionWatcher (this); for (int i = listeners.size(); --i >= 0;) { ((FileBrowserListener*) listeners.getUnchecked (i))->fileDoubleClicked (f); - if (deletionWatcher.hasBeenDeleted()) + if (deletionWatcher == 0) return; i = jmin (i, listeners.size() - 1); diff --git a/src/gui/components/filebrowser/juce_FileChooser.cpp b/src/gui/components/filebrowser/juce_FileChooser.cpp index 87d670027b..47d1ab5c56 100644 --- a/src/gui/components/filebrowser/juce_FileChooser.cpp +++ b/src/gui/components/filebrowser/juce_FileChooser.cpp @@ -102,11 +102,7 @@ bool FileChooser::showDialog (const bool selectsDirectories, const bool selectMultipleFiles, FilePreviewComponent* const previewComponent) { - ScopedPointer currentlyFocusedChecker; - Component* const currentlyFocused = Component::getCurrentlyFocusedComponent(); - - if (currentlyFocused != 0) - currentlyFocusedChecker = new ComponentDeletionWatcher (currentlyFocused); + Component::SafePointer previouslyFocused (Component::getCurrentlyFocusedComponent()); results.clear(); @@ -160,8 +156,8 @@ bool FileChooser::showDialog (const bool selectsDirectories, } } - if (currentlyFocused != 0 && ! currentlyFocusedChecker->hasBeenDeleted()) - currentlyFocused->grabKeyboardFocus(); + if (previouslyFocused != 0) + previouslyFocused->grabKeyboardFocus(); return results.size() > 0; } diff --git a/src/gui/components/juce_Component.cpp b/src/gui/components/juce_Component.cpp index ddbf55a402..167f47760c 100644 --- a/src/gui/components/juce_Component.cpp +++ b/src/gui/components/juce_Component.cpp @@ -30,6 +30,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_Component.h" #include "juce_ComponentDeletionWatcher.h" #include "juce_Desktop.h" +#include "windows/juce_ComponentPeer.h" #include "keyboard/juce_KeyListener.h" #include "lookandfeel/juce_LookAndFeel.h" #include "../../application/juce_Application.h" @@ -44,7 +45,6 @@ BEGIN_JUCE_NAMESPACE #include "mouse/juce_MouseInputSource.h" //============================================================================== -Component* Component::componentUnderMouse = 0; Component* Component::currentlyFocusedComponent = 0; static Array modalComponentStack, modalComponentReturnValueKeys; @@ -92,6 +92,17 @@ Component::Component (const String& name) throw() Component::~Component() { + if (componentListeners_ != 0) + { + for (int i = componentListeners_->size(); --i >= 0;) + { + ((ComponentListener*) componentListeners_->getUnchecked (i)) + ->componentBeingDeleted (*this); + + i = jmin (i, componentListeners_->size()); + } + } + if (parentComponent_ != 0) { parentComponent_->removeChildComponent (this); @@ -102,9 +113,6 @@ Component::~Component() giveAwayFocus(); } - if (componentUnderMouse == this) - componentUnderMouse = 0; - if (flags.hasHeavyweightPeerFlag) removeFromDesktop(); @@ -141,14 +149,14 @@ void Component::setName (const String& name) if (componentListeners_ != 0) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); for (int i = componentListeners_->size(); --i >= 0;) { ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentNameChanged (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -166,7 +174,7 @@ void Component::setVisible (bool shouldBeVisible) // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. checkMessageManagerIsLocked - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); flags.visibleFlag = shouldBeVisible; @@ -188,7 +196,7 @@ void Component::setVisible (bool shouldBeVisible) sendVisibilityChangeMessage(); - if ((! deletionChecker.hasBeenDeleted()) && flags.hasHeavyweightPeerFlag) + if (safePointer != 0 && flags.hasHeavyweightPeerFlag) { ComponentPeer* const peer = getPeer(); @@ -208,18 +216,18 @@ void Component::visibilityChanged() void Component::sendVisibilityChangeMessage() { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); visibilityChanged(); - if ((! deletionChecker.hasBeenDeleted()) && componentListeners_ != 0) + if (safePointer != 0 && componentListeners_ != 0) { for (int i = componentListeners_->size(); --i >= 0;) { ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentVisibilityChanged (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -398,7 +406,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) if (styleWanted != currentStyleFlags || ! flags.hasHeavyweightPeerFlag) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); #if JUCE_LINUX // it's wise to give the component a non-zero size before @@ -430,7 +438,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) if (parentComponent_ != 0) parentComponent_->removeChildComponent (this); - if (! deletionChecker.hasBeenDeleted()) + if (safePointer != 0) { flags.hasHeavyweightPeerFlag = true; @@ -900,14 +908,14 @@ void Component::sendMovedResizedMessages (const bool wasMoved, const bool wasRes if (componentListeners_ != 0) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); for (int i = componentListeners_->size(); --i >= 0;) { ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentMovedOrResized (*this, wasMoved, wasResized); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -1302,14 +1310,14 @@ void Component::childrenChanged() void Component::internalChildrenChanged() { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); const bool hasListeners = componentListeners_ != 0; childrenChanged(); if (hasListeners) { - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; for (int i = componentListeners_->size(); --i >= 0;) @@ -1317,7 +1325,7 @@ void Component::internalChildrenChanged() ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentChildrenChanged (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -1329,7 +1337,7 @@ void Component::internalHierarchyChanged() { parentHierarchyChanged(); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (componentListeners_ != 0) { @@ -1338,7 +1346,7 @@ void Component::internalHierarchyChanged() ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentParentHierarchyChanged (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -1351,8 +1359,8 @@ void Component::internalHierarchyChanged() // you really shouldn't delete the parent component during a callback telling you // that it's changed.. - jassert (! deletionChecker.hasBeenDeleted()); - if (deletionChecker.hasBeenDeleted()) + jassert (safePointer != 0); + if (safePointer == 0) return; i = jmin (i, childComponentList_.size()); @@ -1375,11 +1383,7 @@ int Component::runModalLoop() ->callFunctionOnMessageThread (&runModalLoopCallback, (void*) this); } - Component* const prevFocused = getCurrentlyFocusedComponent(); - - ScopedPointer deletionChecker; - if (prevFocused != 0) - deletionChecker = new ComponentDeletionWatcher (prevFocused); + SafePointer prevFocused (getCurrentlyFocusedComponent()); if (! isCurrentlyModal()) enterModalState(); @@ -1420,7 +1424,7 @@ int Component::runModalLoop() modalComponentStack.removeValue (this); - if (deletionChecker != 0 && ! deletionChecker->hasBeenDeleted()) + if (prevFocused != 0) prevFocused->grabKeyboardFocus(); return returnValue; @@ -1824,13 +1828,13 @@ void Component::sendLookAndFeelChange() // during the lookAndFeelChanged() callback) jassert (isValidComponent()); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); for (int i = childComponentList_.size(); --i >= 0;) { childComponentList_.getUnchecked (i)->sendLookAndFeelChange(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, childComponentList_.size()); @@ -2206,7 +2210,7 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& flags.mouseOverFlag = true; flags.draggingFlag = false; - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (flags.repaintOnMouseActivityFlag) repaint(); @@ -2217,7 +2221,7 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& mouseEnter (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; Desktop::getInstance().resetTimer(); @@ -2226,7 +2230,7 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& { ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseEnter (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, Desktop::getInstance().mouseListeners.size()); @@ -2238,24 +2242,24 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& { ((MouseListener*) mouseListeners_->getUnchecked(i))->mouseEnter (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked(i)))->mouseEnter (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -2268,13 +2272,13 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& void Component::internalMouseExit (MouseInputSource& source, const Point& relativePos, const Time& time) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (flags.draggingFlag) { internalMouseUp (source, relativePos, time, source.getCurrentModifiers().getRawFlags()); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; } @@ -2292,7 +2296,7 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r time, 0, false); mouseExit (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; Desktop::getInstance().resetTimer(); @@ -2301,7 +2305,7 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r { ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseExit (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, Desktop::getInstance().mouseListeners.size()); @@ -2313,24 +2317,24 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseExit (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseExit (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -2360,7 +2364,7 @@ public: Desktop& desktop = Desktop::getInstance(); int numMiceDown = 0; - for (int i = desktop.getNumMouseInputSources(); --i >= 0;) + for (int i = desktop.getNumMouseSources(); --i >= 0;) { MouseInputSource* const source = desktop.getMouseSource(i); if (source->isDragging()) @@ -2402,13 +2406,13 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r { Desktop& desktop = Desktop::getInstance(); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (isCurrentlyBlockedByAnotherModalComponent()) { internalModalInputAttempt(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; // If processing the input attempt has exited the modal loop, we'll allow the event @@ -2426,7 +2430,7 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r { ((MouseListener*) desktop.mouseListeners[i])->mouseDown (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -2445,7 +2449,7 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r { c->toFront (true); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; } @@ -2454,67 +2458,69 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r } if (! flags.dontFocusOnMouseClickFlag) + { grabFocusInternal (focusChangedByMouseClick); - if (! deletionChecker.hasBeenDeleted()) - { - flags.draggingFlag = true; - flags.mouseOverFlag = true; + if (safePointer == 0) + return; + } - if (flags.repaintOnMouseActivityFlag) - repaint(); + flags.draggingFlag = true; + flags.mouseOverFlag = true; - const MouseEvent me (source, relativePos, source.getCurrentModifiers(), - this, time, relativePos, time, - source.getNumberOfMultipleClicks(), false); - mouseDown (me); + if (flags.repaintOnMouseActivityFlag) + repaint(); - if (deletionChecker.hasBeenDeleted()) - return; + const MouseEvent me (source, relativePos, source.getCurrentModifiers(), + this, time, relativePos, time, + source.getNumberOfMultipleClicks(), false); + mouseDown (me); - desktop.resetTimer(); + if (safePointer == 0) + return; - for (int i = desktop.mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) desktop.mouseListeners[i])->mouseDown (me); + desktop.resetTimer(); - if (deletionChecker.hasBeenDeleted()) - return; + for (int i = desktop.mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) desktop.mouseListeners[i])->mouseDown (me); - i = jmin (i, desktop.mouseListeners.size()); - } + if (safePointer == 0) + return; - if (mouseListeners_ != 0) + i = jmin (i, desktop.mouseListeners.size()); + } + + if (mouseListeners_ != 0) + { + for (int i = mouseListeners_->size(); --i >= 0;) { - for (int i = mouseListeners_->size(); --i >= 0;) - { - ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDown (me); + ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDown (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (safePointer == 0) + return; - i = jmin (i, mouseListeners_->size()); - } + i = jmin (i, mouseListeners_->size()); } + } - const Component* p = parentComponent_; - - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + Component* p = parentComponent_; - for (int i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDown (me); + while (p != 0) + { + SafePointer parentPointer (p); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + for (int i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDown (me); - i = jmin (i, p->numDeepMouseListeners); - } + if (safePointer == 0 || parentPointer == 0) + return; - p = p->parentComponent_; + i = jmin (i, p->numDeepMouseListeners); } + + p = p->parentComponent_; } } @@ -2527,7 +2533,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel flags.draggingFlag = false; - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (flags.repaintOnMouseActivityFlag) repaint(); @@ -2541,7 +2547,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel mouseUp (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; desktop.resetTimer(); @@ -2550,7 +2556,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel { ((MouseListener*) desktop.mouseListeners[i])->mouseUp (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -2562,7 +2568,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseUp (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); @@ -2570,17 +2576,17 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel } { - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseUp (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -2602,7 +2608,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel { ((MouseListener*) desktop.mouseListeners[i])->mouseDoubleClick (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -2610,7 +2616,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel for (i = numListeners; --i >= 0;) { - if (deletionChecker.hasBeenDeleted() || mouseListeners_ == 0) + if (safePointer == 0 || mouseListeners_ == 0) return; MouseListener* const ml = (MouseListener*)((*mouseListeners_)[i]); @@ -2618,20 +2624,20 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel ml->mouseDoubleClick (me); } - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDoubleClick (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -2651,7 +2657,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r flags.mouseOverFlag = reallyContains (relativePos.getX(), relativePos.getY(), false); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); const MouseEvent me (source, relativePos, source.getCurrentModifiers(), this, time, @@ -2662,7 +2668,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r mouseDrag (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; desktop.resetTimer(); @@ -2671,7 +2677,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r { ((MouseListener*) desktop.mouseListeners[i])->mouseDrag (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -2683,24 +2689,24 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDrag (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDrag (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -2713,7 +2719,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r void Component::internalMouseMove (MouseInputSource& source, const Point& relativePos, const Time& time) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); if (isValidComponent()) { @@ -2734,7 +2740,7 @@ void Component::internalMouseMove (MouseInputSource& source, const Point& r mouseMove (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; desktop.resetTimer(); @@ -2743,7 +2749,7 @@ void Component::internalMouseMove (MouseInputSource& source, const Point& r { ((MouseListener*) desktop.mouseListeners[i])->mouseMove (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -2755,24 +2761,24 @@ void Component::internalMouseMove (MouseInputSource& source, const Point& r { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseMove (me); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseMove (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -2788,7 +2794,7 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point& const Time& time, const float amountX, const float amountY) { Desktop& desktop = Desktop::getInstance(); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); const float wheelIncrementX = amountX * (1.0f / 256.0f); const float wheelIncrementY = amountY * (1.0f / 256.0f); @@ -2803,7 +2809,7 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point& { ((MouseListener*) desktop.mouseListeners[i])->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -2813,14 +2819,14 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point& { mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; for (int i = desktop.mouseListeners.size(); --i >= 0;) { ((MouseListener*) desktop.mouseListeners[i])->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, desktop.mouseListeners.size()); @@ -2832,24 +2838,24 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point& { ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, mouseListeners_->size()); } } - const Component* p = parentComponent_; + Component* p = parentComponent_; while (p != 0) { - const ComponentDeletionWatcher parentDeletionChecker (p); + SafePointer parentPointer (p); for (int i = p->numDeepMouseListeners; --i >= 0;) { ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + if (safePointer == 0 || parentPointer == 0) return; i = jmin (i, p->numDeepMouseListeners); @@ -2876,10 +2882,10 @@ void Component::internalBroughtToFront() if (flags.hasHeavyweightPeerFlag) Desktop::getInstance().componentBroughtToFront (this); - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); broughtToFront(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; if (componentListeners_ != 0) @@ -2889,7 +2895,7 @@ void Component::internalBroughtToFront() ((ComponentListener*) componentListeners_->getUnchecked (i)) ->componentBroughtToFront (*this); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; i = jmin (i, componentListeners_->size()); @@ -2913,11 +2919,11 @@ void Component::focusGained (FocusChangeType) void Component::internalFocusGain (const FocusChangeType cause) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); focusGained (cause); - if (! deletionChecker.hasBeenDeleted()) + if (safePointer != 0) internalChildFocusChange (cause); } @@ -2928,11 +2934,11 @@ void Component::focusLost (FocusChangeType) void Component::internalFocusLoss (const FocusChangeType cause) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); focusLost (focusChangedDirectly); - if (! deletionChecker.hasBeenDeleted()) + if (safePointer != 0) internalChildFocusChange (cause); } @@ -2949,10 +2955,10 @@ void Component::internalChildFocusChange (FocusChangeType cause) { flags.childCompFocusedFlag = childIsNowFocused; - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); focusOfChildComponentChanged (cause); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; } @@ -2982,11 +2988,11 @@ void Component::setEnabled (const bool shouldBeEnabled) void Component::sendEnablementChangeMessage() { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); enablementChanged(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; for (int i = getNumChildComponents(); --i >= 0;) @@ -2997,7 +3003,7 @@ void Component::sendEnablementChangeMessage() { c->sendEnablementChangeMessage(); - if (deletionChecker.hasBeenDeleted()) + if (safePointer == 0) return; } } @@ -3068,7 +3074,7 @@ void Component::takeKeyboardFocus (const FocusChangeType cause) if (peer != 0) { - const ComponentDeletionWatcher deletionChecker (this); + SafePointer safePointer (this); peer->grabFocus(); @@ -3089,7 +3095,7 @@ void Component::takeKeyboardFocus (const FocusChangeType cause) { focusGained (cause); - if (! deletionChecker.hasBeenDeleted()) + if (safePointer != 0) internalChildFocusChange (cause); } } @@ -3184,11 +3190,10 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) { if (nextComp->isCurrentlyBlockedByAnotherModalComponent()) { - const ComponentDeletionWatcher deletionChecker (nextComp); + SafePointer safePointer (this); internalModalInputAttempt(); - if (deletionChecker.hasBeenDeleted() - || nextComp->isCurrentlyBlockedByAnotherModalComponent()) + if (safePointer == 0 || nextComp->isCurrentlyBlockedByAnotherModalComponent()) return; } @@ -3249,11 +3254,6 @@ const Point Component::getMouseXYRelative() const return globalPositionToRelative (Desktop::getMousePosition()); } -Component* JUCE_CALLTYPE Component::getComponentUnderMouse() throw() -{ - return componentUnderMouse; -} - //============================================================================== const Rectangle Component::getParentMonitorArea() const throw() { diff --git a/src/gui/components/juce_Component.h b/src/gui/components/juce_Component.h index fe8325e929..87926e10f5 100644 --- a/src/gui/components/juce_Component.h +++ b/src/gui/components/juce_Component.h @@ -35,7 +35,6 @@ #include "../graphics/effects/juce_ImageEffectFilter.h" #include "../graphics/geometry/juce_RectangleList.h" #include "../graphics/geometry/juce_BorderSize.h" -#include "windows/juce_ComponentPeer.h" #include "../../events/juce_MessageListener.h" #include "../../text/juce_StringArray.h" #include "../../containers/juce_VoidArray.h" @@ -43,7 +42,7 @@ class LookAndFeel; class MouseInputSource; class MouseInputSourceInternal; - +class ComponentPeer; //============================================================================== /** @@ -1602,13 +1601,6 @@ public: */ const Point getMouseXYRelative() const; - /** Returns the component that's currently underneath the mouse. - - @returns the component or 0 if there isn't one. - @see contains, getComponentAt - */ - static Component* JUCE_CALLTYPE getComponentUnderMouse() throw(); - //============================================================================== /** Called when this component's size has been changed. @@ -1896,6 +1888,71 @@ public: */ uint32 getComponentUID() const throw() { return componentUID; } + //============================================================================== + /** Holds a pointer to some type of Component, which automatically becomes null if + the component is deleted. + + If you're using a component which may be deleted by another event that's outside + of your control, use a SafePointer instead of a normal pointer to refer to it, + and you can test whether it's null before using it to see if something has deleted + it. + + 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. + */ + template + class JUCE_API SafePointer : private ComponentListener + { + public: + /** Creates a null SafePointer. */ + SafePointer() : comp (0) {} + + /** Creates a SafePointer that points at the given component. */ + SafePointer (ComponentType* const component) : comp (component) { attach(); } + + /** Creates a copy of another SafePointer. */ + SafePointer (const SafePointer& other) : comp (other.comp) { attach(); } + + /** Destructor. */ + ~SafePointer() { detach(); } + + /** Copies another pointer to this one. */ + SafePointer& operator= (const SafePointer& other) { return operator= (other.comp); } + + /** Copies another pointer to this one. */ + SafePointer& operator= (ComponentType* const newComponent) + { + detach(); + comp = newComponent; + attach(); + return *this; + } + + /** Returns the component that this pointer refers to, or null if the component no longer exists. */ + operator ComponentType*() throw() { return comp; } + + /** Returns the component that this pointer refers to, or null if the component no longer exists. */ + operator const ComponentType*() const throw() { return comp; } + + /** Returns the component that this pointer refers to, or null if the component no longer exists. */ + ComponentType* operator->() throw() { jassert (comp != 0); return comp; } + + /** 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; } + + //============================================================================== + juce_UseDebuggingNewOperator + + private: + ComponentType* comp; + + void attach() { if (comp != 0) comp->addComponentListener (this); } + void detach() { if (comp != 0) comp->removeComponentListener (this); } + void componentBeingDeleted (Component&) { comp = 0; } + }; + //============================================================================== juce_UseDebuggingNewOperator @@ -1907,7 +1964,6 @@ private: friend class MouseInputSourceInternal; static Component* currentlyFocusedComponent; - static Component* componentUnderMouse; //============================================================================== String componentName_; diff --git a/src/gui/components/juce_ComponentListener.cpp b/src/gui/components/juce_ComponentListener.cpp index bae53f5c5d..1c29e383dd 100644 --- a/src/gui/components/juce_ComponentListener.cpp +++ b/src/gui/components/juce_ComponentListener.cpp @@ -27,33 +27,15 @@ BEGIN_JUCE_NAMESPACE - #include "juce_ComponentListener.h" - //============================================================================== -void ComponentListener::componentMovedOrResized (Component&, bool, bool) -{ -} - -void ComponentListener::componentBroughtToFront (Component&) -{ -} - -void ComponentListener::componentVisibilityChanged (Component&) -{ -} - -void ComponentListener::componentChildrenChanged (Component&) -{ -} - -void ComponentListener::componentParentHierarchyChanged (Component&) -{ -} - -void ComponentListener::componentNameChanged (Component&) -{ -} +void ComponentListener::componentMovedOrResized (Component&, bool, bool) {} +void ComponentListener::componentBroughtToFront (Component&) {} +void ComponentListener::componentVisibilityChanged (Component&) {} +void ComponentListener::componentChildrenChanged (Component&) {} +void ComponentListener::componentParentHierarchyChanged (Component&) {} +void ComponentListener::componentNameChanged (Component&) {} +void ComponentListener::componentBeingDeleted (Component& component) {} END_JUCE_NAMESPACE diff --git a/src/gui/components/juce_ComponentListener.h b/src/gui/components/juce_ComponentListener.h index 24c8dbcb11..2b3443adf1 100644 --- a/src/gui/components/juce_ComponentListener.h +++ b/src/gui/components/juce_ComponentListener.h @@ -95,6 +95,16 @@ public: @see Component::setName, Component::getName */ virtual void componentNameChanged (Component& component); + + /** Called when the component is in the process of being deleted. + + This callback is made from inside the destructor, so be very, very cautious + about what you do inside the callback. + + It will be called before the component has been removed from its parent, and + before any child components have been removed. + */ + virtual void componentBeingDeleted (Component& component); }; diff --git a/src/gui/components/juce_Desktop.cpp b/src/gui/components/juce_Desktop.cpp index 242ff4022b..419cb3e844 100644 --- a/src/gui/components/juce_Desktop.cpp +++ b/src/gui/components/juce_Desktop.cpp @@ -29,7 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_Desktop.h" -#include "juce_ComponentDeletionWatcher.h" +#include "windows/juce_ComponentPeer.h" #include "mouse/juce_MouseInputSource.h" #include "mouse/juce_MouseListener.h" #include "mouse/juce_MouseEvent.h" @@ -222,6 +222,35 @@ void Desktop::incrementMouseClickCounter() throw() ++mouseClickCounter; } +int Desktop::getNumDraggingMouseSources() const throw() +{ + int num = 0; + for (int i = mouseSources.size(); --i >= 0;) + if (mouseSources.getUnchecked(i)->isDragging()) + ++num; + + return num; +} + +MouseInputSource* Desktop::getDraggingMouseSource (int index) const throw() +{ + int num = 0; + for (int i = mouseSources.size(); --i >= 0;) + { + MouseInputSource* const mi = mouseSources.getUnchecked(i); + + if (mi->isDragging()) + { + if (index == num) + return mi; + + ++num; + } + } + + return 0; +} + //============================================================================== void Desktop::addGlobalMouseListener (MouseListener* const listener) throw() { @@ -287,7 +316,7 @@ void Desktop::sendMouseMove() if (target != 0) { - ComponentDeletionWatcher deletionChecker (target); + Component::SafePointer deletionChecker (target); const Point pos (target->globalPositionToRelative (lastFakeMouseMove)); const Time now (Time::getCurrentTime()); @@ -301,7 +330,7 @@ void Desktop::sendMouseMove() else ((MouseListener*) mouseListeners[i])->mouseMove (me); - if (deletionChecker.hasBeenDeleted()) + if (deletionChecker == 0) return; i = jmin (i, mouseListeners.size()); diff --git a/src/gui/components/juce_Desktop.h b/src/gui/components/juce_Desktop.h index 69f5309ff9..dfac048f1d 100644 --- a/src/gui/components/juce_Desktop.h +++ b/src/gui/components/juce_Desktop.h @@ -227,6 +227,41 @@ public: Component* findComponentAt (const Point& screenPosition) const; + //============================================================================== + /** Returns the number of MouseInputSource objects the system has at its disposal. + In a traditional single-mouse system, there might be only one object. On a multi-touch + system, there could be one input source per potential finger. + To find out how many mouse events are currently happening, use getNumDraggingMouseSources(). + @see getMouseSource + */ + int getNumMouseSources() const throw() { return mouseSources.size(); } + + /** Returns one of the system's MouseInputSource objects. + The index should be from 0 to getNumMouseSources() - 1. Out-of-range indexes will return + a null pointer. + In a traditional single-mouse system, there might be only one object. On a multi-touch + system, there could be one input source per potential finger. + */ + MouseInputSource* getMouseSource (int index) const throw() { return mouseSources [index]; } + + /** Returns the main mouse input device that the system is using. + @see getNumMouseSources() + */ + MouseInputSource& getMainMouseSource() const throw() { return *mouseSources.getUnchecked(0); } + + /** Returns the number of mouse-sources that are currently being dragged. + In a traditional single-mouse system, this will be 0 or 1, depending on whether a + juce component has the button down on it. In a multi-touch system, this could + be any number from 0 to the number of simultaneous touches that can be detected. + */ + int getNumDraggingMouseSources() const throw(); + + /** Returns one of the mouse sources that's currently being dragged. + The index should be between 0 and getNumDraggingMouseSources() - 1. If the index is + out of range, or if no mice or fingers are down, this will return a null pointer. + */ + MouseInputSource* getDraggingMouseSource (int index) const throw(); + //============================================================================== juce_UseDebuggingNewOperator @@ -239,10 +274,6 @@ public: /** True if the OS supports semitransparent windows */ static bool canUseSemiTransparentWindows() throw(); - int getNumMouseInputSources() const throw() { return mouseSources.size(); } - MouseInputSource* getMouseSource (int index) const throw() { return mouseSources [index]; } - MouseInputSource& getMainMouseSource() const throw() { return *mouseSources.getUnchecked(0); } - private: //============================================================================== static Desktop* instance; diff --git a/src/gui/components/layout/juce_ComponentAnimator.cpp b/src/gui/components/layout/juce_ComponentAnimator.cpp index 6742d41250..43740d71f7 100644 --- a/src/gui/components/layout/juce_ComponentAnimator.cpp +++ b/src/gui/components/layout/juce_ComponentAnimator.cpp @@ -35,13 +35,11 @@ BEGIN_JUCE_NAMESPACE struct AnimationTask { AnimationTask (Component* const comp) - : component (comp), - watcher (comp) + : component (comp) { } - Component* component; - ComponentDeletionWatcher watcher; + Component::SafePointer component; Rectangle destination; int msElapsed, msTotal; double startSpeed, midSpeed, endSpeed, lastProgress; @@ -49,7 +47,7 @@ struct AnimationTask bool useTimeslice (const int elapsed) { - if (watcher.hasBeenDeleted()) + if (component == 0) return false; msElapsed += elapsed; @@ -88,7 +86,7 @@ struct AnimationTask void moveToFinalDestination() { - if (! watcher.hasBeenDeleted()) + if (component != 0) component->setBounds (destination); } diff --git a/src/gui/components/layout/juce_ComponentAnimator.h b/src/gui/components/layout/juce_ComponentAnimator.h index fa252ab7d4..ed98ddc0b5 100644 --- a/src/gui/components/layout/juce_ComponentAnimator.h +++ b/src/gui/components/layout/juce_ComponentAnimator.h @@ -27,7 +27,6 @@ #define __JUCE_COMPONENTANIMATOR_JUCEHEADER__ #include "../juce_Component.h" -#include "../juce_ComponentDeletionWatcher.h" #include "../../../events/juce_ChangeBroadcaster.h" #include "../../../events/juce_Timer.h" diff --git a/src/gui/components/layout/juce_ComponentBoundsConstrainer.cpp b/src/gui/components/layout/juce_ComponentBoundsConstrainer.cpp index 76acf88bdd..93bdb24250 100644 --- a/src/gui/components/layout/juce_ComponentBoundsConstrainer.cpp +++ b/src/gui/components/layout/juce_ComponentBoundsConstrainer.cpp @@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_ComponentBoundsConstrainer.h" #include "../juce_Desktop.h" +#include "../windows/juce_ComponentPeer.h" //============================================================================== diff --git a/src/gui/components/layout/juce_ComponentMovementWatcher.cpp b/src/gui/components/layout/juce_ComponentMovementWatcher.cpp index 10b77fffe6..8a2806ddf6 100644 --- a/src/gui/components/layout/juce_ComponentMovementWatcher.cpp +++ b/src/gui/components/layout/juce_ComponentMovementWatcher.cpp @@ -38,10 +38,6 @@ ComponentMovementWatcher::ComponentMovementWatcher (Component* const component_) { jassert (component != 0); // can't use this with a null pointer.. -#ifdef JUCE_DEBUG - deletionWatcher = new ComponentDeletionWatcher (component_); -#endif - component->addComponentListener (this); registerWithParentComps(); @@ -57,10 +53,8 @@ ComponentMovementWatcher::~ComponentMovementWatcher() //============================================================================== void ComponentMovementWatcher::componentParentHierarchyChanged (Component&) { -#ifdef JUCE_DEBUG // agh! don't delete the target component without deleting this object first! - jassert (! deletionWatcher->hasBeenDeleted()); -#endif + jassert (component != 0); if (! reentrant) { @@ -70,11 +64,9 @@ void ComponentMovementWatcher::componentParentHierarchyChanged (Component&) if (peer != lastPeer) { - ComponentDeletionWatcher watcher (component); - componentPeerChanged(); - if (watcher.hasBeenDeleted()) + if (component == 0) return; lastPeer = peer; @@ -91,10 +83,8 @@ void ComponentMovementWatcher::componentParentHierarchyChanged (Component&) void ComponentMovementWatcher::componentMovedOrResized (Component&, bool wasMoved, bool wasResized) { -#ifdef JUCE_DEBUG // agh! don't delete the target component without deleting this object first! - jassert (! deletionWatcher->hasBeenDeleted()); -#endif + jassert (component != 0); if (wasMoved) { diff --git a/src/gui/components/layout/juce_ComponentMovementWatcher.h b/src/gui/components/layout/juce_ComponentMovementWatcher.h index 5b00690e11..fe42e9588a 100644 --- a/src/gui/components/layout/juce_ComponentMovementWatcher.h +++ b/src/gui/components/layout/juce_ComponentMovementWatcher.h @@ -27,7 +27,6 @@ #define __JUCE_COMPONENTMOVEMENTWATCHER_JUCEHEADER__ #include "../juce_Component.h" -#include "../juce_ComponentDeletionWatcher.h" //============================================================================== @@ -77,14 +76,11 @@ public: private: //============================================================================== - Component* const component; + Component::SafePointer component; ComponentPeer* lastPeer; VoidArray registeredParentComps; bool reentrant; Rectangle lastBounds; -#ifdef JUCE_DEBUG - ScopedPointer deletionWatcher; -#endif void unregister() throw(); void registerWithParentComps() throw(); diff --git a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp index 0c708bfe9e..d810d26ee9 100644 --- a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -35,6 +35,7 @@ BEGIN_JUCE_NAMESPACE #include "../buttons/juce_ImageButton.h" #include "../buttons/juce_DrawableButton.h" #include "../buttons/juce_HyperlinkButton.h" +#include "../windows/juce_ComponentPeer.h" #include "../windows/juce_AlertWindow.h" #include "../windows/juce_DocumentWindow.h" #include "../windows/juce_ResizableWindow.h" diff --git a/src/gui/components/menus/juce_MenuBarComponent.cpp b/src/gui/components/menus/juce_MenuBarComponent.cpp index c7b80b7df6..8af0d72107 100644 --- a/src/gui/components/menus/juce_MenuBarComponent.cpp +++ b/src/gui/components/menus/juce_MenuBarComponent.cpp @@ -193,13 +193,8 @@ void MenuBarComponent::showMenu (int index) currentPopup = 0; menuBarItemsChanged (0); - Component* const prevFocused = getCurrentlyFocusedComponent(); - - ScopedPointer prevCompDeletionChecker; - if (prevFocused != 0) - prevCompDeletionChecker = new ComponentDeletionWatcher (prevFocused); - - ComponentDeletionWatcher deletionChecker (this); + Component::SafePointer prevFocused (getCurrentlyFocusedComponent()); + Component::SafePointer deletionChecker (this); enterModalState (false); inModalState = true; @@ -244,7 +239,7 @@ void MenuBarComponent::showMenu (int index) // be stuck behind other comps that are already modal.. result = currentPopup->runModalLoop(); - if (deletionChecker.hasBeenDeleted()) + if (deletionChecker == 0) return; const int lastPopupIndex = currentPopupIndex; @@ -276,7 +271,7 @@ void MenuBarComponent::showMenu (int index) inModalState = false; exitModalState (0); - if (prevCompDeletionChecker != 0 && ! prevCompDeletionChecker->hasBeenDeleted()) + if (prevFocused != 0) prevFocused->grabKeyboardFocus(); const Point mousePos (getMouseXYRelative()); diff --git a/src/gui/components/menus/juce_PopupMenu.cpp b/src/gui/components/menus/juce_PopupMenu.cpp index 789b3841bf..aa7706864d 100644 --- a/src/gui/components/menus/juce_PopupMenu.cpp +++ b/src/gui/components/menus/juce_PopupMenu.cpp @@ -29,8 +29,8 @@ BEGIN_JUCE_NAMESPACE #include "juce_PopupMenu.h" #include "juce_PopupMenuCustomComponent.h" +#include "../windows/juce_ComponentPeer.h" #include "../lookandfeel/juce_LookAndFeel.h" -#include "../juce_ComponentDeletionWatcher.h" #include "../juce_Desktop.h" #include "../../graphics/imaging/juce_Image.h" #include "../keyboard/juce_KeyPressMappingSet.h" @@ -270,7 +270,6 @@ public: activeSubMenu (0), menuBarComponent (0), managerOfChosenCommand (0), - componentAttachedTo (0), minimumWidth (0), maximumNumColumns (7), standardItemHeight (0), @@ -309,7 +308,6 @@ public: activeSubMenu = 0; deleteAllChildren(); - attachedCompWatcher = 0; } //============================================================================== @@ -353,7 +351,6 @@ public: mw->menuBarComponent = menuBarComponent; mw->managerOfChosenCommand = managerOfChosenCommand; mw->componentAttachedTo = componentAttachedTo; - mw->attachedCompWatcher = componentAttachedTo != 0 ? new ComponentDeletionWatcher (componentAttachedTo) : 0; mw->calculateWindowPos (minX, maxX, minY, maxY, alignToRectangle); mw->setTopLeftPosition (mw->windowPos.getX(), @@ -562,7 +559,7 @@ public: if (! isOverAnyMenu()) { - if (componentAttachedTo != 0 && ! attachedCompWatcher->hasBeenDeleted()) + if (componentAttachedTo != 0) { // we want to dismiss the menu, but if we do it synchronously, then // the mouse-click will be allowed to pass through. That's good, except @@ -597,7 +594,7 @@ public: if (! isVisible()) return; - if (attachedCompWatcher != 0 && attachedCompWatcher->hasBeenDeleted()) + if (componentAttachedTo == 0) { dismissMenu (0); return; @@ -750,8 +747,7 @@ private: ScopedPointer activeSubMenu; Component* menuBarComponent; ApplicationCommandManager** managerOfChosenCommand; - Component* componentAttachedTo; - ScopedPointer attachedCompWatcher; + Component::SafePointer componentAttachedTo; Rectangle windowPos; Point lastMouse; int minimumWidth, maximumNumColumns, standardItemHeight; @@ -1546,16 +1542,8 @@ int PopupMenu::showMenu (const int x, const int y, const int w, const int h, const bool alignToRectangle, Component* const componentAttachedTo) { - Component* const prevFocused = Component::getCurrentlyFocusedComponent(); - - ScopedPointer deletionChecker[2]; - if (prevFocused != 0) - deletionChecker[0] = new ComponentDeletionWatcher (prevFocused); - - Component* const prevTopLevel = (prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0; - - if (prevTopLevel != 0) - deletionChecker[1] = new ComponentDeletionWatcher (prevTopLevel); + Component::SafePointer prevFocused (Component::getCurrentlyFocusedComponent()); + Component::SafePointer prevTopLevel ((prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0); Window::wasHiddenBecauseOfAppChange() = false; @@ -1582,10 +1570,10 @@ int PopupMenu::showMenu (const int x, const int y, const int w, const int h, if (! Window::wasHiddenBecauseOfAppChange()) { - if (deletionChecker[1] != 0 && ! deletionChecker[1]->hasBeenDeleted()) + if (prevTopLevel != 0) prevTopLevel->toFront (true); - if (deletionChecker[0] != 0 && ! deletionChecker[0]->hasBeenDeleted()) + if (prevFocused != 0) prevFocused->grabKeyboardFocus(); } } diff --git a/src/gui/components/mouse/juce_DragAndDropContainer.cpp b/src/gui/components/mouse/juce_DragAndDropContainer.cpp index 847b43250e..6fa145233b 100644 --- a/src/gui/components/mouse/juce_DragAndDropContainer.cpp +++ b/src/gui/components/mouse/juce_DragAndDropContainer.cpp @@ -28,12 +28,13 @@ BEGIN_JUCE_NAMESPACE #include "juce_DragAndDropContainer.h" -#include "../juce_ComponentDeletionWatcher.h" +#include "../windows/juce_ComponentPeer.h" #include "../juce_Desktop.h" #include "../../../events/juce_Timer.h" #include "../../../core/juce_Random.h" #include "../../graphics/imaging/juce_Image.h" #include "../mouse/juce_MouseEvent.h" +#include "../mouse/juce_MouseInputSource.h" #include "juce_FileDragAndDropTarget.h" bool juce_performDragDropFiles (const StringArray& files, const bool copyFiles, bool& shouldStop); @@ -47,13 +48,14 @@ class DragImageComponent : public Component, public: DragImageComponent (Image* const im, const String& desc, - Component* const s, + Component* const sourceComponent, + Component* const mouseDragSource_, DragAndDropContainer* const o, const Point& imageOffset_) : image (im), - source (s), + source (sourceComponent), + mouseDragSource (mouseDragSource_), owner (o), - currentlyOver (0), dragDesc (desc), imageOffset (imageOffset_), hasCheckedForExternalDrag (false), @@ -61,14 +63,9 @@ public: { setSize (im->getWidth(), im->getHeight()); - sourceWatcher = new ComponentDeletionWatcher (source); - - mouseDragSource = Component::getComponentUnderMouse(); - if (mouseDragSource == 0) mouseDragSource = source; - mouseDragSourceWatcher = new ComponentDeletionWatcher (mouseDragSource); mouseDragSource->addMouseListener (this, false); startTimer (200); @@ -82,13 +79,12 @@ public: if (owner->dragImageComponent == this) owner->dragImageComponent.release(); - if (! mouseDragSourceWatcher->hasBeenDeleted()) + if (mouseDragSource != 0) { mouseDragSource->removeMouseListener (this); - if (currentlyOverWatcher != 0 && ! currentlyOverWatcher->hasBeenDeleted()) - if (currentlyOver->isInterestedInDragSource (dragDesc, source)) - currentlyOver->itemDragExit (dragDesc, source); + if (getCurrentlyOver() != 0 && getCurrentlyOver()->isInterestedInDragSource (dragDesc, source)) + getCurrentlyOver()->itemDragExit (dragDesc, source); } } @@ -104,8 +100,7 @@ public: } } - DragAndDropTarget* findTarget (const Point& screenPos, - Point& relativePos) const + DragAndDropTarget* findTarget (const Point& screenPos, Point& relativePos) { Component* hit = getParentComponent(); @@ -143,7 +138,7 @@ public: { if (e.originalComponent != this) { - if (! mouseDragSourceWatcher->hasBeenDeleted()) + if (mouseDragSource != 0) mouseDragSource->removeMouseListener (this); bool dropAccepted = false; @@ -161,7 +156,7 @@ public: setVisible (true); - if (dropAccepted || sourceWatcher->hasBeenDeleted()) + if (dropAccepted || source == 0) { fadeOutComponent (120); } @@ -188,8 +183,7 @@ public: // a modal loop and deletes this object before the method completes) const String dragDescLocal (dragDesc); - currentlyOverWatcher = 0; - currentlyOver = 0; + currentlyOverComp = 0; ddt->itemDropped (dragDescLocal, source, relPos.getX(), relPos.getY()); } @@ -215,46 +209,28 @@ public: Point relPos; DragAndDropTarget* const ddt = findTarget (screenPos, relPos); + Component* ddtComp = dynamic_cast (ddt); drawImage = (ddt == 0) || ddt->shouldDrawDragImageWhenOver(); - if (ddt != currentlyOver) + if (ddtComp != currentlyOverComp) { - if (currentlyOverWatcher != 0 && ! currentlyOverWatcher->hasBeenDeleted()) + if (currentlyOverComp != 0 && source != 0 + && getCurrentlyOver()->isInterestedInDragSource (dragDescLocal, source)) { - Component* const over = dynamic_cast (currentlyOver); - - if (over != 0 - && over->isValidComponent() - && ! (sourceWatcher->hasBeenDeleted()) - && currentlyOver->isInterestedInDragSource (dragDescLocal, source)) - { - currentlyOver->itemDragExit (dragDescLocal, source); - } + getCurrentlyOver()->itemDragExit (dragDescLocal, source); } - currentlyOver = ddt; - currentlyOverWatcher = 0; + currentlyOverComp = ddtComp; - if (ddt != 0) - { - currentlyOverWatcher = new ComponentDeletionWatcher (dynamic_cast (ddt)); - - if (currentlyOver->isInterestedInDragSource (dragDescLocal, source)) - currentlyOver->itemDragEnter (dragDescLocal, source, relPos.getX(), relPos.getY()); - } - } - else if (currentlyOverWatcher != 0 && currentlyOverWatcher->hasBeenDeleted()) - { - currentlyOver = 0; - currentlyOverWatcher = 0; + if (ddt != 0 && ddt->isInterestedInDragSource (dragDescLocal, source)) + ddt->itemDragEnter (dragDescLocal, source, relPos.getX(), relPos.getY()); } - if (currentlyOver != 0 - && currentlyOver->isInterestedInDragSource (dragDescLocal, source)) - currentlyOver->itemDragMove (dragDescLocal, source, relPos.getX(), relPos.getY()); + if (getCurrentlyOver() != 0 && getCurrentlyOver()->isInterestedInDragSource (dragDescLocal, source)) + getCurrentlyOver()->itemDragMove (dragDescLocal, source, relPos.getX(), relPos.getY()); - if (currentlyOver == 0 + if (getCurrentlyOver() == 0 && canDoExternalDrag && ! hasCheckedForExternalDrag) { @@ -267,13 +243,13 @@ public: if (owner->shouldDropFilesWhenDraggedExternally (dragDescLocal, source, files, canMoveFiles) && files.size() > 0) { - ComponentDeletionWatcher cdw (this); + Component::SafePointer cdw (this); setVisible (false); if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles); - if (! cdw.hasBeenDeleted()) + if (cdw != 0) delete this; return; @@ -291,13 +267,13 @@ public: void timerCallback() { - if (sourceWatcher->hasBeenDeleted()) + if (source == 0) { delete this; } else if (! isMouseButtonDownAnywhere()) { - if (! mouseDragSourceWatcher->hasBeenDeleted()) + if (mouseDragSource != 0) mouseDragSource->removeMouseListener (this); delete this; @@ -306,12 +282,15 @@ public: private: ScopedPointer image; - Component* const source; + Component::SafePointer source; + Component::SafePointer mouseDragSource; DragAndDropContainer* const owner; - ScopedPointer sourceWatcher, mouseDragSourceWatcher, currentlyOverWatcher; - Component* mouseDragSource; - DragAndDropTarget* currentlyOver; + Component::SafePointer currentlyOverComp; + DragAndDropTarget* getCurrentlyOver() + { + return dynamic_cast (static_cast (currentlyOverComp)); + } String dragDesc; const Point imageOffset; @@ -344,90 +323,95 @@ void DragAndDropContainer::startDragging (const String& sourceDescription, { Component* const thisComp = dynamic_cast (this); - if (thisComp != 0) + if (thisComp == 0) + { + jassertfalse; // Your DragAndDropContainer needs to be a Component! + return; + } + + MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource (0); + + if (draggingSource == 0 || ! draggingSource->isDragging()) { - const Point lastMouseDown (Desktop::getLastMouseDownPosition()); - Point imageOffset; + jassertfalse; // You must call startDragging() from within a mouseDown or mouseDrag callback! + return; + } + + const Point lastMouseDown (Desktop::getLastMouseDownPosition()); + Point imageOffset; - if (dragImage == 0) + if (dragImage == 0) + { + dragImage = sourceComponent->createComponentSnapshot (Rectangle (0, 0, sourceComponent->getWidth(), sourceComponent->getHeight())); + + if (dragImage->getFormat() != Image::ARGB) { - dragImage = sourceComponent->createComponentSnapshot (Rectangle (0, 0, sourceComponent->getWidth(), sourceComponent->getHeight())); + Image* newIm = Image::createNativeImage (Image::ARGB, dragImage->getWidth(), dragImage->getHeight(), true); + Graphics g2 (*newIm); + g2.drawImageAt (dragImage, 0, 0); - if (dragImage->getFormat() != Image::ARGB) - { - Image* newIm = Image::createNativeImage (Image::ARGB, dragImage->getWidth(), dragImage->getHeight(), true); - Graphics g2 (*newIm); - g2.drawImageAt (dragImage, 0, 0); + dragImage = newIm; + } - dragImage = newIm; - } + dragImage->multiplyAllAlphas (0.6f); - dragImage->multiplyAllAlphas (0.6f); + const int lo = 150; + const int hi = 400; - const int lo = 150; - const int hi = 400; + Point relPos (sourceComponent->globalPositionToRelative (lastMouseDown)); + Point clipped (Rectangle (0, 0, dragImage->getWidth(), dragImage->getHeight()) + .getConstrainedPoint (relPos)); - Point relPos (sourceComponent->globalPositionToRelative (lastMouseDown)); - Point clipped (Rectangle (0, 0, dragImage->getWidth(), dragImage->getHeight()) - .getConstrainedPoint (relPos)); + for (int y = dragImage->getHeight(); --y >= 0;) + { + const double dy = (y - clipped.getY()) * (y - clipped.getY()); - for (int y = dragImage->getHeight(); --y >= 0;) + for (int x = dragImage->getWidth(); --x >= 0;) { - const double dy = (y - clipped.getY()) * (y - clipped.getY()); + const int dx = x - clipped.getX(); + const int distance = roundToInt (sqrt (dx * dx + dy)); - for (int x = dragImage->getWidth(); --x >= 0;) + if (distance > lo) { - const int dx = x - clipped.getX(); - const int distance = roundToInt (sqrt (dx * dx + dy)); + const float alpha = (distance > hi) ? 0 + : (hi - distance) / (float) (hi - lo) + + Random::getSystemRandom().nextFloat() * 0.008f; - if (distance > lo) - { - const float alpha = (distance > hi) ? 0 - : (hi - distance) / (float) (hi - lo) - + Random::getSystemRandom().nextFloat() * 0.008f; - - dragImage->multiplyAlphaAt (x, y, alpha); - } + dragImage->multiplyAlphaAt (x, y, alpha); } } - - imageOffset = -clipped; - } - else - { - if (imageOffsetFromMouse == 0) - imageOffset = Point (dragImage->getWidth() / -2, - dragImage->getHeight() / -2); - else - imageOffset = *imageOffsetFromMouse; } - dragImageComponent = new DragImageComponent (dragImage.release(), sourceDescription, sourceComponent, - this, imageOffset); + imageOffset = -clipped; + } + else + { + if (imageOffsetFromMouse == 0) + imageOffset = Point (dragImage->getWidth() / -2, + dragImage->getHeight() / -2); + else + imageOffset = *imageOffsetFromMouse; + } - currentDragDesc = sourceDescription; + dragImageComponent = new DragImageComponent (dragImage.release(), sourceDescription, sourceComponent, + draggingSource->getComponentUnderMouse(), this, imageOffset); - if (allowDraggingToExternalWindows) - { - if (! Desktop::canUseSemiTransparentWindows()) - dragImageComponent->setOpaque (true); + currentDragDesc = sourceDescription; - dragImageComponent->addToDesktop (ComponentPeer::windowIgnoresMouseClicks - | ComponentPeer::windowIsTemporary - | ComponentPeer::windowIgnoresKeyPresses); - } - else - thisComp->addChildComponent (dragImageComponent); + if (allowDraggingToExternalWindows) + { + if (! Desktop::canUseSemiTransparentWindows()) + dragImageComponent->setOpaque (true); - static_cast (static_cast (dragImageComponent))->updateLocation (false, lastMouseDown); - dragImageComponent->setVisible (true); + dragImageComponent->addToDesktop (ComponentPeer::windowIgnoresMouseClicks + | ComponentPeer::windowIsTemporary + | ComponentPeer::windowIgnoresKeyPresses); } else - { - // this class must only be implemented by an object that - // is also a Component. - jassertfalse - } + thisComp->addChildComponent (dragImageComponent); + + static_cast (static_cast (dragImageComponent))->updateLocation (false, lastMouseDown); + dragImageComponent->setVisible (true); } } diff --git a/src/gui/components/mouse/juce_MouseInputSource.cpp b/src/gui/components/mouse/juce_MouseInputSource.cpp index 347910d2e9..6c4a6b762e 100644 --- a/src/gui/components/mouse/juce_MouseInputSource.cpp +++ b/src/gui/components/mouse/juce_MouseInputSource.cpp @@ -30,9 +30,9 @@ BEGIN_JUCE_NAMESPACE #include "juce_MouseInputSource.h" #include "juce_MouseEvent.h" #include "../juce_Component.h" -#include "../juce_ComponentDeletionWatcher.h" #include "../../../events/juce_AsyncUpdater.h" #include "../lookandfeel/juce_LookAndFeel.h" +#include "../windows/juce_ComponentPeer.h" //============================================================================== @@ -59,7 +59,7 @@ public: Component* getComponentUnderMouse() const { - return componentUnderMouse != 0 ? const_cast (componentUnderMouse->getComponent()) : 0; + return const_cast (static_cast (componentUnderMouse)); } const ModifierKeys getCurrentModifiers() const @@ -144,7 +144,7 @@ public: if (newComponent != current) { - ScopedPointer newCompWatcher (newComponent != 0 ? new ComponentDeletionWatcher (newComponent) : 0); + Component::SafePointer safeNewComp (newComponent); const ModifierKeys originalButtonState (buttonState); if (current != 0) @@ -154,9 +154,8 @@ public: buttonState = originalButtonState; } - componentUnderMouse = newCompWatcher; + componentUnderMouse = safeNewComp; current = getComponentUnderMouse(); - Component::componentUnderMouse = current; if (current != 0) current->internalMouseEnter (source, current->globalPositionToRelative (screenPos), time); @@ -406,7 +405,7 @@ public: private: MouseInputSource& source; - ScopedPointer componentUnderMouse; + Component::SafePointer componentUnderMouse; ComponentPeer* lastPeer; Point unboundedMouseOffset; diff --git a/src/gui/components/special/juce_DropShadower.cpp b/src/gui/components/special/juce_DropShadower.cpp index 7a51284db2..80a51bbcdb 100644 --- a/src/gui/components/special/juce_DropShadower.cpp +++ b/src/gui/components/special/juce_DropShadower.cpp @@ -31,8 +31,8 @@ BEGIN_JUCE_NAMESPACE #include "../../graphics/imaging/juce_ImageCache.h" #include "../../graphics/imaging/juce_ImageConvolutionKernel.h" #include "../../graphics/imaging/juce_Image.h" -#include "../juce_ComponentDeletionWatcher.h" #include "../juce_Desktop.h" +#include "../windows/juce_ComponentPeer.h" //============================================================================== diff --git a/src/gui/components/special/juce_MagnifierComponent.cpp b/src/gui/components/special/juce_MagnifierComponent.cpp index 78a120c513..7bc4dd9d44 100644 --- a/src/gui/components/special/juce_MagnifierComponent.cpp +++ b/src/gui/components/special/juce_MagnifierComponent.cpp @@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_MagnifierComponent.h" #include "../../graphics/imaging/juce_Image.h" +#include "../windows/juce_ComponentPeer.h" //============================================================================== diff --git a/src/gui/components/special/juce_OpenGLComponent.cpp b/src/gui/components/special/juce_OpenGLComponent.cpp index cdb12056f4..a8fda1cba6 100644 --- a/src/gui/components/special/juce_OpenGLComponent.cpp +++ b/src/gui/components/special/juce_OpenGLComponent.cpp @@ -30,6 +30,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_OpenGLComponent.h" +#include "../windows/juce_ComponentPeer.h" #include "../layout/juce_ComponentMovementWatcher.h" #include "../../../threads/juce_ScopedLock.h" diff --git a/src/gui/components/windows/juce_AlertWindow.cpp b/src/gui/components/windows/juce_AlertWindow.cpp index 6051121f07..1e172051aa 100644 --- a/src/gui/components/windows/juce_AlertWindow.cpp +++ b/src/gui/components/windows/juce_AlertWindow.cpp @@ -28,6 +28,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_AlertWindow.h" +#include "../windows/juce_ComponentPeer.h" #include "../lookandfeel/juce_LookAndFeel.h" #include "../buttons/juce_TextButton.h" #include "../controls/juce_TextEditor.h" diff --git a/src/gui/components/windows/juce_ComponentPeer.cpp b/src/gui/components/windows/juce_ComponentPeer.cpp index e51669a6f4..b35aad0bd8 100644 --- a/src/gui/components/windows/juce_ComponentPeer.cpp +++ b/src/gui/components/windows/juce_ComponentPeer.cpp @@ -27,9 +27,8 @@ BEGIN_JUCE_NAMESPACE +#include "juce_ComponentPeer.h" #include "../../../application/juce_Application.h" -#include "../juce_Component.h" -#include "../juce_ComponentDeletionWatcher.h" #include "../juce_Desktop.h" #include "../../../events/juce_MessageManager.h" #include "../../../core/juce_Time.h" @@ -167,7 +166,7 @@ bool ComponentPeer::handleKeyPress (const int keyCode, while (target != 0) { - const ComponentDeletionWatcher deletionChecker (target); + const Component::SafePointer deletionChecker (target); if (target->keyListeners_ != 0) { @@ -175,7 +174,7 @@ bool ComponentPeer::handleKeyPress (const int keyCode, { keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyPressed (keyInfo, target); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) + if (keyWasUsed || deletionChecker == 0) return keyWasUsed; i = jmin (i, target->keyListeners_->size()); @@ -184,7 +183,7 @@ bool ComponentPeer::handleKeyPress (const int keyCode, keyWasUsed = target->keyPressed (keyInfo); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) + if (keyWasUsed || deletionChecker == 0) break; if (keyInfo.isKeyCode (KeyPress::tabKey) && Component::getCurrentlyFocusedComponent() != 0) @@ -221,11 +220,11 @@ bool ComponentPeer::handleKeyUpOrDown (const bool isKeyDown) while (target != 0) { - const ComponentDeletionWatcher deletionChecker (target); + const Component::SafePointer deletionChecker (target); keyWasUsed = target->keyStateChanged (isKeyDown); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) + if (keyWasUsed || deletionChecker == 0) break; if (target->keyListeners_ != 0) @@ -234,7 +233,7 @@ bool ComponentPeer::handleKeyUpOrDown (const bool isKeyDown) { keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyStateChanged (isKeyDown, target); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) + if (keyWasUsed || deletionChecker == 0) return keyWasUsed; i = jmin (i, target->keyListeners_->size()); @@ -295,7 +294,7 @@ void ComponentPeer::handleMovedOrResized() if (component->flags.hasHeavyweightPeerFlag && ! nowMinimised) { - const ComponentDeletionWatcher deletionChecker (component); + const Component::SafePointer deletionChecker (component); const Rectangle newBounds (getBounds()); const bool wasMoved = (component->getPosition() != newBounds.getPosition()); @@ -310,7 +309,7 @@ void ComponentPeer::handleMovedOrResized() component->sendMovedResizedMessages (wasMoved, wasResized); - if (deletionChecker.hasBeenDeleted()) + if (deletionChecker == 0) return; } } @@ -409,10 +408,8 @@ void ComponentPeer::handleFileDragMove (const StringArray& files, const PointhasBeenDeleted()) - lastTarget = const_cast (dynamic_cast (dragAndDropTargetComponent->getComponent())); + FileDragAndDropTarget* lastTarget + = const_cast (dynamic_cast (static_cast (dragAndDropTargetComponent))); FileDragAndDropTarget* newTarget = 0; @@ -432,10 +429,8 @@ void ComponentPeer::handleFileDragMove (const StringArray& files, const Point (newTarget); - const Point pos (component->relativePositionToOtherComponent (targetComp, position)); - - dragAndDropTargetComponent = new ComponentDeletionWatcher (dynamic_cast (newTarget)); + dragAndDropTargetComponent = dynamic_cast (newTarget); + const Point pos (component->relativePositionToOtherComponent (dragAndDropTargetComponent, position)); newTarget->fileDragEnter (files, pos.getX(), pos.getY()); } } @@ -466,9 +461,10 @@ void ComponentPeer::handleFileDragDrop (const StringArray& files, const PointhasBeenDeleted()) + if (dragAndDropTargetComponent != 0) { - FileDragAndDropTarget* const target = const_cast (dynamic_cast (dragAndDropTargetComponent->getComponent())); + FileDragAndDropTarget* const target + = const_cast (dynamic_cast (static_cast (dragAndDropTargetComponent))); dragAndDropTargetComponent = 0; lastDragAndDropCompUnderMouse = 0; diff --git a/src/gui/components/windows/juce_ComponentPeer.h b/src/gui/components/windows/juce_ComponentPeer.h index 18f0bf79c3..2059b1ee0a 100644 --- a/src/gui/components/windows/juce_ComponentPeer.h +++ b/src/gui/components/windows/juce_ComponentPeer.h @@ -26,8 +26,7 @@ #ifndef __JUCE_COMPONENTPEER_JUCEHEADER__ #define __JUCE_COMPONENTPEER_JUCEHEADER__ -class Component; -class Graphics; +#include "../juce_Component.h" #include "../mouse/juce_MouseCursor.h" #include "../keyboard/juce_TextInputTarget.h" #include "../../../events/juce_MessageListener.h" @@ -35,7 +34,6 @@ class Graphics; #include "../../graphics/geometry/juce_RectangleList.h" class ComponentBoundsConstrainer; -class ComponentDeletionWatcher; //============================================================================== @@ -368,7 +366,7 @@ protected: private: //============================================================================== Component* lastFocusedComponent; - ScopedPointer dragAndDropTargetComponent; + Component::SafePointer dragAndDropTargetComponent; Component* lastDragAndDropCompUnderMouse; bool fakeMouseMessageSent : 1, isWindowMinimised : 1; diff --git a/src/gui/components/windows/juce_DocumentWindow.cpp b/src/gui/components/windows/juce_DocumentWindow.cpp index 56057e9f98..ebb0b33391 100644 --- a/src/gui/components/windows/juce_DocumentWindow.cpp +++ b/src/gui/components/windows/juce_DocumentWindow.cpp @@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_DocumentWindow.h" +#include "juce_ComponentPeer.h" #include "../lookandfeel/juce_LookAndFeel.h" #include "../../graphics/imaging/juce_Image.h" diff --git a/src/gui/components/windows/juce_ResizableWindow.cpp b/src/gui/components/windows/juce_ResizableWindow.cpp index 6ba351c6fc..4ca57f2924 100644 --- a/src/gui/components/windows/juce_ResizableWindow.cpp +++ b/src/gui/components/windows/juce_ResizableWindow.cpp @@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_ResizableWindow.h" +#include "juce_ComponentPeer.h" #include "../juce_Desktop.h" #include "../lookandfeel/juce_LookAndFeel.h" #include "../../graphics/geometry/juce_RectangleList.h" diff --git a/src/gui/components/windows/juce_SplashScreen.cpp b/src/gui/components/windows/juce_SplashScreen.cpp index 3e2eecb2a6..9497006e70 100644 --- a/src/gui/components/windows/juce_SplashScreen.cpp +++ b/src/gui/components/windows/juce_SplashScreen.cpp @@ -28,6 +28,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_SplashScreen.h" +#include "../windows/juce_ComponentPeer.h" #include "../../../events/juce_MessageManager.h" #include "../../graphics/imaging/juce_ImageCache.h" #include "../juce_Desktop.h" diff --git a/src/gui/components/windows/juce_TooltipWindow.cpp b/src/gui/components/windows/juce_TooltipWindow.cpp index a5b1e4e172..cd64471cdc 100644 --- a/src/gui/components/windows/juce_TooltipWindow.cpp +++ b/src/gui/components/windows/juce_TooltipWindow.cpp @@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_TooltipWindow.h" +#include "../windows/juce_ComponentPeer.h" #include "../../../core/juce_Time.h" #include "../../../threads/juce_Process.h" #include "../lookandfeel/juce_LookAndFeel.h" diff --git a/src/gui/components/windows/juce_TopLevelWindow.cpp b/src/gui/components/windows/juce_TopLevelWindow.cpp index 1b9a690aba..19f7592f4f 100644 --- a/src/gui/components/windows/juce_TopLevelWindow.cpp +++ b/src/gui/components/windows/juce_TopLevelWindow.cpp @@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_TopLevelWindow.h" +#include "../windows/juce_ComponentPeer.h" #include "../juce_Desktop.h" #include "../lookandfeel/juce_LookAndFeel.h" #include "../special/juce_DropShadower.h" diff --git a/src/native/juce_linux_NativeCode.cpp b/src/native/juce_linux_NativeCode.cpp index 0606fd57ce..048d811096 100644 --- a/src/native/juce_linux_NativeCode.cpp +++ b/src/native/juce_linux_NativeCode.cpp @@ -69,10 +69,10 @@ BEGIN_JUCE_NAMESPACE #include "../gui/components/special/juce_WebBrowserComponent.h" #include "../gui/components/keyboard/juce_KeyPress.h" #include "../utilities/juce_SystemClipboard.h" +#include "../gui/components/windows/juce_ComponentPeer.h" #include "../gui/components/windows/juce_AlertWindow.h" #include "../gui/components/special/juce_OpenGLComponent.h" #include "../gui/components/juce_Desktop.h" -#include "../gui/components/juce_ComponentDeletionWatcher.h" #include "../gui/graphics/geometry/juce_RectangleList.h" #include "../gui/graphics/imaging/juce_ImageFileFormat.h" #include "../gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h" diff --git a/src/native/juce_mac_NativeCode.mm b/src/native/juce_mac_NativeCode.mm index 6dde995783..a38c45caab 100644 --- a/src/native/juce_mac_NativeCode.mm +++ b/src/native/juce_mac_NativeCode.mm @@ -54,6 +54,7 @@ BEGIN_JUCE_NAMESPACE #include "../gui/graphics/imaging/juce_ImageFileFormat.h" #include "../gui/graphics/imaging/juce_CameraDevice.h" #include "../gui/components/windows/juce_AlertWindow.h" +#include "../gui/components/windows/juce_ComponentPeer.h" #include "../gui/components/juce_Desktop.h" #include "../gui/components/menus/juce_MenuBarModel.h" #include "../gui/components/special/juce_OpenGLComponent.h" diff --git a/src/native/juce_win32_NativeCode.cpp b/src/native/juce_win32_NativeCode.cpp index 6c8df850a7..57f8fe12f7 100644 --- a/src/native/juce_win32_NativeCode.cpp +++ b/src/native/juce_win32_NativeCode.cpp @@ -57,6 +57,7 @@ BEGIN_JUCE_NAMESPACE #include "../gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h" #include "../gui/graphics/imaging/juce_ImageFileFormat.h" #include "../gui/graphics/imaging/juce_CameraDevice.h" +#include "../gui/components/windows/juce_ComponentPeer.h" #include "../gui/components/windows/juce_AlertWindow.h" #include "../gui/components/juce_Desktop.h" #include "../gui/components/menus/juce_MenuBarModel.h" diff --git a/src/native/linux/juce_linux_Windowing.cpp b/src/native/linux/juce_linux_Windowing.cpp index 9d9e93a4a4..3a17202bbd 100644 --- a/src/native/linux/juce_linux_Windowing.cpp +++ b/src/native/linux/juce_linux_Windowing.cpp @@ -535,7 +535,7 @@ public: if (windowH != 0) { - const ComponentDeletionWatcher deletionChecker (component); + Component::SafePointer deletionChecker (component); wx = x; wy = y; @@ -566,7 +566,7 @@ public: wx - windowBorder.getLeft(), wy - windowBorder.getTop(), ww, wh); - if (! deletionChecker.hasBeenDeleted()) + if (deletionChecker != 0) { updateBorderSize(); handleMovedOrResized(); diff --git a/src/native/windows/juce_win32_Windowing.cpp b/src/native/windows/juce_win32_Windowing.cpp index 01664df020..50274008e6 100644 --- a/src/native/windows/juce_win32_Windowing.cpp +++ b/src/native/windows/juce_win32_Windowing.cpp @@ -563,7 +563,7 @@ public: if (fullScreen != shouldBeFullScreen) { fullScreen = shouldBeFullScreen; - const ComponentDeletionWatcher deletionChecker (component); + const Component::SafePointer deletionChecker (component); if (! fullScreen) { @@ -589,7 +589,7 @@ public: SendMessageW (hwnd, WM_SETTINGCHANGE, 0, 0); } - if (! deletionChecker.hasBeenDeleted()) + if (deletionChecker != 0) handleMovedOrResized(); } }