From c16f6f17a922f9f8cea0b8b43b9bb7f84c450e21 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Mon, 1 Nov 2010 17:51:09 +0000 Subject: [PATCH] The Component class no longer derives from MessageListener - this was adding a lot of overhead to each component construction/destruction, and was rarely providing any benefit. You can add it as a base class yourself if you need it. Component::isValidComponent() has now been removed - it was never 100% reliable and its job can be done better using Component::SafePointer to watch for deletions. Also minor fixes to AudioDeviceManager and Midi sysex parsing. --- .../Project/jucer_ProjectTreeViewBase.cpp | 39 ++- .../audio plugin host/Source/HostStartup.cpp | 32 +- .../wrapper/AU/juce_AU_Wrapper.mm | 2 +- juce_amalgamated.cpp | 309 +++++++++--------- juce_amalgamated.h | 37 +-- src/audio/devices/juce_AudioDeviceManager.cpp | 47 ++- src/audio/devices/juce_AudioDeviceManager.h | 1 + src/audio/midi/juce_MidiMessage.cpp | 19 +- src/core/juce_StandardHeader.h | 2 +- src/events/juce_CallbackMessage.h | 2 +- src/events/juce_Message.cpp | 2 +- src/events/juce_Message.h | 2 +- src/events/juce_MessageManager.cpp | 2 +- src/gui/components/controls/juce_Toolbar.cpp | 39 ++- .../controls/juce_ToolbarItemComponent.cpp | 2 - src/gui/components/juce_Component.cpp | 98 +++--- src/gui/components/juce_Component.h | 27 +- src/gui/components/juce_Desktop.cpp | 22 +- .../layout/juce_TabbedComponent.cpp | 35 +- .../components/layout/juce_TabbedComponent.h | 4 +- src/gui/components/menus/juce_PopupMenu.cpp | 21 +- .../mouse/juce_ComponentDragger.cpp | 4 +- .../mouse/juce_MouseHoverDetector.cpp | 5 - .../special/juce_BubbleComponent.cpp | 2 +- .../components/windows/juce_ComponentPeer.cpp | 1 - .../components/windows/juce_ComponentPeer.h | 1 + src/threads/juce_Thread.cpp | 9 + 27 files changed, 354 insertions(+), 412 deletions(-) diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectTreeViewBase.cpp b/extras/Jucer (experimental)/Source/Project/jucer_ProjectTreeViewBase.cpp index e578b5cdf6..2ffb154cb6 100644 --- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectTreeViewBase.cpp +++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectTreeViewBase.cpp @@ -120,36 +120,35 @@ ProjectTreeViewBase* ProjectTreeViewBase::findTreeViewItem (const Project::Item& } //============================================================================== -class RenameMessage : public CallbackMessage +void ProjectTreeViewBase::triggerAsyncRename (const Project::Item& itemToRename) { -public: - RenameMessage (TreeView* const tree_, const Project::Item& itemToRename_) - : tree (tree_), itemToRename (itemToRename_) {} - - ~RenameMessage() throw() {} - - void messageCallback() + class RenameMessage : public CallbackMessage { - if (tree->isValidComponent()) - { - ProjectTreeViewBase* pg = dynamic_cast (tree->getRootItem()); + public: + RenameMessage (TreeView* const tree_, const Project::Item& itemToRename_) + : tree (tree_), itemToRename (itemToRename_) {} - if (pg != 0) + void messageCallback() + { + if (tree != 0) { - pg = pg->findTreeViewItem (itemToRename); + ProjectTreeViewBase* pg = dynamic_cast (tree->getRootItem()); if (pg != 0) - pg->showRenameBox(); + { + pg = pg->findTreeViewItem (itemToRename); + + if (pg != 0) + pg->showRenameBox(); + } } } - } - TreeView* tree; - Project::Item itemToRename; -}; + private: + Component::SafePointer tree; + Project::Item itemToRename; + }; -void ProjectTreeViewBase::triggerAsyncRename (const Project::Item& itemToRename) -{ (new RenameMessage (getOwnerView(), itemToRename))->post(); } diff --git a/extras/audio plugin host/Source/HostStartup.cpp b/extras/audio plugin host/Source/HostStartup.cpp index 166751dd13..264c37abc0 100644 --- a/extras/audio plugin host/Source/HostStartup.cpp +++ b/extras/audio plugin host/Source/HostStartup.cpp @@ -38,12 +38,9 @@ ApplicationCommandManager* commandManager = 0; //============================================================================== class PluginHostApp : public JUCEApplication { - MainHostWindow* mainWindow; - public: //============================================================================== PluginHostApp() - : mainWindow (0) { } @@ -55,8 +52,8 @@ public: { // initialise our settings file.. ApplicationProperties::getInstance() - ->setStorageParameters (T("Juce Audio Plugin Host"), - T("settings"), String::empty, 1000, + ->setStorageParameters ("Juce Audio Plugin Host", + "settings", String::empty, 1000, PropertiesFile::storeAsXML); commandManager = new ApplicationCommandManager(); @@ -75,35 +72,26 @@ public: void shutdown() { - deleteAndZero (mainWindow); - + mainWindow = 0; ApplicationProperties::getInstance()->closeFiles(); deleteAndZero (commandManager); } - const String getApplicationName() - { - return T("Juce Plug-In Host"); - } - - const String getApplicationVersion() - { - return ProjectInfo::versionString; - } - void systemRequestedQuit() { - if (mainWindow->isValidComponent()) + if (mainWindow != 0) mainWindow->tryToQuitApplication(); else JUCEApplication::quit(); } - bool moreThanOneInstanceAllowed() - { - return true; - } + const String getApplicationName() { return "Juce Plug-In Host"; } + const String getApplicationVersion() { return ProjectInfo::versionString; } + bool moreThanOneInstanceAllowed() { return true; } + +private: + ScopedPointer mainWindow; }; diff --git a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm index 0133bb60e8..e7c5456ef8 100644 --- a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm +++ b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm @@ -1062,7 +1062,7 @@ public: - (void) deleteEditor { - if (editorComp != 0 && editorComp->isValidComponent()) + if (editorComp != 0) { if (editorComp->getChildComponent(0) != 0) if (activePlugins.contains ((void*) au)) // plugin may have been deleted before the UI diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 36c333a749..664f11beab 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -17007,6 +17007,15 @@ Thread::Thread (const String& threadName) Thread::~Thread() { + /* If your thread class's destructor has been called without first stopping the thread, that + means that this partially destructed object is still performing some work - and that's not + unlikely to be a safe approach to take! + + To avoid this type of nastiness, always make sure you call stopThread() before or during + your subclass's destructor. + */ + jassert (! isThreadRunning()); + stopThread (100); } @@ -25697,6 +25706,7 @@ const String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& ne currentSetup = newSetup; currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate); + currentSetup.bufferSize = chooseBestBufferSize (newSetup.bufferSize); error = currentAudioDevice->open (inputChannels, outputChannels, @@ -25734,40 +25744,36 @@ double AudioDeviceManager::chooseBestSampleRate (double rate) const jassert (currentAudioDevice != 0); if (rate > 0) - { - bool ok = false; - for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) - { - const double sr = currentAudioDevice->getSampleRate (i); + if (currentAudioDevice->getSampleRate (i) == rate) + return rate; - if (sr == rate) - ok = true; - } + double lowestAbove44 = 0.0; - if (! ok) - rate = 0; + for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) + { + const double sr = currentAudioDevice->getSampleRate (i); + + if (sr >= 44100.0 && (lowestAbove44 == 0 || sr < lowestAbove44)) + lowestAbove44 = sr; } - if (rate == 0) - { - double lowestAbove44 = 0.0; + if (lowestAbove44 > 0.0) + return lowestAbove44; - for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) - { - const double sr = currentAudioDevice->getSampleRate (i); + return currentAudioDevice->getSampleRate (0); +} - if (sr >= 44100.0 && (lowestAbove44 == 0 || sr < lowestAbove44)) - lowestAbove44 = sr; - } +int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const +{ + jassert (currentAudioDevice != 0); - if (lowestAbove44 == 0.0) - rate = currentAudioDevice->getSampleRate (0); - else - rate = lowestAbove44; - } + if (bufferSize > 0) + for (int i = currentAudioDevice->getNumBufferSizesAvailable(); --i >= 0;) + if (currentAudioDevice->getBufferSizeSamples(i) == bufferSize) + return bufferSize; - return rate; + return currentAudioDevice->getDefaultBufferSize(); } void AudioDeviceManager::stopDevice() @@ -28897,17 +28903,26 @@ MidiMessage::MidiMessage (const void* src_, int sz, int& numBytesUsed, const uin if (byte == 0xf0) { const uint8* d = src; + bool haveReadAllLengthBytes = false; while (d < src + sz) { - if (*d >= 0x80) // stop if we hit a status byte, and don't include it in this message + if (*d >= 0x80) { - if (*d == 0xf7) // include an 0xf7 if we hit one - ++d; + if (*d == 0xf7) + { + ++d; // include the trailing 0xf7 when we hit it + break; + } - break; + if (haveReadAllLengthBytes) // if we see a 0x80 bit set after the initial data length + break; // bytes, assume it's the end of the sysex + + ++d; + continue; } + haveReadAllLengthBytes = true; ++d; } @@ -29003,7 +29018,7 @@ void MidiMessage::setChannel (const int channel) throw() jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 if ((data[0] & 0xf0) != (uint8) 0xf0) - data[0] = (uint8) ((data[0] & (uint8)0xf0) + data[0] = (uint8) ((data[0] & (uint8) 0xf0) | (uint8)(channel - 1)); } @@ -39004,7 +39019,7 @@ Message::Message (const int intParameter1_, { } -Message::~Message() throw() +Message::~Message() { } @@ -39101,7 +39116,7 @@ void MessageManager::postMessageToQueue (Message* const message) } CallbackMessage::CallbackMessage() throw() {} -CallbackMessage::~CallbackMessage() throw() {} +CallbackMessage::~CallbackMessage() {} void CallbackMessage::post() { @@ -39856,12 +39871,6 @@ BEGIN_JUCE_NAMESPACE #define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); -enum ComponentMessageNumbers -{ - customCommandMessage = 0x7fff0001, - exitModalStateMessage = 0x7fff0002 -}; - Component* Component::currentlyFocusedComponent = 0; class Component::MouseListenerList @@ -40157,11 +40166,6 @@ bool Component::isShowing() const return false; } -bool Component::isValidComponent() const -{ - return (this != 0) && isValidMessageListener(); -} - void* Component::getWindowHandle() const { const ComponentPeer* const peer = getPeer(); @@ -41058,12 +41062,6 @@ Component* Component::getTopLevelComponent() const throw() bool Component::isParentOf (const Component* possibleChild) const throw() { - if (! possibleChild->isValidComponent()) - { - jassert (possibleChild == 0); - return false; - } - while (possibleChild != 0) { possibleChild = possibleChild->parentComponent_; @@ -41184,7 +41182,27 @@ void Component::exitModalState (const int returnValue) } else { - postMessage (new Message (exitModalStateMessage, returnValue, 0, 0)); + class ExitModalStateMessage : public CallbackMessage + { + public: + ExitModalStateMessage (Component* const target_, const int result_) + : target (target_), result (result_) {} + + void messageCallback() + { + if (target != 0) + target->exitModalState (result); + } + + private: + Component::SafePointer target; + const int result; + + ExitModalStateMessage (ExitModalStateMessage&); + ExitModalStateMessage& operator= (const ExitModalStateMessage&); + }; + + (new ExitModalStateMessage (this, returnValue))->post(); } } } @@ -41555,22 +41573,21 @@ void Component::sendLookAndFeelChange() { repaint(); - lookAndFeelChanged(); - - // (it's not a great idea to do anything that would delete this component - // during the lookAndFeelChanged() callback) - jassert (isValidComponent()); - SafePointer safePointer (this); - for (int i = childComponentList_.size(); --i >= 0;) + lookAndFeelChanged(); + + if (safePointer != 0) { - childComponentList_.getUnchecked (i)->sendLookAndFeelChange(); + for (int i = childComponentList_.size(); --i >= 0;) + { + childComponentList_.getUnchecked (i)->sendLookAndFeelChange(); - if (safePointer == 0) - return; + if (safePointer == 0) + return; - i = jmin (i, childComponentList_.size()); + i = jmin (i, childComponentList_.size()); + } } } @@ -41814,13 +41831,11 @@ void Component::parentSizeChanged() void Component::addComponentListener (ComponentListener* const newListener) { - jassert (isValidComponent()); componentListeners.add (newListener); } void Component::removeComponentListener (ComponentListener* const listenerToRemove) { - jassert (isValidComponent()); componentListeners.remove (listenerToRemove); } @@ -41855,21 +41870,29 @@ void Component::paintOverChildren (Graphics&) // all painting is done in the subclasses } -void Component::handleMessage (const Message& message) +void Component::postCommandMessage (const int commandId) { - if (message.intParameter1 == exitModalStateMessage) - { - exitModalState (message.intParameter2); - } - else if (message.intParameter1 == customCommandMessage) + class CustomCommandMessage : public CallbackMessage { - handleCommandMessage (message.intParameter2); - } -} + public: + CustomCommandMessage (Component* const target_, const int commandId_) + : target (target_), commandId (commandId_) {} -void Component::postCommandMessage (const int commandId) -{ - postMessage (new Message (customCommandMessage, commandId, 0, 0)); + void messageCallback() + { + if (target != 0) + target->exitModalState (commandId); + } + + private: + Component::SafePointer target; + const int commandId; + + CustomCommandMessage (CustomCommandMessage&); + CustomCommandMessage& operator= (const CustomCommandMessage&); + }; + + (new CustomCommandMessage (this, commandId))->post(); } void Component::handleCommandMessage (int) @@ -42247,9 +42270,6 @@ void Component::broughtToFront() void Component::internalBroughtToFront() { - if (! isValidComponent()) - return; - if (flags.hasHeavyweightPeerFlag) Desktop::getInstance().componentBroughtToFront (this); @@ -42821,10 +42841,14 @@ Component* Desktop::findComponentAt (const Point& screenPosition) const for (int i = desktopComponents.size(); --i >= 0;) { Component* const c = desktopComponents.getUnchecked(i); - const Point relative (c->globalPositionToRelative (screenPosition)); - if (c->contains (relative.getX(), relative.getY())) - return c->getComponentAt (relative.getX(), relative.getY()); + if (c->isVisible()) + { + const Point relative (c->globalPositionToRelative (screenPosition)); + + if (c->contains (relative.getX(), relative.getY())) + return c->getComponentAt (relative.getX(), relative.getY()); + } } return 0; @@ -42991,12 +43015,10 @@ void Desktop::setKioskModeComponent (Component* componentToUse, const bool allow { if (kioskModeComponent != componentToUse) { - // agh! Don't delete a component without first stopping it being the kiosk comp - jassert (kioskModeComponent == 0 || kioskModeComponent->isValidComponent()); - // agh! Don't remove a component from the desktop if it's the kiosk comp! - jassert (kioskModeComponent == 0 || kioskModeComponent->isOnDesktop()); + // agh! Don't delete or remove a component from the desktop while it's still the kiosk component! + jassert (kioskModeComponent == 0 || ComponentPeer::getPeerFor (kioskModeComponent) != 0); - if (kioskModeComponent->isValidComponent()) + if (kioskModeComponent != 0) { juce_setKioskComponent (kioskModeComponent, false, allowMenusAndBars); @@ -43007,10 +43029,8 @@ void Desktop::setKioskModeComponent (Component* componentToUse, const bool allow if (kioskModeComponent != 0) { - jassert (kioskModeComponent->isValidComponent()); - // Only components that are already on the desktop can be put into kiosk mode! - jassert (kioskModeComponent->isOnDesktop()); + jassert (ComponentPeer::getPeerFor (kioskModeComponent) != 0); kioskComponentOriginalBounds = kioskModeComponent->getBounds(); @@ -55041,7 +55061,7 @@ class Toolbar::MissingItemsComponent : public PopupMenuCustomComponent public: MissingItemsComponent (Toolbar& owner_, const int height_) : PopupMenuCustomComponent (true), - owner (owner_), + owner (&owner_), height (height_) { for (int i = owner_.items.size(); --i >= 0;) @@ -55060,23 +55080,23 @@ public: ~MissingItemsComponent() { - // deleting the toolbar while its menu it open?? - jassert (owner.isValidComponent()); - - for (int i = 0; i < getNumChildComponents(); ++i) + if (owner != 0) { - ToolbarItemComponent* const tc = dynamic_cast (getChildComponent (i)); - - if (tc != 0) + for (int i = 0; i < getNumChildComponents(); ++i) { - tc->setVisible (false); - const int index = oldIndexes.remove (i); - owner.addChildComponent (tc, index); - --i; + ToolbarItemComponent* const tc = dynamic_cast (getChildComponent (i)); + + if (tc != 0) + { + tc->setVisible (false); + const int index = oldIndexes.remove (i); + owner->addChildComponent (tc, index); + --i; + } } - } - owner.resized(); + owner->resized(); + } } void layout (const int preferredWidth) @@ -55122,7 +55142,7 @@ public: juce_UseDebuggingNewOperator private: - Toolbar& owner; + Component::SafePointer owner; const int height; Array oldIndexes; @@ -55745,10 +55765,17 @@ void Toolbar::showCustomisationDialog (ToolbarItemFactory& factory, const int op { setEditingActive (true); + #if JUCE_DEBUG + Component::SafePointer checker (this); + #endif + ToolbarCustomisationDialog dw (factory, this, optionFlags); dw.runModalLoop(); - jassert (isValidComponent()); // ? deleting the toolbar while it's being edited? + #if JUCE_DEBUG + jassert (checker != 0); // Don't delete the toolbar while it's being customised! + #endif + setEditingActive (false); } @@ -55883,7 +55910,6 @@ ToolbarItemComponent::ToolbarItemComponent (const int itemId_, ToolbarItemComponent::~ToolbarItemComponent() { - jassert (overlayComp == 0 || overlayComp->isValidComponent()); overlayComp = 0; } @@ -55971,7 +55997,6 @@ void ToolbarItemComponent::setEditingMode (const ToolbarEditingMode newMode) if (mode == normalMode) { - jassert (overlayComp == 0 || overlayComp->isValidComponent()); overlayComp = 0; } else if (overlayComp == 0) @@ -64333,8 +64358,7 @@ private: }; TabbedComponent::TabbedComponent (const TabbedButtonBar::Orientation orientation) - : panelComponent (0), - tabDepth (30), + : tabDepth (30), outlineThickness (1), edgeIndent (0) { @@ -64387,13 +64411,10 @@ void TabbedComponent::clearTabs() for (int i = contentComponents.size(); --i >= 0;) { - Component* const c = contentComponents.getUnchecked(i); - - // be careful not to delete these components until they've been removed from the tab component - jassert (c == 0 || c->isValidComponent()); + Component::SafePointer& c = contentComponents.getReference (i); if (c != 0 && (bool) c->getProperties() [deleteComponentId]) - delete c; + c.deleteAndZero(); } contentComponents.clear(); @@ -64420,19 +64441,16 @@ void TabbedComponent::setTabName (const int tabIndex, const String& newName) void TabbedComponent::removeTab (const int tabIndex) { - Component* const c = contentComponents [tabIndex]; - - if (c != 0 && (bool) c->getProperties() [deleteComponentId]) + if (tabIndex >= 0 && tabIndex < contentComponents.size()) { - if (c == panelComponent) - panelComponent = 0; - - delete c; - } + Component::SafePointer& c = contentComponents.getReference (tabIndex); - contentComponents.remove (tabIndex); + if (c != 0 && (bool) c->getProperties() [deleteComponentId]) + c.deleteAndZero(); - tabs->removeTab (tabIndex); + contentComponents.remove (tabIndex); + tabs->removeTab (tabIndex); + } } int TabbedComponent::getNumTabs() const @@ -64558,15 +64576,15 @@ void TabbedComponent::resized() const Rectangle bounds (indents.subtractedFrom (getLocalBounds())); for (int i = contentComponents.size(); --i >= 0;) - if (contentComponents.getUnchecked (i) != 0) - contentComponents.getUnchecked (i)->setBounds (bounds); + if (contentComponents.getReference (i) != 0) + contentComponents.getReference (i)->setBounds (bounds); } void TabbedComponent::lookAndFeelChanged() { for (int i = contentComponents.size(); --i >= 0;) - if (contentComponents.getUnchecked (i) != 0) - contentComponents.getUnchecked (i)->lookAndFeelChanged(); + if (contentComponents.getReference (i) != 0) + contentComponents.getReference (i)->lookAndFeelChanged(); } void TabbedComponent::changeCallback (const int newCurrentTabIndex, @@ -69200,12 +69218,8 @@ public: ~Window() { getActiveWindows().removeValue (this); - Desktop::getInstance().removeGlobalMouseListener (this); - - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); activeSubMenu = 0; - deleteAllChildren(); } @@ -69322,8 +69336,6 @@ public: { if (isVisible()) { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - activeSubMenu = 0; currentChild = 0; @@ -69423,8 +69435,6 @@ public: if (showSubMenuFor (currentChild)) { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - if (activeSubMenu != 0 && activeSubMenu->isVisible()) activeSubMenu->selectNextItem (1); } @@ -69512,7 +69522,7 @@ public: if (now > timeEnteredCurrentChildComp + 100 && reallyContains (localMousePos.getX(), localMousePos.getY(), true) - && currentChild->isValidComponent() + && currentChild != 0 && (! disableMouseMoves) && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) { @@ -69668,8 +69678,6 @@ private: bool isOverChildren() const { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - return isVisible() && (isOver || (activeSubMenu != 0 && activeSubMenu->isOverChildren())); } @@ -69982,7 +69990,7 @@ private: void setCurrentlyHighlightedChild (PopupMenu::ItemComponent* const child) { - if (currentChild->isValidComponent()) + if (currentChild != 0) currentChild->setHighlighted (false); currentChild = child; @@ -69996,10 +70004,9 @@ private: bool showSubMenuFor (PopupMenu::ItemComponent* const childComp) { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); activeSubMenu = 0; - if (childComp->isValidComponent() && childComp->itemInfo.hasActiveSubMenu()) + if (childComp != 0 && childComp->itemInfo.hasActiveSubMenu()) { activeSubMenu = Window::create (*(childComp->itemInfo.subMenu), dismissOnMouseUp, @@ -70042,8 +70049,6 @@ private: bool isMovingTowardsMenu = false; - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()) - if (isOver && (activeSubMenu != 0) && globalMousePos != lastMouse) { // try to intelligently guess whether the user is moving the mouse towards a currently-open @@ -70104,7 +70109,7 @@ private: void triggerCurrentlyHighlightedItem() { - if (currentChild->isValidComponent() + if (currentChild != 0 && currentChild->itemInfo.canBeTriggered() && (currentChild->itemInfo.customComp == 0 || currentChild->itemInfo.customComp->isTriggeredAutomatically)) @@ -70679,7 +70684,7 @@ ComponentDragger::~ComponentDragger() void ComponentDragger::startDraggingComponent (Component* const componentToDrag, ComponentBoundsConstrainer* const constrainer_) { - jassert (componentToDrag->isValidComponent()); + jassert (componentToDrag != 0); if (componentToDrag != 0) { @@ -70690,7 +70695,7 @@ void ComponentDragger::startDraggingComponent (Component* const componentToDrag, void ComponentDragger::dragComponent (Component* const componentToDrag, const MouseEvent& e) { - jassert (componentToDrag->isValidComponent()); + jassert (componentToDrag != 0); jassert (e.mods.isAnyMouseButtonDown()); // (the event has to be a drag event..) if (componentToDrag != 0) @@ -71960,12 +71965,7 @@ void MouseHoverDetector::setHoverComponent (Component* const newSourceComponent) hasJustHovered = false; if (source != 0) - { - // ! you need to delete the hover detector before deleting its component - jassert (source->isValidComponent()); - source->removeMouseListener (&internalTimer); - } source = newSourceComponent; @@ -74086,7 +74086,7 @@ void BubbleComponent::setAllowedPlacement (const int newPlacement) void BubbleComponent::setPosition (Component* componentToPointTo) { - jassert (componentToPointTo->isValidComponent()); + jassert (componentToPointTo != 0); Point pos; @@ -77911,7 +77911,6 @@ void ComponentPeer::setConstrainer (ComponentBoundsConstrainer* const newConstra void ComponentPeer::handleMovedOrResized() { - jassert (component->isValidComponent()); updateCurrentModifiers(); const bool nowMinimised = isMinimised(); @@ -258310,8 +258309,6 @@ public: if (! XInitImage (xImage)) jassertfalse; } - - zeromem (imageData, h * lineStride); } ~XBitmapImage() diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 9a16d40a56..0ba851a835 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 84 +#define JUCE_BUILDNUMBER 85 /** Current Juce version number. @@ -12256,7 +12256,7 @@ public: void* pointerParameter) throw(); /** Destructor. */ - virtual ~Message() throw(); + virtual ~Message(); // These values can be used for carrying simple data that the application needs to // pass around. For more complex messages, just create a subclass. @@ -25998,8 +25998,7 @@ class ComponentPeer; The base class for all JUCE user-interface objects. */ -class JUCE_API Component : public MouseListener, - public MessageListener +class JUCE_API Component : public MouseListener { public: @@ -26052,18 +26051,6 @@ public: */ virtual void setName (const String& newName); - /** Checks whether this Component object has been deleted. - - This will check whether this object is still a valid component, or whether - it's been deleted. - - It's safe to call this on null or dangling pointers, but note that there is a - small risk if another new (but different) component has been created at the - same memory address which this one occupied, this methods can return a - false positive. - */ - bool isValidComponent() const; - /** Makes the component visible or invisible. This method will show or hide the component. @@ -28009,16 +27996,8 @@ private: protected: /** @internal */ virtual void internalRepaint (int x, int y, int w, int h); - + /** @internal */ virtual ComponentPeer* createNewPeer (int styleFlags, void* nativeWindowToAttachTo); - - /** Overridden from the MessageListener parent class. - - You can override this if you really need to, but be sure to pass your unwanted messages up - to this base class implementation, as the Component class needs to send itself messages - to work properly. - */ - void handleMessage (const Message&); }; #endif // __JUCE_COMPONENT_JUCEHEADER__ @@ -38881,6 +38860,7 @@ private: void scanDevicesIfNeeded(); void deleteCurrentDevice(); double chooseBestSampleRate (double preferred) const; + int chooseBestBufferSize (int preferred) const; void insertDefaultDeviceNames (AudioDeviceSetup& setup) const; AudioIODeviceType* findType (const String& inputName, const String& outputName); @@ -43432,7 +43412,7 @@ public: CallbackMessage() throw(); /** Destructor. */ - ~CallbackMessage() throw(); + ~CallbackMessage(); /** Called when the message is delivered. @@ -53273,8 +53253,8 @@ protected: private: - Array contentComponents; - Component* panelComponent; + Array > contentComponents; + Component::SafePointer panelComponent; int tabDepth; int outlineThickness, edgeIndent; static const Identifier deleteComponentId; @@ -59311,6 +59291,7 @@ private: bool fakeMouseMessageSent : 1, isWindowMinimised : 1; friend class Component; + friend class Desktop; static ComponentPeer* getPeerFor (const Component* component) throw(); void setLastDragDropTarget (Component* comp); diff --git a/src/audio/devices/juce_AudioDeviceManager.cpp b/src/audio/devices/juce_AudioDeviceManager.cpp index 63433ace21..c935891872 100644 --- a/src/audio/devices/juce_AudioDeviceManager.cpp +++ b/src/audio/devices/juce_AudioDeviceManager.cpp @@ -443,6 +443,7 @@ const String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& ne currentSetup = newSetup; currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate); + currentSetup.bufferSize = chooseBestBufferSize (newSetup.bufferSize); error = currentAudioDevice->open (inputChannels, outputChannels, @@ -480,40 +481,36 @@ double AudioDeviceManager::chooseBestSampleRate (double rate) const jassert (currentAudioDevice != 0); if (rate > 0) - { - bool ok = false; - for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) - { - const double sr = currentAudioDevice->getSampleRate (i); + if (currentAudioDevice->getSampleRate (i) == rate) + return rate; - if (sr == rate) - ok = true; - } + double lowestAbove44 = 0.0; - if (! ok) - rate = 0; + for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) + { + const double sr = currentAudioDevice->getSampleRate (i); + + if (sr >= 44100.0 && (lowestAbove44 == 0 || sr < lowestAbove44)) + lowestAbove44 = sr; } - if (rate == 0) - { - double lowestAbove44 = 0.0; + if (lowestAbove44 > 0.0) + return lowestAbove44; - for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) - { - const double sr = currentAudioDevice->getSampleRate (i); + return currentAudioDevice->getSampleRate (0); +} - if (sr >= 44100.0 && (lowestAbove44 == 0 || sr < lowestAbove44)) - lowestAbove44 = sr; - } +int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const +{ + jassert (currentAudioDevice != 0); - if (lowestAbove44 == 0.0) - rate = currentAudioDevice->getSampleRate (0); - else - rate = lowestAbove44; - } + if (bufferSize > 0) + for (int i = currentAudioDevice->getNumBufferSizesAvailable(); --i >= 0;) + if (currentAudioDevice->getBufferSizeSamples(i) == bufferSize) + return bufferSize; - return rate; + return currentAudioDevice->getDefaultBufferSize(); } void AudioDeviceManager::stopDevice() diff --git a/src/audio/devices/juce_AudioDeviceManager.h b/src/audio/devices/juce_AudioDeviceManager.h index 44358bbb63..38f0ead16b 100644 --- a/src/audio/devices/juce_AudioDeviceManager.h +++ b/src/audio/devices/juce_AudioDeviceManager.h @@ -517,6 +517,7 @@ private: void scanDevicesIfNeeded(); void deleteCurrentDevice(); double chooseBestSampleRate (double preferred) const; + int chooseBestBufferSize (int preferred) const; void insertDefaultDeviceNames (AudioDeviceSetup& setup) const; AudioIODeviceType* findType (const String& inputName, const String& outputName); diff --git a/src/audio/midi/juce_MidiMessage.cpp b/src/audio/midi/juce_MidiMessage.cpp index faf91ea3f6..437d527cd3 100644 --- a/src/audio/midi/juce_MidiMessage.cpp +++ b/src/audio/midi/juce_MidiMessage.cpp @@ -184,17 +184,26 @@ MidiMessage::MidiMessage (const void* src_, int sz, int& numBytesUsed, const uin if (byte == 0xf0) { const uint8* d = src; + bool haveReadAllLengthBytes = false; while (d < src + sz) { - if (*d >= 0x80) // stop if we hit a status byte, and don't include it in this message + if (*d >= 0x80) { - if (*d == 0xf7) // include an 0xf7 if we hit one - ++d; + if (*d == 0xf7) + { + ++d; // include the trailing 0xf7 when we hit it + break; + } - break; + if (haveReadAllLengthBytes) // if we see a 0x80 bit set after the initial data length + break; // bytes, assume it's the end of the sysex + + ++d; + continue; } + haveReadAllLengthBytes = true; ++d; } @@ -290,7 +299,7 @@ void MidiMessage::setChannel (const int channel) throw() jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 if ((data[0] & 0xf0) != (uint8) 0xf0) - data[0] = (uint8) ((data[0] & (uint8)0xf0) + data[0] = (uint8) ((data[0] & (uint8) 0xf0) | (uint8)(channel - 1)); } diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 69404a11e0..bd6a46fda7 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 84 +#define JUCE_BUILDNUMBER 85 /** Current Juce version number. diff --git a/src/events/juce_CallbackMessage.h b/src/events/juce_CallbackMessage.h index f0af431945..8ac6c46429 100644 --- a/src/events/juce_CallbackMessage.h +++ b/src/events/juce_CallbackMessage.h @@ -51,7 +51,7 @@ public: CallbackMessage() throw(); /** Destructor. */ - ~CallbackMessage() throw(); + ~CallbackMessage(); //============================================================================== /** Called when the message is delivered. diff --git a/src/events/juce_Message.cpp b/src/events/juce_Message.cpp index 36f2212e57..8f51d495a3 100644 --- a/src/events/juce_Message.cpp +++ b/src/events/juce_Message.cpp @@ -50,7 +50,7 @@ Message::Message (const int intParameter1_, { } -Message::~Message() throw() +Message::~Message() { } diff --git a/src/events/juce_Message.h b/src/events/juce_Message.h index 8909825bde..1c2c76deaa 100644 --- a/src/events/juce_Message.h +++ b/src/events/juce_Message.h @@ -59,7 +59,7 @@ public: void* pointerParameter) throw(); /** Destructor. */ - virtual ~Message() throw(); + virtual ~Message(); //============================================================================== // These values can be used for carrying simple data that the application needs to diff --git a/src/events/juce_MessageManager.cpp b/src/events/juce_MessageManager.cpp index eaf163fde0..d8ff82071b 100644 --- a/src/events/juce_MessageManager.cpp +++ b/src/events/juce_MessageManager.cpp @@ -87,7 +87,7 @@ void MessageManager::postMessageToQueue (Message* const message) //============================================================================== CallbackMessage::CallbackMessage() throw() {} -CallbackMessage::~CallbackMessage() throw() {} +CallbackMessage::~CallbackMessage() {} void CallbackMessage::post() { diff --git a/src/gui/components/controls/juce_Toolbar.cpp b/src/gui/components/controls/juce_Toolbar.cpp index 035477391b..65563a7922 100644 --- a/src/gui/components/controls/juce_Toolbar.cpp +++ b/src/gui/components/controls/juce_Toolbar.cpp @@ -177,7 +177,7 @@ class Toolbar::MissingItemsComponent : public PopupMenuCustomComponent public: MissingItemsComponent (Toolbar& owner_, const int height_) : PopupMenuCustomComponent (true), - owner (owner_), + owner (&owner_), height (height_) { for (int i = owner_.items.size(); --i >= 0;) @@ -196,23 +196,23 @@ public: ~MissingItemsComponent() { - // deleting the toolbar while its menu it open?? - jassert (owner.isValidComponent()); - - for (int i = 0; i < getNumChildComponents(); ++i) + if (owner != 0) { - ToolbarItemComponent* const tc = dynamic_cast (getChildComponent (i)); - - if (tc != 0) + for (int i = 0; i < getNumChildComponents(); ++i) { - tc->setVisible (false); - const int index = oldIndexes.remove (i); - owner.addChildComponent (tc, index); - --i; + ToolbarItemComponent* const tc = dynamic_cast (getChildComponent (i)); + + if (tc != 0) + { + tc->setVisible (false); + const int index = oldIndexes.remove (i); + owner->addChildComponent (tc, index); + --i; + } } - } - owner.resized(); + owner->resized(); + } } void layout (const int preferredWidth) @@ -258,7 +258,7 @@ public: juce_UseDebuggingNewOperator private: - Toolbar& owner; + Component::SafePointer owner; const int height; Array oldIndexes; @@ -890,10 +890,17 @@ void Toolbar::showCustomisationDialog (ToolbarItemFactory& factory, const int op { setEditingActive (true); + #if JUCE_DEBUG + Component::SafePointer checker (this); + #endif + ToolbarCustomisationDialog dw (factory, this, optionFlags); dw.runModalLoop(); - jassert (isValidComponent()); // ? deleting the toolbar while it's being edited? + #if JUCE_DEBUG + jassert (checker != 0); // Don't delete the toolbar while it's being customised! + #endif + setEditingActive (false); } diff --git a/src/gui/components/controls/juce_ToolbarItemComponent.cpp b/src/gui/components/controls/juce_ToolbarItemComponent.cpp index 8c027b10cf..696482a68e 100644 --- a/src/gui/components/controls/juce_ToolbarItemComponent.cpp +++ b/src/gui/components/controls/juce_ToolbarItemComponent.cpp @@ -165,7 +165,6 @@ ToolbarItemComponent::ToolbarItemComponent (const int itemId_, ToolbarItemComponent::~ToolbarItemComponent() { - jassert (overlayComp == 0 || overlayComp->isValidComponent()); overlayComp = 0; } @@ -253,7 +252,6 @@ void ToolbarItemComponent::setEditingMode (const ToolbarEditingMode newMode) if (mode == normalMode) { - jassert (overlayComp == 0 || overlayComp->isValidComponent()); overlayComp = 0; } else if (overlayComp == 0) diff --git a/src/gui/components/juce_Component.cpp b/src/gui/components/juce_Component.cpp index 2adb7ca8c1..a5ce7bebee 100644 --- a/src/gui/components/juce_Component.cpp +++ b/src/gui/components/juce_Component.cpp @@ -46,12 +46,6 @@ BEGIN_JUCE_NAMESPACE //============================================================================== #define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); -enum ComponentMessageNumbers -{ - customCommandMessage = 0x7fff0001, - exitModalStateMessage = 0x7fff0002 -}; - Component* Component::currentlyFocusedComponent = 0; @@ -353,11 +347,6 @@ bool Component::isShowing() const //============================================================================== -bool Component::isValidComponent() const -{ - return (this != 0) && isValidMessageListener(); -} - void* Component::getWindowHandle() const { const ComponentPeer* const peer = getPeer(); @@ -1264,12 +1253,6 @@ Component* Component::getTopLevelComponent() const throw() bool Component::isParentOf (const Component* possibleChild) const throw() { - if (! possibleChild->isValidComponent()) - { - jassert (possibleChild == 0); - return false; - } - while (possibleChild != 0) { possibleChild = possibleChild->parentComponent_; @@ -1392,7 +1375,27 @@ void Component::exitModalState (const int returnValue) } else { - postMessage (new Message (exitModalStateMessage, returnValue, 0, 0)); + class ExitModalStateMessage : public CallbackMessage + { + public: + ExitModalStateMessage (Component* const target_, const int result_) + : target (target_), result (result_) {} + + void messageCallback() + { + if (target != 0) + target->exitModalState (result); + } + + private: + Component::SafePointer target; + const int result; + + ExitModalStateMessage (ExitModalStateMessage&); + ExitModalStateMessage& operator= (const ExitModalStateMessage&); + }; + + (new ExitModalStateMessage (this, returnValue))->post(); } } } @@ -1770,22 +1773,21 @@ void Component::sendLookAndFeelChange() { repaint(); - lookAndFeelChanged(); - - // (it's not a great idea to do anything that would delete this component - // during the lookAndFeelChanged() callback) - jassert (isValidComponent()); - SafePointer safePointer (this); - for (int i = childComponentList_.size(); --i >= 0;) + lookAndFeelChanged(); + + if (safePointer != 0) { - childComponentList_.getUnchecked (i)->sendLookAndFeelChange(); + for (int i = childComponentList_.size(); --i >= 0;) + { + childComponentList_.getUnchecked (i)->sendLookAndFeelChange(); - if (safePointer == 0) - return; + if (safePointer == 0) + return; - i = jmin (i, childComponentList_.size()); + i = jmin (i, childComponentList_.size()); + } } } @@ -2033,13 +2035,11 @@ void Component::parentSizeChanged() void Component::addComponentListener (ComponentListener* const newListener) { - jassert (isValidComponent()); componentListeners.add (newListener); } void Component::removeComponentListener (ComponentListener* const listenerToRemove) { - jassert (isValidComponent()); componentListeners.remove (listenerToRemove); } @@ -2078,22 +2078,29 @@ void Component::paintOverChildren (Graphics&) } //============================================================================== -void Component::handleMessage (const Message& message) +void Component::postCommandMessage (const int commandId) { - if (message.intParameter1 == exitModalStateMessage) + class CustomCommandMessage : public CallbackMessage { - exitModalState (message.intParameter2); - } - else if (message.intParameter1 == customCommandMessage) - { - handleCommandMessage (message.intParameter2); - } -} + public: + CustomCommandMessage (Component* const target_, const int commandId_) + : target (target_), commandId (commandId_) {} -//============================================================================== -void Component::postCommandMessage (const int commandId) -{ - postMessage (new Message (customCommandMessage, commandId, 0, 0)); + void messageCallback() + { + if (target != 0) + target->exitModalState (commandId); + } + + private: + Component::SafePointer target; + const int commandId; + + CustomCommandMessage (CustomCommandMessage&); + CustomCommandMessage& operator= (const CustomCommandMessage&); + }; + + (new CustomCommandMessage (this, commandId))->post(); } void Component::handleCommandMessage (int) @@ -2477,9 +2484,6 @@ void Component::broughtToFront() void Component::internalBroughtToFront() { - if (! isValidComponent()) - return; - if (flags.hasHeavyweightPeerFlag) Desktop::getInstance().componentBroughtToFront (this); diff --git a/src/gui/components/juce_Component.h b/src/gui/components/juce_Component.h index 501b1a8c81..6270bb3ad4 100644 --- a/src/gui/components/juce_Component.h +++ b/src/gui/components/juce_Component.h @@ -36,7 +36,6 @@ #include "../graphics/imaging/juce_Image.h" #include "../graphics/geometry/juce_RectangleList.h" #include "../graphics/geometry/juce_BorderSize.h" -#include "../../events/juce_MessageListener.h" #include "../../events/juce_ListenerList.h" #include "../../text/juce_StringArray.h" #include "../../containers/juce_Array.h" @@ -54,8 +53,7 @@ class ComponentPeer; The base class for all JUCE user-interface objects. */ -class JUCE_API Component : public MouseListener, - public MessageListener +class JUCE_API Component : public MouseListener { public: //============================================================================== @@ -109,19 +107,6 @@ public: */ virtual void setName (const String& newName); - //============================================================================== - /** Checks whether this Component object has been deleted. - - This will check whether this object is still a valid component, or whether - it's been deleted. - - It's safe to call this on null or dangling pointers, but note that there is a - small risk if another new (but different) component has been created at the - same memory address which this one occupied, this methods can return a - false positive. - */ - bool isValidComponent() const; - //============================================================================== /** Makes the component visible or invisible. @@ -2112,16 +2097,8 @@ private: protected: /** @internal */ virtual void internalRepaint (int x, int y, int w, int h); - + /** @internal */ virtual ComponentPeer* createNewPeer (int styleFlags, void* nativeWindowToAttachTo); - - /** Overridden from the MessageListener parent class. - - You can override this if you really need to, but be sure to pass your unwanted messages up - to this base class implementation, as the Component class needs to send itself messages - to work properly. - */ - void handleMessage (const Message&); }; diff --git a/src/gui/components/juce_Desktop.cpp b/src/gui/components/juce_Desktop.cpp index f325f63eb8..f2bbbfd14d 100644 --- a/src/gui/components/juce_Desktop.cpp +++ b/src/gui/components/juce_Desktop.cpp @@ -157,10 +157,14 @@ Component* Desktop::findComponentAt (const Point& screenPosition) const for (int i = desktopComponents.size(); --i >= 0;) { Component* const c = desktopComponents.getUnchecked(i); - const Point relative (c->globalPositionToRelative (screenPosition)); - if (c->contains (relative.getX(), relative.getY())) - return c->getComponentAt (relative.getX(), relative.getY()); + if (c->isVisible()) + { + const Point relative (c->globalPositionToRelative (screenPosition)); + + if (c->contains (relative.getX(), relative.getY())) + return c->getComponentAt (relative.getX(), relative.getY()); + } } return 0; @@ -332,12 +336,10 @@ void Desktop::setKioskModeComponent (Component* componentToUse, const bool allow { if (kioskModeComponent != componentToUse) { - // agh! Don't delete a component without first stopping it being the kiosk comp - jassert (kioskModeComponent == 0 || kioskModeComponent->isValidComponent()); - // agh! Don't remove a component from the desktop if it's the kiosk comp! - jassert (kioskModeComponent == 0 || kioskModeComponent->isOnDesktop()); + // agh! Don't delete or remove a component from the desktop while it's still the kiosk component! + jassert (kioskModeComponent == 0 || ComponentPeer::getPeerFor (kioskModeComponent) != 0); - if (kioskModeComponent->isValidComponent()) + if (kioskModeComponent != 0) { juce_setKioskComponent (kioskModeComponent, false, allowMenusAndBars); @@ -348,10 +350,8 @@ void Desktop::setKioskModeComponent (Component* componentToUse, const bool allow if (kioskModeComponent != 0) { - jassert (kioskModeComponent->isValidComponent()); - // Only components that are already on the desktop can be put into kiosk mode! - jassert (kioskModeComponent->isOnDesktop()); + jassert (ComponentPeer::getPeerFor (kioskModeComponent) != 0); kioskComponentOriginalBounds = kioskModeComponent->getBounds(); diff --git a/src/gui/components/layout/juce_TabbedComponent.cpp b/src/gui/components/layout/juce_TabbedComponent.cpp index 85c541851c..219137adc3 100644 --- a/src/gui/components/layout/juce_TabbedComponent.cpp +++ b/src/gui/components/layout/juce_TabbedComponent.cpp @@ -77,8 +77,7 @@ private: TabbedComponent::TabbedComponent (const TabbedButtonBar::Orientation orientation) - : panelComponent (0), - tabDepth (30), + : tabDepth (30), outlineThickness (1), edgeIndent (0) { @@ -133,13 +132,10 @@ void TabbedComponent::clearTabs() for (int i = contentComponents.size(); --i >= 0;) { - Component* const c = contentComponents.getUnchecked(i); - - // be careful not to delete these components until they've been removed from the tab component - jassert (c == 0 || c->isValidComponent()); + Component::SafePointer& c = contentComponents.getReference (i); if (c != 0 && (bool) c->getProperties() [deleteComponentId]) - delete c; + c.deleteAndZero(); } contentComponents.clear(); @@ -166,19 +162,16 @@ void TabbedComponent::setTabName (const int tabIndex, const String& newName) void TabbedComponent::removeTab (const int tabIndex) { - Component* const c = contentComponents [tabIndex]; - - if (c != 0 && (bool) c->getProperties() [deleteComponentId]) + if (tabIndex >= 0 && tabIndex < contentComponents.size()) { - if (c == panelComponent) - panelComponent = 0; - - delete c; - } + Component::SafePointer& c = contentComponents.getReference (tabIndex); - contentComponents.remove (tabIndex); + if (c != 0 && (bool) c->getProperties() [deleteComponentId]) + c.deleteAndZero(); - tabs->removeTab (tabIndex); + contentComponents.remove (tabIndex); + tabs->removeTab (tabIndex); + } } int TabbedComponent::getNumTabs() const @@ -304,15 +297,15 @@ void TabbedComponent::resized() const Rectangle bounds (indents.subtractedFrom (getLocalBounds())); for (int i = contentComponents.size(); --i >= 0;) - if (contentComponents.getUnchecked (i) != 0) - contentComponents.getUnchecked (i)->setBounds (bounds); + if (contentComponents.getReference (i) != 0) + contentComponents.getReference (i)->setBounds (bounds); } void TabbedComponent::lookAndFeelChanged() { for (int i = contentComponents.size(); --i >= 0;) - if (contentComponents.getUnchecked (i) != 0) - contentComponents.getUnchecked (i)->lookAndFeelChanged(); + if (contentComponents.getReference (i) != 0) + contentComponents.getReference (i)->lookAndFeelChanged(); } void TabbedComponent::changeCallback (const int newCurrentTabIndex, diff --git a/src/gui/components/layout/juce_TabbedComponent.h b/src/gui/components/layout/juce_TabbedComponent.h index 007558a301..1b979aa768 100644 --- a/src/gui/components/layout/juce_TabbedComponent.h +++ b/src/gui/components/layout/juce_TabbedComponent.h @@ -228,8 +228,8 @@ protected: private: //============================================================================== - Array contentComponents; - Component* panelComponent; + Array > contentComponents; + Component::SafePointer panelComponent; int tabDepth; int outlineThickness, edgeIndent; static const Identifier deleteComponentId; diff --git a/src/gui/components/menus/juce_PopupMenu.cpp b/src/gui/components/menus/juce_PopupMenu.cpp index e26ccc9e21..462dd7aa38 100644 --- a/src/gui/components/menus/juce_PopupMenu.cpp +++ b/src/gui/components/menus/juce_PopupMenu.cpp @@ -293,12 +293,8 @@ public: ~Window() { getActiveWindows().removeValue (this); - Desktop::getInstance().removeGlobalMouseListener (this); - - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); activeSubMenu = 0; - deleteAllChildren(); } @@ -419,8 +415,6 @@ public: { if (isVisible()) { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - activeSubMenu = 0; currentChild = 0; @@ -521,8 +515,6 @@ public: if (showSubMenuFor (currentChild)) { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - if (activeSubMenu != 0 && activeSubMenu->isVisible()) activeSubMenu->selectNextItem (1); } @@ -611,7 +603,7 @@ public: if (now > timeEnteredCurrentChildComp + 100 && reallyContains (localMousePos.getX(), localMousePos.getY(), true) - && currentChild->isValidComponent() + && currentChild != 0 && (! disableMouseMoves) && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) { @@ -769,8 +761,6 @@ private: bool isOverChildren() const { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - return isVisible() && (isOver || (activeSubMenu != 0 && activeSubMenu->isOverChildren())); } @@ -1084,7 +1074,7 @@ private: void setCurrentlyHighlightedChild (PopupMenu::ItemComponent* const child) { - if (currentChild->isValidComponent()) + if (currentChild != 0) currentChild->setHighlighted (false); currentChild = child; @@ -1098,10 +1088,9 @@ private: bool showSubMenuFor (PopupMenu::ItemComponent* const childComp) { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); activeSubMenu = 0; - if (childComp->isValidComponent() && childComp->itemInfo.hasActiveSubMenu()) + if (childComp != 0 && childComp->itemInfo.hasActiveSubMenu()) { activeSubMenu = Window::create (*(childComp->itemInfo.subMenu), dismissOnMouseUp, @@ -1144,8 +1133,6 @@ private: bool isMovingTowardsMenu = false; - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()) - if (isOver && (activeSubMenu != 0) && globalMousePos != lastMouse) { // try to intelligently guess whether the user is moving the mouse towards a currently-open @@ -1206,7 +1193,7 @@ private: void triggerCurrentlyHighlightedItem() { - if (currentChild->isValidComponent() + if (currentChild != 0 && currentChild->itemInfo.canBeTriggered() && (currentChild->itemInfo.customComp == 0 || currentChild->itemInfo.customComp->isTriggeredAutomatically)) diff --git a/src/gui/components/mouse/juce_ComponentDragger.cpp b/src/gui/components/mouse/juce_ComponentDragger.cpp index 13ad874785..7b9d2993f5 100644 --- a/src/gui/components/mouse/juce_ComponentDragger.cpp +++ b/src/gui/components/mouse/juce_ComponentDragger.cpp @@ -45,7 +45,7 @@ ComponentDragger::~ComponentDragger() void ComponentDragger::startDraggingComponent (Component* const componentToDrag, ComponentBoundsConstrainer* const constrainer_) { - jassert (componentToDrag->isValidComponent()); + jassert (componentToDrag != 0); if (componentToDrag != 0) { @@ -56,7 +56,7 @@ void ComponentDragger::startDraggingComponent (Component* const componentToDrag, void ComponentDragger::dragComponent (Component* const componentToDrag, const MouseEvent& e) { - jassert (componentToDrag->isValidComponent()); + jassert (componentToDrag != 0); jassert (e.mods.isAnyMouseButtonDown()); // (the event has to be a drag event..) if (componentToDrag != 0) diff --git a/src/gui/components/mouse/juce_MouseHoverDetector.cpp b/src/gui/components/mouse/juce_MouseHoverDetector.cpp index aedcda4088..4df80ef9ef 100644 --- a/src/gui/components/mouse/juce_MouseHoverDetector.cpp +++ b/src/gui/components/mouse/juce_MouseHoverDetector.cpp @@ -59,12 +59,7 @@ void MouseHoverDetector::setHoverComponent (Component* const newSourceComponent) hasJustHovered = false; if (source != 0) - { - // ! you need to delete the hover detector before deleting its component - jassert (source->isValidComponent()); - source->removeMouseListener (&internalTimer); - } source = newSourceComponent; diff --git a/src/gui/components/special/juce_BubbleComponent.cpp b/src/gui/components/special/juce_BubbleComponent.cpp index 9d1f5f123b..31619c8d5c 100644 --- a/src/gui/components/special/juce_BubbleComponent.cpp +++ b/src/gui/components/special/juce_BubbleComponent.cpp @@ -96,7 +96,7 @@ void BubbleComponent::setAllowedPlacement (const int newPlacement) void BubbleComponent::setPosition (Component* componentToPointTo) { - jassert (componentToPointTo->isValidComponent()); + jassert (componentToPointTo != 0); Point pos; diff --git a/src/gui/components/windows/juce_ComponentPeer.cpp b/src/gui/components/windows/juce_ComponentPeer.cpp index 2d7680a904..9e72871cb0 100644 --- a/src/gui/components/windows/juce_ComponentPeer.cpp +++ b/src/gui/components/windows/juce_ComponentPeer.cpp @@ -301,7 +301,6 @@ void ComponentPeer::setConstrainer (ComponentBoundsConstrainer* const newConstra void ComponentPeer::handleMovedOrResized() { - jassert (component->isValidComponent()); updateCurrentModifiers(); const bool nowMinimised = isMinimised(); diff --git a/src/gui/components/windows/juce_ComponentPeer.h b/src/gui/components/windows/juce_ComponentPeer.h index 10cc6cdc46..3b693a64df 100644 --- a/src/gui/components/windows/juce_ComponentPeer.h +++ b/src/gui/components/windows/juce_ComponentPeer.h @@ -372,6 +372,7 @@ private: bool fakeMouseMessageSent : 1, isWindowMinimised : 1; friend class Component; + friend class Desktop; static ComponentPeer* getPeerFor (const Component* component) throw(); void setLastDragDropTarget (Component* comp); diff --git a/src/threads/juce_Thread.cpp b/src/threads/juce_Thread.cpp index a432ff50ee..57fbe7173b 100644 --- a/src/threads/juce_Thread.cpp +++ b/src/threads/juce_Thread.cpp @@ -102,6 +102,15 @@ Thread::Thread (const String& threadName) Thread::~Thread() { + /* If your thread class's destructor has been called without first stopping the thread, that + means that this partially destructed object is still performing some work - and that's not + unlikely to be a safe approach to take! + + To avoid this type of nastiness, always make sure you call stopThread() before or during + your subclass's destructor. + */ + jassert (! isThreadRunning()); + stopThread (100); }