| @@ -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 <ProjectTreeViewBase*> (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 <ProjectTreeViewBase*> (tree->getRootItem()); | |||
| if (pg != 0) | |||
| pg->showRenameBox(); | |||
| { | |||
| pg = pg->findTreeViewItem (itemToRename); | |||
| if (pg != 0) | |||
| pg->showRenameBox(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| TreeView* tree; | |||
| Project::Item itemToRename; | |||
| }; | |||
| private: | |||
| Component::SafePointer<TreeView> tree; | |||
| Project::Item itemToRename; | |||
| }; | |||
| void ProjectTreeViewBase::triggerAsyncRename (const Project::Item& itemToRename) | |||
| { | |||
| (new RenameMessage (getOwnerView(), itemToRename))->post(); | |||
| } | |||
| @@ -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 <MainHostWindow> mainWindow; | |||
| }; | |||
| @@ -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 | |||
| @@ -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<Component> 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<Component> 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<Component> 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<int>& screenPosition) const | |||
| for (int i = desktopComponents.size(); --i >= 0;) | |||
| { | |||
| Component* const c = desktopComponents.getUnchecked(i); | |||
| const Point<int> relative (c->globalPositionToRelative (screenPosition)); | |||
| if (c->contains (relative.getX(), relative.getY())) | |||
| return c->getComponentAt (relative.getX(), relative.getY()); | |||
| if (c->isVisible()) | |||
| { | |||
| const Point<int> 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 <ToolbarItemComponent*> (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 <ToolbarItemComponent*> (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<Toolbar> owner; | |||
| const int height; | |||
| Array <int> oldIndexes; | |||
| @@ -55745,10 +55765,17 @@ void Toolbar::showCustomisationDialog (ToolbarItemFactory& factory, const int op | |||
| { | |||
| setEditingActive (true); | |||
| #if JUCE_DEBUG | |||
| Component::SafePointer<Component> 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<Component>& 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<Component>& 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<int> 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<int> 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() | |||
| @@ -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 <Component*> contentComponents; | |||
| Component* panelComponent; | |||
| Array <Component::SafePointer<Component> > contentComponents; | |||
| Component::SafePointer<Component> 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); | |||
| @@ -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() | |||
| @@ -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); | |||
| @@ -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)); | |||
| } | |||
| @@ -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. | |||
| @@ -51,7 +51,7 @@ public: | |||
| CallbackMessage() throw(); | |||
| /** Destructor. */ | |||
| ~CallbackMessage() throw(); | |||
| ~CallbackMessage(); | |||
| //============================================================================== | |||
| /** Called when the message is delivered. | |||
| @@ -50,7 +50,7 @@ Message::Message (const int intParameter1_, | |||
| { | |||
| } | |||
| Message::~Message() throw() | |||
| Message::~Message() | |||
| { | |||
| } | |||
| @@ -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 | |||
| @@ -87,7 +87,7 @@ void MessageManager::postMessageToQueue (Message* const message) | |||
| //============================================================================== | |||
| CallbackMessage::CallbackMessage() throw() {} | |||
| CallbackMessage::~CallbackMessage() throw() {} | |||
| CallbackMessage::~CallbackMessage() {} | |||
| void CallbackMessage::post() | |||
| { | |||
| @@ -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 <ToolbarItemComponent*> (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 <ToolbarItemComponent*> (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<Toolbar> owner; | |||
| const int height; | |||
| Array <int> oldIndexes; | |||
| @@ -890,10 +890,17 @@ void Toolbar::showCustomisationDialog (ToolbarItemFactory& factory, const int op | |||
| { | |||
| setEditingActive (true); | |||
| #if JUCE_DEBUG | |||
| Component::SafePointer<Component> 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); | |||
| } | |||
| @@ -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) | |||
| @@ -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<Component> 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<Component> 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<Component> 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); | |||
| @@ -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&); | |||
| }; | |||
| @@ -157,10 +157,14 @@ Component* Desktop::findComponentAt (const Point<int>& screenPosition) const | |||
| for (int i = desktopComponents.size(); --i >= 0;) | |||
| { | |||
| Component* const c = desktopComponents.getUnchecked(i); | |||
| const Point<int> relative (c->globalPositionToRelative (screenPosition)); | |||
| if (c->contains (relative.getX(), relative.getY())) | |||
| return c->getComponentAt (relative.getX(), relative.getY()); | |||
| if (c->isVisible()) | |||
| { | |||
| const Point<int> 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(); | |||
| @@ -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<Component>& 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<Component>& 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<int> 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, | |||
| @@ -228,8 +228,8 @@ protected: | |||
| private: | |||
| //============================================================================== | |||
| Array <Component*> contentComponents; | |||
| Component* panelComponent; | |||
| Array <Component::SafePointer<Component> > contentComponents; | |||
| Component::SafePointer<Component> panelComponent; | |||
| int tabDepth; | |||
| int outlineThickness, edgeIndent; | |||
| static const Identifier deleteComponentId; | |||
| @@ -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)) | |||
| @@ -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) | |||
| @@ -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; | |||
| @@ -96,7 +96,7 @@ void BubbleComponent::setAllowedPlacement (const int newPlacement) | |||
| void BubbleComponent::setPosition (Component* componentToPointTo) | |||
| { | |||
| jassert (componentToPointTo->isValidComponent()); | |||
| jassert (componentToPointTo != 0); | |||
| Point<int> pos; | |||
| @@ -301,7 +301,6 @@ void ComponentPeer::setConstrainer (ComponentBoundsConstrainer* const newConstra | |||
| void ComponentPeer::handleMovedOrResized() | |||
| { | |||
| jassert (component->isValidComponent()); | |||
| updateCurrentModifiers(); | |||
| const bool nowMinimised = isMinimised(); | |||
| @@ -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); | |||
| @@ -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); | |||
| } | |||