| @@ -225,6 +225,10 @@ public: | |||
| menu.addCommandItem (commandManager, CommandIDs::closeWindow); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (commandManager, CommandIDs::goToPreviousDoc); | |||
| menu.addCommandItem (commandManager, CommandIDs::goToNextDoc); | |||
| menu.addSeparator(); | |||
| const int numDocs = jmin (50, getApp()->openDocumentManager.getNumOpenDocuments()); | |||
| for (int i = 0; i < numDocs; ++i) | |||
| @@ -46,6 +46,8 @@ namespace CommandIDs | |||
| static const int closeWindow = 0x201001; | |||
| static const int closeAllDocuments = 0x201000; | |||
| static const int goToPreviousDoc = 0x201002; | |||
| static const int goToNextDoc = 0x201003; | |||
| static const int toFront = 0x2020a0; | |||
| static const int toBack = 0x2030a1; | |||
| @@ -346,10 +346,8 @@ void MainWindowList::closeWindow (MainWindow* w) | |||
| void MainWindowList::openDocument (OpenDocumentManager::Document* doc) | |||
| { | |||
| MainWindow* const w = getOrCreateFrontmostWindow(); | |||
| w->makeVisible(); | |||
| MainWindow* w = getOrCreateFrontmostWindow(); | |||
| w->getProjectContentComponent()->showDocument (doc); | |||
| avoidSuperimposedWindows (w); | |||
| } | |||
| bool MainWindowList::openFile (const File& file) | |||
| @@ -381,11 +379,7 @@ bool MainWindowList::openFile (const File& file) | |||
| else if (file.exists()) | |||
| { | |||
| MainWindow* const w = getOrCreateFrontmostWindow(); | |||
| const bool ok = w->openFile (file); | |||
| w->makeVisible(); | |||
| avoidSuperimposedWindows (w); | |||
| return ok; | |||
| return w->openFile (file); | |||
| } | |||
| return false; | |||
| @@ -403,7 +397,12 @@ MainWindow* MainWindowList::createNewMainWindow() | |||
| MainWindow* MainWindowList::getOrCreateFrontmostWindow() | |||
| { | |||
| if (windows.size() == 0) | |||
| return createNewMainWindow(); | |||
| { | |||
| MainWindow* w = createNewMainWindow(); | |||
| avoidSuperimposedWindows (w); | |||
| w->makeVisible(); | |||
| return w; | |||
| } | |||
| for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) | |||
| { | |||
| @@ -26,9 +26,7 @@ | |||
| #include "jucer_OpenDocumentManager.h" | |||
| #include "jucer_FilePreviewComponent.h" | |||
| #include "../Code Editor/jucer_SourceCodeEditor.h" | |||
| //============================================================================== | |||
| Component* SourceCodeDocument::createEditor() { return new SourceCodeEditor (this, codeDoc); } | |||
| #include "jucer_Application.h" | |||
| //============================================================================== | |||
| @@ -113,7 +111,7 @@ void OpenDocumentManager::addListener (DocumentCloseListener* listener) | |||
| void OpenDocumentManager::removeListener (DocumentCloseListener* listener) | |||
| { | |||
| listeners.removeValue (listener); | |||
| listeners.removeFirstMatchingValue (listener); | |||
| } | |||
| //============================================================================== | |||
| @@ -160,19 +158,6 @@ OpenDocumentManager::Document* OpenDocumentManager::getOpenDocument (int index) | |||
| return documents.getUnchecked (index); | |||
| } | |||
| void OpenDocumentManager::moveDocumentToTopOfStack (Document* doc) | |||
| { | |||
| for (int i = documents.size(); --i >= 0;) | |||
| { | |||
| if (doc == documents.getUnchecked(i)) | |||
| { | |||
| documents.move (i, 0); | |||
| commandManager->commandStatusChanged(); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| FileBasedDocument::SaveResult OpenDocumentManager::saveIfNeededAndUserAgrees (OpenDocumentManager::Document* doc) | |||
| { | |||
| if (! doc->needsSaving()) | |||
| @@ -312,3 +297,77 @@ void OpenDocumentManager::fileHasBeenRenamed (const File& oldFile, const File& n | |||
| d->fileHasBeenRenamed (newFile); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| RecentDocumentList::RecentDocumentList() | |||
| { | |||
| JucerApplication::getApp()->openDocumentManager.addListener (this); | |||
| } | |||
| RecentDocumentList::~RecentDocumentList() | |||
| { | |||
| JucerApplication::getApp()->openDocumentManager.removeListener (this); | |||
| } | |||
| void RecentDocumentList::clear() | |||
| { | |||
| previousDocs.clear(); | |||
| nextDocs.clear(); | |||
| } | |||
| void RecentDocumentList::newDocumentOpened (OpenDocumentManager::Document* document) | |||
| { | |||
| if (document != getCurrentDocument()) | |||
| { | |||
| nextDocs.clear(); | |||
| previousDocs.add (document); | |||
| } | |||
| } | |||
| bool RecentDocumentList::canGoToPrevious() const | |||
| { | |||
| return previousDocs.size() > 1; | |||
| } | |||
| bool RecentDocumentList::canGoToNext() const | |||
| { | |||
| return nextDocs.size() > 0; | |||
| } | |||
| OpenDocumentManager::Document* RecentDocumentList::getPrevious() | |||
| { | |||
| if (! canGoToPrevious()) | |||
| return nullptr; | |||
| nextDocs.insert (0, previousDocs.remove (previousDocs.size() - 1)); | |||
| return previousDocs.getLast(); | |||
| } | |||
| OpenDocumentManager::Document* RecentDocumentList::getNext() | |||
| { | |||
| if (! canGoToNext()) | |||
| return nullptr; | |||
| OpenDocumentManager::Document* d = nextDocs.remove (0); | |||
| previousDocs.add (d); | |||
| return d; | |||
| } | |||
| OpenDocumentManager::Document* RecentDocumentList::getClosestPreviousDocOtherThan (OpenDocumentManager::Document* oneToAvoid) const | |||
| { | |||
| for (int i = previousDocs.size(); --i >= 0;) | |||
| if (previousDocs.getUnchecked(i) != oneToAvoid) | |||
| return previousDocs.getUnchecked(i); | |||
| return nullptr; | |||
| } | |||
| void RecentDocumentList::documentAboutToClose (OpenDocumentManager::Document* document) | |||
| { | |||
| previousDocs.removeAllInstancesOf (document); | |||
| nextDocs.removeAllInstancesOf (document); | |||
| jassert (! previousDocs.contains (document)); | |||
| jassert (! nextDocs.contains (document)); | |||
| } | |||
| @@ -65,7 +65,6 @@ public: | |||
| //============================================================================== | |||
| int getNumOpenDocuments() const; | |||
| Document* getOpenDocument (int index) const; | |||
| void moveDocumentToTopOfStack (Document* doc); | |||
| void clear(); | |||
| bool canOpenFile (const File& file); | |||
| @@ -117,72 +116,31 @@ private: | |||
| }; | |||
| //============================================================================== | |||
| class SourceCodeDocument : public OpenDocumentManager::Document | |||
| class RecentDocumentList : private OpenDocumentManager::DocumentCloseListener | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| SourceCodeDocument (Project* project_, const File& file_) | |||
| : modDetector (file_), project (project_) | |||
| { | |||
| reloadFromFile(); | |||
| } | |||
| //============================================================================== | |||
| struct Type : public OpenDocumentManager::DocumentType | |||
| { | |||
| bool canOpenFile (const File& file) { return file.hasFileExtension ("cpp;h;hpp;mm;m;c;cc;cxx;txt;inc;tcc;xml;plist;rtf;html;htm;php;py;rb;cs"); } | |||
| Document* openFile (Project* project, const File& file) { return new SourceCodeDocument (project, file); } | |||
| }; | |||
| //============================================================================== | |||
| bool loadedOk() const { return true; } | |||
| bool isForFile (const File& file) const { return getFile() == file; } | |||
| bool isForNode (const ValueTree& node) const { return false; } | |||
| bool refersToProject (Project& p) const { return project == &p; } | |||
| Project* getProject() const { return project; } | |||
| String getName() const { return getFile().getFileName(); } | |||
| String getType() const { return getFile().getFileExtension() + " file"; } | |||
| File getFile() const { return modDetector.getFile(); } | |||
| bool needsSaving() const { return codeDoc.hasChangedSinceSavePoint(); } | |||
| bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); } | |||
| void fileHasBeenRenamed (const File& newFile) { modDetector.fileHasBeenRenamed (newFile); } | |||
| void reloadFromFile() | |||
| { | |||
| modDetector.updateHash(); | |||
| RecentDocumentList(); | |||
| ~RecentDocumentList(); | |||
| ScopedPointer <InputStream> in (modDetector.getFile().createInputStream()); | |||
| void newDocumentOpened (OpenDocumentManager::Document* document); | |||
| if (in != nullptr) | |||
| codeDoc.loadFromStream (*in); | |||
| } | |||
| bool save() | |||
| { | |||
| TemporaryFile temp (modDetector.getFile()); | |||
| OpenDocumentManager::Document* getCurrentDocument() const { return previousDocs.getLast(); } | |||
| { | |||
| FileOutputStream fo (temp.getFile()); | |||
| bool canGoToPrevious() const; | |||
| bool canGoToNext() const; | |||
| if (! (fo.openedOk() && codeDoc.writeToStream (fo))) | |||
| return false; | |||
| } | |||
| OpenDocumentManager::Document* getPrevious(); | |||
| OpenDocumentManager::Document* getNext(); | |||
| if (! temp.overwriteTargetFileWithTemporary()) | |||
| return false; | |||
| OpenDocumentManager::Document* getClosestPreviousDocOtherThan (OpenDocumentManager::Document* oneToAvoid) const; | |||
| codeDoc.setSavePoint(); | |||
| modDetector.updateHash(); | |||
| return true; | |||
| } | |||
| void clear(); | |||
| Component* createEditor(); | |||
| Component* createViewer() { return createEditor(); } | |||
| private: | |||
| void documentAboutToClose (OpenDocumentManager::Document*); | |||
| protected: | |||
| FileModificationDetector modDetector; | |||
| CodeDocument codeDoc; | |||
| Project* project; | |||
| Array <OpenDocumentManager::Document*> previousDocs, nextDocs; | |||
| }; | |||
| #endif // __JUCER_OPENDOCUMENTMANAGER_JUCEHEADER__ | |||
| @@ -28,15 +28,19 @@ | |||
| //============================================================================== | |||
| SourceCodeEditor::SourceCodeEditor (OpenDocumentManager::Document* document_, CodeDocument& codeDocument) | |||
| SourceCodeEditor::SourceCodeEditor (OpenDocumentManager::Document* document_) | |||
| : DocumentEditorComponent (document_) | |||
| { | |||
| createEditor (codeDocument); | |||
| } | |||
| SourceCodeEditor::SourceCodeEditor (OpenDocumentManager::Document* document_) | |||
| : DocumentEditorComponent (document_) | |||
| SourceCodeEditor::~SourceCodeEditor() | |||
| { | |||
| getAppSettings().appearance.settings.removeListener (this); | |||
| SourceCodeDocument* doc = dynamic_cast <SourceCodeDocument*> (getDocument()); | |||
| if (doc != nullptr) | |||
| doc->updateLastPosition (*editor); | |||
| } | |||
| void SourceCodeEditor::createEditor (CodeDocument& codeDocument) | |||
| @@ -66,11 +70,6 @@ void SourceCodeEditor::setEditor (CodeEditorComponent* newEditor) | |||
| getAppSettings().appearance.settings.addListener (this); | |||
| } | |||
| SourceCodeEditor::~SourceCodeEditor() | |||
| { | |||
| getAppSettings().appearance.settings.removeListener (this); | |||
| } | |||
| void SourceCodeEditor::highlightLine (int lineNum, int characterIndex) | |||
| { | |||
| if (lineNum <= editor->getFirstLineOnScreen() | |||
| @@ -96,3 +95,52 @@ void SourceCodeEditor::valueTreeChildRemoved (ValueTree&, ValueTree&) | |||
| void SourceCodeEditor::valueTreeChildOrderChanged (ValueTree&) { updateColourScheme(); } | |||
| void SourceCodeEditor::valueTreeParentChanged (ValueTree&) { updateColourScheme(); } | |||
| void SourceCodeEditor::valueTreeRedirected (ValueTree&) { updateColourScheme(); } | |||
| //============================================================================== | |||
| Component* SourceCodeDocument::createEditor() | |||
| { | |||
| SourceCodeEditor* e = new SourceCodeEditor (this); | |||
| e->createEditor (codeDoc); | |||
| applyLastPosition (*(e->editor)); | |||
| return e; | |||
| } | |||
| void SourceCodeDocument::reloadFromFile() | |||
| { | |||
| modDetector.updateHash(); | |||
| ScopedPointer <InputStream> in (modDetector.getFile().createInputStream()); | |||
| if (in != nullptr) | |||
| codeDoc.loadFromStream (*in); | |||
| } | |||
| bool SourceCodeDocument::save() | |||
| { | |||
| TemporaryFile temp (modDetector.getFile()); | |||
| { | |||
| FileOutputStream fo (temp.getFile()); | |||
| if (! (fo.openedOk() && codeDoc.writeToStream (fo))) | |||
| return false; | |||
| } | |||
| if (! temp.overwriteTargetFileWithTemporary()) | |||
| return false; | |||
| codeDoc.setSavePoint(); | |||
| modDetector.updateHash(); | |||
| return true; | |||
| } | |||
| void SourceCodeDocument::updateLastPosition (CodeEditorComponent& editor) | |||
| { | |||
| lastState = new CodeEditorComponent::State (editor); | |||
| } | |||
| void SourceCodeDocument::applyLastPosition (CodeEditorComponent& editor) const | |||
| { | |||
| if (lastState != nullptr) | |||
| lastState->restoreState (editor); | |||
| } | |||
| @@ -29,12 +29,60 @@ | |||
| #include "../Project/jucer_Project.h" | |||
| #include "../Application/jucer_DocumentEditorComponent.h" | |||
| //============================================================================== | |||
| class SourceCodeDocument : public OpenDocumentManager::Document | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| SourceCodeDocument (Project* project_, const File& file_) | |||
| : modDetector (file_), project (project_) | |||
| { | |||
| reloadFromFile(); | |||
| } | |||
| //============================================================================== | |||
| struct Type : public OpenDocumentManager::DocumentType | |||
| { | |||
| bool canOpenFile (const File& file) { return file.hasFileExtension ("cpp;h;hpp;mm;m;c;cc;cxx;txt;inc;tcc;xml;plist;rtf;html;htm;php;py;rb;cs"); } | |||
| Document* openFile (Project* project, const File& file) { return new SourceCodeDocument (project, file); } | |||
| }; | |||
| //============================================================================== | |||
| bool loadedOk() const { return true; } | |||
| bool isForFile (const File& file) const { return getFile() == file; } | |||
| bool isForNode (const ValueTree& node) const { return false; } | |||
| bool refersToProject (Project& p) const { return project == &p; } | |||
| Project* getProject() const { return project; } | |||
| String getName() const { return getFile().getFileName(); } | |||
| String getType() const { return getFile().getFileExtension() + " file"; } | |||
| File getFile() const { return modDetector.getFile(); } | |||
| bool needsSaving() const { return codeDoc.hasChangedSinceSavePoint(); } | |||
| bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); } | |||
| void fileHasBeenRenamed (const File& newFile) { modDetector.fileHasBeenRenamed (newFile); } | |||
| void reloadFromFile(); | |||
| bool save(); | |||
| Component* createEditor(); | |||
| Component* createViewer() { return createEditor(); } | |||
| void updateLastPosition (CodeEditorComponent& editor); | |||
| void applyLastPosition (CodeEditorComponent& editor) const; | |||
| protected: | |||
| FileModificationDetector modDetector; | |||
| CodeDocument codeDoc; | |||
| Project* project; | |||
| ScopedPointer<CodeEditorComponent::State> lastState; | |||
| }; | |||
| //============================================================================== | |||
| class SourceCodeEditor : public DocumentEditorComponent, | |||
| private ValueTree::Listener | |||
| { | |||
| public: | |||
| SourceCodeEditor (OpenDocumentManager::Document* document, CodeDocument& codeDocument); | |||
| SourceCodeEditor (OpenDocumentManager::Document* document); | |||
| ~SourceCodeEditor(); | |||
| @@ -43,9 +91,9 @@ public: | |||
| void highlightLine (int lineNum, int characterIndex); | |||
| private: | |||
| ScopedPointer<CodeEditorComponent> editor; | |||
| private: | |||
| void resized(); | |||
| void valueTreePropertyChanged (ValueTree&, const Identifier&); | |||
| @@ -102,6 +102,7 @@ ProjectContentComponent::~ProjectContentComponent() | |||
| { | |||
| setProject (nullptr); | |||
| contentView = nullptr; | |||
| removeChildComponent (&bubbleMessage); | |||
| jassert (getNumChildComponents() <= 1); | |||
| } | |||
| @@ -236,16 +237,25 @@ bool ProjectContentComponent::showEditorForFile (const File& f) | |||
| || showDocument (JucerApplication::getApp()->openDocumentManager.openFile (project, f)); | |||
| } | |||
| File ProjectContentComponent::getCurrentFile() const | |||
| { | |||
| return currentDocument != nullptr ? currentDocument->getFile() | |||
| : File::nonexistent; | |||
| } | |||
| bool ProjectContentComponent::showDocument (OpenDocumentManager::Document* doc) | |||
| { | |||
| if (doc == nullptr) | |||
| return false; | |||
| JucerApplication::getApp()->openDocumentManager.moveDocumentToTopOfStack (doc); | |||
| if (doc->hasFileBeenModifiedExternally()) | |||
| doc->reloadFromFile(); | |||
| if (doc == getCurrentDocument()) | |||
| return true; | |||
| recentDocumentList.newDocumentOpened (doc); | |||
| return setEditorComponent (doc->createEditor(), doc); | |||
| } | |||
| @@ -255,18 +265,27 @@ void ProjectContentComponent::hideEditor() | |||
| contentView = nullptr; | |||
| updateMainWindowTitle(); | |||
| commandManager->commandStatusChanged(); | |||
| recentDocumentList.clear(); | |||
| } | |||
| void ProjectContentComponent::hideDocument (OpenDocumentManager::Document* doc) | |||
| { | |||
| if (doc == currentDocument) | |||
| hideEditor(); | |||
| { | |||
| OpenDocumentManager::Document* replacement = recentDocumentList.getClosestPreviousDocOtherThan (doc); | |||
| if (replacement != nullptr) | |||
| showDocument (replacement); | |||
| else | |||
| hideEditor(); | |||
| } | |||
| } | |||
| bool ProjectContentComponent::setEditorComponent (Component* editor, OpenDocumentManager::Document* doc) | |||
| { | |||
| if (editor != nullptr) | |||
| { | |||
| contentView = nullptr; | |||
| contentView = editor; | |||
| currentDocument = doc; | |||
| addAndMakeVisible (editor); | |||
| @@ -274,6 +293,7 @@ bool ProjectContentComponent::setEditorComponent (Component* editor, OpenDocumen | |||
| updateMainWindowTitle(); | |||
| commandManager->commandStatusChanged(); | |||
| editor->grabKeyboardFocus(); | |||
| return true; | |||
| } | |||
| @@ -281,6 +301,16 @@ bool ProjectContentComponent::setEditorComponent (Component* editor, OpenDocumen | |||
| return false; | |||
| } | |||
| bool ProjectContentComponent::goToPreviousFile() | |||
| { | |||
| return showDocument (recentDocumentList.getPrevious()); | |||
| } | |||
| bool ProjectContentComponent::goToNextFile() | |||
| { | |||
| return showDocument (recentDocumentList.getNext()); | |||
| } | |||
| void ProjectContentComponent::updateMainWindowTitle() | |||
| { | |||
| MainWindow* mw = findParentComponentOfClass<MainWindow>(); | |||
| @@ -314,6 +344,8 @@ void ProjectContentComponent::getAllCommands (Array <CommandID>& commands) | |||
| CommandIDs::openInIDE, | |||
| CommandIDs::saveAndOpenInIDE, | |||
| CommandIDs::showProjectSettings, | |||
| CommandIDs::goToPreviousDoc, | |||
| CommandIDs::goToNextDoc, | |||
| StandardApplicationCommandIDs::del }; | |||
| commands.addArray (ids, numElementsInArray (ids)); | |||
| @@ -361,6 +393,26 @@ void ProjectContentComponent::getCommandInfo (const CommandID commandID, Applica | |||
| #endif | |||
| break; | |||
| case CommandIDs::goToPreviousDoc: | |||
| result.setInfo ("Previous Document", "Go to previous document", CommandCategories::general, 0); | |||
| result.setActive (recentDocumentList.canGoToPrevious()); | |||
| #if JUCE_MAC | |||
| result.defaultKeypresses.add (KeyPress (KeyPress::leftKey, ModifierKeys::commandModifier | ModifierKeys::ctrlModifier, 0)); | |||
| #else | |||
| result.defaultKeypresses.add (KeyPress (KeyPress::leftKey, ModifierKeys::ctrlModifier | ModifierKeys::shiftModifier, 0)); | |||
| #endif | |||
| break; | |||
| case CommandIDs::goToNextDoc: | |||
| result.setInfo ("Next Document", "Go to next document", CommandCategories::general, 0); | |||
| result.setActive (recentDocumentList.canGoToNext()); | |||
| #if JUCE_MAC | |||
| result.defaultKeypresses.add (KeyPress (KeyPress::rightKey, ModifierKeys::commandModifier | ModifierKeys::ctrlModifier, 0)); | |||
| #else | |||
| result.defaultKeypresses.add (KeyPress (KeyPress::rightKey, ModifierKeys::ctrlModifier | ModifierKeys::shiftModifier, 0)); | |||
| #endif | |||
| break; | |||
| case CommandIDs::openInIDE: | |||
| #if JUCE_MAC | |||
| result.setInfo ("Open in XCode...", | |||
| @@ -449,6 +501,14 @@ bool ProjectContentComponent::perform (const InvocationInfo& info) | |||
| JucerApplication::getApp()->openDocumentManager.closeDocument (currentDocument, true); | |||
| break; | |||
| case CommandIDs::goToPreviousDoc: | |||
| goToPreviousFile(); | |||
| break; | |||
| case CommandIDs::goToNextDoc: | |||
| goToNextFile(); | |||
| break; | |||
| case CommandIDs::openInIDE: | |||
| if (project != nullptr) | |||
| { | |||
| @@ -35,7 +35,7 @@ class ProjectTreeViewBase; | |||
| */ | |||
| class ProjectContentComponent : public Component, | |||
| public ApplicationCommandTarget, | |||
| public ChangeListener | |||
| private ChangeListener | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| @@ -47,21 +47,24 @@ public: | |||
| void saveTreeViewState(); | |||
| bool showEditorForFile (const File& f); | |||
| File getCurrentFile() const; | |||
| bool showDocument (OpenDocumentManager::Document* doc); | |||
| void hideDocument (OpenDocumentManager::Document* doc); | |||
| OpenDocumentManager::Document* getCurrentDocument() const { return currentDocument; } | |||
| void hideEditor(); | |||
| bool setEditorComponent (Component* editor, OpenDocumentManager::Document* doc); | |||
| Component* getEditorComponent() const { return contentView; } | |||
| OpenDocumentManager::Document* getCurrentDocument() const { return currentDocument; } | |||
| File getCurrentFile() const { return currentDocument != nullptr ? currentDocument->getFile() : File::nonexistent; } | |||
| bool goToPreviousFile(); | |||
| bool goToNextFile(); | |||
| void updateMissingFileStatuses(); | |||
| virtual void createProjectTabs(); | |||
| void showBubbleMessage (const Rectangle<int>& pos, const String& text); | |||
| void changeListenerCallback (ChangeBroadcaster*); | |||
| //============================================================================== | |||
| ApplicationCommandTarget* getNextCommandTarget(); | |||
| void getAllCommands (Array <CommandID>& commands); | |||
| @@ -76,15 +79,16 @@ public: | |||
| protected: | |||
| Project* project; | |||
| OpenDocumentManager::Document* currentDocument; | |||
| RecentDocumentList recentDocumentList; | |||
| TabbedComponent treeViewTabs; | |||
| ScopedPointer<ResizableEdgeComponent> resizerBar; | |||
| ScopedPointer<Component> contentView; | |||
| ComponentBoundsConstrainer treeSizeConstrainer; | |||
| BubbleMessageComponent bubbleMessage; | |||
| void changeListenerCallback (ChangeBroadcaster*); | |||
| void updateMainWindowTitle(); | |||
| bool reinvokeCommandAfterClosingPropertyEditors (const InvocationInfo&); | |||
| bool canProjectBeLaunched() const; | |||
| @@ -62,7 +62,7 @@ void AudioProcessor::addListener (AudioProcessorListener* const newListener) | |||
| void AudioProcessor::removeListener (AudioProcessorListener* const listenerToRemove) | |||
| { | |||
| const ScopedLock sl (listenerLock); | |||
| listeners.removeValue (listenerToRemove); | |||
| listeners.removeFirstMatchingValue (listenerToRemove); | |||
| } | |||
| void AudioProcessor::setPlayConfigDetails (const int numIns, | |||
| @@ -43,33 +43,56 @@ struct TextEditorKeyMapper | |||
| */ | |||
| static bool invokeKeyFunction (CallbackClass& target, const KeyPress& key) | |||
| { | |||
| const bool isShiftDown = key.getModifiers().isShiftDown(); | |||
| const bool ctrlOrAltDown = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown(); | |||
| const ModifierKeys& mods = key.getModifiers(); | |||
| const bool isShiftDown = mods.isShiftDown(); | |||
| const bool ctrlOrAltDown = mods.isCtrlDown() || mods.isAltDown(); | |||
| int numCtrlAltCommandKeys = 0; | |||
| if (mods.isCtrlDown()) ++numCtrlAltCommandKeys; | |||
| if (mods.isAltDown()) ++numCtrlAltCommandKeys; | |||
| if (key == KeyPress (KeyPress::downKey, ModifierKeys::ctrlModifier, 0) && target.scrollUp()) return true; | |||
| if (key == KeyPress (KeyPress::upKey, ModifierKeys::ctrlModifier, 0) && target.scrollDown()) return true; | |||
| #if JUCE_MAC | |||
| if (key.getModifiers().isCommandDown()) | |||
| if (mods.isCommandDown() && ! ctrlOrAltDown) | |||
| { | |||
| if (key.isKeyCode (KeyPress::upKey)) return target.moveCaretToTop (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::downKey)) return target.moveCaretToEnd (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::leftKey)) return target.moveCaretToStartOfLine (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::rightKey)) return target.moveCaretToEndOfLine (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::rightKey)) return target.moveCaretToEndOfLine (isShiftDown); | |||
| } | |||
| if (mods.isCommandDown()) | |||
| ++numCtrlAltCommandKeys; | |||
| #endif | |||
| if (key.isKeyCode (KeyPress::upKey)) return target.moveCaretUp (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::downKey)) return target.moveCaretDown (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::leftKey)) return target.moveCaretLeft (ctrlOrAltDown, isShiftDown); | |||
| if (key.isKeyCode (KeyPress::rightKey)) return target.moveCaretRight (ctrlOrAltDown, isShiftDown); | |||
| if (key.isKeyCode (KeyPress::pageUpKey)) return target.pageUp (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::pageDownKey)) return target.pageDown (isShiftDown); | |||
| if (numCtrlAltCommandKeys < 2) | |||
| { | |||
| if (key.isKeyCode (KeyPress::leftKey)) return target.moveCaretLeft (ctrlOrAltDown, isShiftDown); | |||
| if (key.isKeyCode (KeyPress::rightKey)) return target.moveCaretRight (ctrlOrAltDown, isShiftDown); | |||
| if (key.isKeyCode (KeyPress::homeKey)) return ctrlOrAltDown ? target.moveCaretToTop (isShiftDown) | |||
| : target.moveCaretToStartOfLine (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::endKey)) return ctrlOrAltDown ? target.moveCaretToEnd (isShiftDown) | |||
| : target.moveCaretToEndOfLine (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::homeKey)) return ctrlOrAltDown ? target.moveCaretToTop (isShiftDown) | |||
| : target.moveCaretToStartOfLine (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::endKey)) return ctrlOrAltDown ? target.moveCaretToEnd (isShiftDown) | |||
| : target.moveCaretToEndOfLine (isShiftDown); | |||
| } | |||
| if (numCtrlAltCommandKeys == 0) | |||
| { | |||
| if (key.isKeyCode (KeyPress::upKey)) return target.moveCaretUp (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::downKey)) return target.moveCaretDown (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::pageUpKey)) return target.pageUp (isShiftDown); | |||
| if (key.isKeyCode (KeyPress::pageDownKey)) return target.pageDown (isShiftDown); | |||
| } | |||
| if (numCtrlAltCommandKeys < 2) | |||
| { | |||
| if (key.isKeyCode (KeyPress::backspaceKey)) return target.deleteBackwards (ctrlOrAltDown); | |||
| if (key.isKeyCode (KeyPress::deleteKey)) return target.deleteForwards (ctrlOrAltDown); | |||
| } | |||
| if (key == KeyPress ('c', ModifierKeys::commandModifier, 0) | |||
| || key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0)) | |||
| @@ -83,9 +106,6 @@ struct TextEditorKeyMapper | |||
| || key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0)) | |||
| return target.pasteFromClipboard(); | |||
| if (key.isKeyCode (KeyPress::backspaceKey)) return target.deleteBackwards (ctrlOrAltDown); | |||
| if (key.isKeyCode (KeyPress::deleteKey)) return target.deleteForwards (ctrlOrAltDown); | |||
| if (key == KeyPress ('a', ModifierKeys::commandModifier, 0)) | |||
| return target.selectAll(); | |||