| @@ -72,6 +72,12 @@ public: | |||
| commandManager = new ApplicationCommandManager(); | |||
| commandManager->registerAllCommandsForTarget (this); | |||
| { | |||
| CodeDocument doc; | |||
| CodeEditorComponent ed (doc, nullptr); | |||
| commandManager->registerAllCommandsForTarget (&ed); | |||
| } | |||
| menuModel = new MainMenuModel(); | |||
| doExtraInitialisation(); | |||
| @@ -262,13 +268,10 @@ public: | |||
| menu.addCommandItem (commandManager, StandardApplicationCommandIDs::selectAll); | |||
| menu.addCommandItem (commandManager, StandardApplicationCommandIDs::deselectAll); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (commandManager, CommandIDs::toFront); | |||
| menu.addCommandItem (commandManager, CommandIDs::toBack); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (commandManager, CommandIDs::group); | |||
| menu.addCommandItem (commandManager, CommandIDs::ungroup); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (commandManager, CommandIDs::bringBackLostItems); | |||
| menu.addCommandItem (commandManager, CommandIDs::showFindPanel); | |||
| menu.addCommandItem (commandManager, CommandIDs::findSelection); | |||
| menu.addCommandItem (commandManager, CommandIDs::findNext); | |||
| menu.addCommandItem (commandManager, CommandIDs::findPrevious); | |||
| } | |||
| virtual void createViewMenu (PopupMenu& menu) | |||
| @@ -331,7 +334,6 @@ public: | |||
| const CommandID ids[] = { CommandIDs::newProject, | |||
| CommandIDs::open, | |||
| CommandIDs::showPrefs, | |||
| CommandIDs::closeAllDocuments, | |||
| CommandIDs::saveAll, | |||
| CommandIDs::updateModules, | |||
| @@ -355,11 +357,6 @@ public: | |||
| result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0)); | |||
| break; | |||
| case CommandIDs::showPrefs: | |||
| result.setInfo ("Preferences...", "Shows the preferences panel.", CommandCategories::general, 0); | |||
| result.defaultKeypresses.add (KeyPress (',', ModifierKeys::commandModifier, 0)); | |||
| break; | |||
| case CommandIDs::showAppearanceSettings: | |||
| result.setInfo ("Fonts and Colours...", "Shows the appearance settings window.", CommandCategories::general, 0); | |||
| break; | |||
| @@ -394,7 +391,6 @@ public: | |||
| { | |||
| case CommandIDs::newProject: createNewProject(); break; | |||
| case CommandIDs::open: askUserToOpenFile(); break; | |||
| case CommandIDs::showPrefs: showPrefsPanel(); break; | |||
| case CommandIDs::saveAll: openDocumentManager.saveAll(); break; | |||
| case CommandIDs::closeAllDocuments: closeAllDocuments (true); break; | |||
| case CommandIDs::showUTF8Tool: showUTF8ToolWindow (utf8Window); break; | |||
| @@ -407,11 +403,6 @@ public: | |||
| } | |||
| //============================================================================== | |||
| void showPrefsPanel() | |||
| { | |||
| jassertfalse; | |||
| } | |||
| void createNewProject() | |||
| { | |||
| if (makeSureUserHasSelectedModuleFolder()) | |||
| @@ -504,8 +495,7 @@ private: | |||
| stopTimer(); | |||
| delete this; | |||
| JUCEApplication* app = JUCEApplication::getInstance(); | |||
| if (app != nullptr) | |||
| if (JUCEApplication* app = JUCEApplication::getInstance()) | |||
| app->systemRequestedQuit(); | |||
| } | |||
| @@ -37,53 +37,27 @@ namespace CommandIDs | |||
| closeProject = 0x200051, | |||
| saveProject = 0x200060, | |||
| saveAll = 0x200080, | |||
| openInIDE = 0x200072, | |||
| saveAndOpenInIDE = 0x200073, | |||
| updateModules = 0x200075, | |||
| showUTF8Tool = 0x200076, | |||
| showAppearanceSettings = 0x200077, | |||
| showConfigPanel = 0x200074, | |||
| showFilePanel = 0x200078, | |||
| saveAll = 0x200080, | |||
| closeWindow = 0x201001, | |||
| closeAllDocuments = 0x201000, | |||
| goToPreviousDoc = 0x201002, | |||
| goToNextDoc = 0x201003, | |||
| goToCounterpart = 0x201004, | |||
| deleteSelectedItem = 0x201005, | |||
| toFront = 0x2020a0, | |||
| toBack = 0x2030a1, | |||
| showOrHideProperties = 0x2030b0, | |||
| showOrHideTree = 0x2030b1, | |||
| showOrHideMarkers = 0x2030b2, | |||
| toggleSnapping = 0x2030b3, | |||
| makeLineSegment = 0x2030c0, | |||
| makeCubicSegment = 0x2030c1, | |||
| breakSegment = 0x2030c2, | |||
| pointModeCorner = 0x2030c3, | |||
| pointModeRounded = 0x2030c4, | |||
| pointModeSymmetric = 0x2030c5, | |||
| group = 0x202170, | |||
| ungroup = 0x202180, | |||
| showPrefs = 0x2020c0, | |||
| useTabbedWindows = 0x2020d0, | |||
| showGrid = 0x2020e0, | |||
| enableSnapToGrid = 0x2020f0, | |||
| zoomIn = 0x202130, | |||
| zoomOut = 0x202140, | |||
| zoomNormal = 0x202150, | |||
| spaceBarDrag = 0x202160, | |||
| bringBackLostItems = 0x202120, | |||
| newDocumentBase = 0x322010, | |||
| newComponentBase = 0x302010, | |||
| newElementBase = 0x312010 | |||
| showFindPanel = 0x2010a0, | |||
| findSelection = 0x2010a1, | |||
| findNext = 0x2010a2, | |||
| findPrevious = 0x2010a3 | |||
| }; | |||
| } | |||
| @@ -259,7 +259,7 @@ void MainWindow::showNewProjectWizard() | |||
| //============================================================================== | |||
| ApplicationCommandTarget* MainWindow::getNextCommandTarget() | |||
| { | |||
| return 0; | |||
| return nullptr; | |||
| } | |||
| void MainWindow::getAllCommands (Array <CommandID>& commands) | |||
| @@ -106,9 +106,7 @@ SourceCodeEditor::~SourceCodeEditor() | |||
| { | |||
| getAppSettings().appearance.settings.removeListener (this); | |||
| SourceCodeDocument* doc = dynamic_cast <SourceCodeDocument*> (getDocument()); | |||
| if (doc != nullptr) | |||
| if (SourceCodeDocument* doc = dynamic_cast <SourceCodeDocument*> (getDocument())) | |||
| doc->updateLastState (*editor); | |||
| } | |||
| @@ -176,6 +174,7 @@ static CPlusPlusCodeTokeniser cppTokeniser; | |||
| CppCodeEditorComponent::CppCodeEditorComponent (const File& f, CodeDocument& codeDocument) | |||
| : CodeEditorComponent (codeDocument, &cppTokeniser), file (f) | |||
| { | |||
| setCommandManager (commandManager); | |||
| } | |||
| void CppCodeEditorComponent::handleReturnKey() | |||
| @@ -535,7 +535,7 @@ void ProjectContentComponent::getAllCommands (Array <CommandID>& commands) | |||
| CommandIDs::goToPreviousDoc, | |||
| CommandIDs::goToNextDoc, | |||
| CommandIDs::goToCounterpart, | |||
| StandardApplicationCommandIDs::del }; | |||
| CommandIDs::deleteSelectedItem }; | |||
| commands.addArray (ids, numElementsInArray (ids)); | |||
| } | |||
| @@ -655,7 +655,7 @@ void ProjectContentComponent::getCommandInfo (const CommandID commandID, Applica | |||
| result.defaultKeypresses.add (KeyPress ('i', ModifierKeys::commandModifier, 0)); | |||
| break; | |||
| case StandardApplicationCommandIDs::del: | |||
| case CommandIDs::deleteSelectedItem: | |||
| result.setInfo ("Delete Selected File", String::empty, CommandCategories::general, 0); | |||
| result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0)); | |||
| result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0)); | |||
| @@ -712,7 +712,7 @@ bool ProjectContentComponent::perform (const InvocationInfo& info) | |||
| case CommandIDs::openInIDE: openInIDE(); break; | |||
| case StandardApplicationCommandIDs::del: deleteSelectedTreeItems(); break; | |||
| case CommandIDs::deleteSelectedItem: deleteSelectedTreeItems(); break; | |||
| case CommandIDs::saveAndOpenInIDE: | |||
| if (saveProject()) | |||
| @@ -75,12 +75,8 @@ void GroupTreeViewItem::moveSelectedItemsTo (OwnedArray <Project::Item>& selecte | |||
| void GroupTreeViewItem::checkFileStatus() | |||
| { | |||
| for (int i = 0; i < getNumSubItems(); ++i) | |||
| { | |||
| ProjectTreeViewBase* p = dynamic_cast <ProjectTreeViewBase*> (getSubItem(i)); | |||
| if (p != nullptr) | |||
| if (ProjectTreeViewBase* p = dynamic_cast <ProjectTreeViewBase*> (getSubItem(i))) | |||
| p->checkFileStatus(); | |||
| } | |||
| } | |||
| ProjectTreeViewBase* GroupTreeViewItem::createSubItem (const Project::Item& child) | |||
| @@ -97,9 +93,7 @@ ProjectTreeViewBase* GroupTreeViewItem::createSubItem (const Project::Item& chil | |||
| void GroupTreeViewItem::showDocument() | |||
| { | |||
| ProjectContentComponent* pcc = getProjectContentComponent(); | |||
| if (pcc != nullptr) | |||
| if (ProjectContentComponent* pcc = getProjectContentComponent()) | |||
| pcc->setEditorComponent (new GroupInformationComponent (item), nullptr); | |||
| } | |||
| @@ -243,8 +237,7 @@ void SourceFileTreeViewItem::showPopupMenu() | |||
| { | |||
| PopupMenu m; | |||
| GroupTreeViewItem* parentGroup = dynamic_cast <GroupTreeViewItem*> (getParentProjectItem()); | |||
| if (parentGroup != nullptr) | |||
| if (GroupTreeViewItem* parentGroup = dynamic_cast <GroupTreeViewItem*> (getParentProjectItem())) | |||
| { | |||
| parentGroup->addCreateFileMenuItems (m); | |||
| m.addSeparator(); | |||
| @@ -267,8 +260,6 @@ void SourceFileTreeViewItem::showPopupMenu() | |||
| void SourceFileTreeViewItem::handlePopupMenuResult (int resultCode) | |||
| { | |||
| GroupTreeViewItem* parentGroup = dynamic_cast <GroupTreeViewItem*> (getParentProjectItem()); | |||
| switch (resultCode) | |||
| { | |||
| case 1: getFile().startAsProcess(); break; | |||
| @@ -277,7 +268,7 @@ void SourceFileTreeViewItem::handlePopupMenuResult (int resultCode) | |||
| case 4: triggerAsyncRename (item); break; | |||
| default: | |||
| if (parentGroup != nullptr) | |||
| if (GroupTreeViewItem* parentGroup = dynamic_cast <GroupTreeViewItem*> (getParentProjectItem())) | |||
| parentGroup->processCreateFileMenuItem (resultCode); | |||
| break; | |||
| @@ -49,17 +49,10 @@ public: | |||
| const ModifierKeys mods (ModifierKeys::getCurrentModifiers()); | |||
| if (! mods.isAnyMouseButtonDown()) | |||
| { | |||
| Component* comp = Desktop::getInstance().findComponentAt (screenPos); | |||
| if (comp != nullptr) | |||
| { | |||
| ComponentPeer* const peer = comp->getPeer(); | |||
| if (peer != nullptr && ! peer->isFocused()) | |||
| peer->handleMouseEvent (0, screenPos - peer->getScreenPosition(), mods, Time::currentTimeMillis()); | |||
| } | |||
| } | |||
| if (Component* const comp = Desktop::getInstance().findComponentAt (screenPos)) | |||
| if (ComponentPeer* const peer = comp->getPeer()) | |||
| if (! peer->isFocused()) | |||
| peer->handleMouseEvent (0, screenPos - peer->getScreenPosition(), mods, Time::currentTimeMillis()); | |||
| } | |||
| } | |||
| @@ -27,7 +27,6 @@ ApplicationCommandManager::ApplicationCommandManager() | |||
| : firstTarget (nullptr) | |||
| { | |||
| keyMappings = new KeyPressMappingSet (this); | |||
| Desktop::getInstance().addFocusChangeListener (this); | |||
| } | |||
| @@ -65,7 +64,7 @@ void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& n | |||
| } | |||
| else | |||
| { | |||
| // trying to re-register the same command with different parameters? | |||
| // trying to re-register the same command ID with different parameters? | |||
| jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName | |||
| && (newCommand.description == getCommandForID (newCommand.commandID)->description || newCommand.description.isEmpty()) | |||
| && newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName | |||
| @@ -169,26 +168,24 @@ bool ApplicationCommandManager::invokeDirectly (const CommandID commandID, const | |||
| return invoke (info, asynchronously); | |||
| } | |||
| bool ApplicationCommandManager::invoke (const ApplicationCommandTarget::InvocationInfo& info_, const bool asynchronously) | |||
| bool ApplicationCommandManager::invoke (const ApplicationCommandTarget::InvocationInfo& inf, const bool asynchronously) | |||
| { | |||
| // This call isn't thread-safe for use from a non-UI thread without locking the message | |||
| // manager first.. | |||
| jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| bool ok = false; | |||
| ApplicationCommandInfo commandInfo (0); | |||
| ApplicationCommandTarget* const target = getTargetForCommand (info_.commandID, commandInfo); | |||
| if (target == nullptr) | |||
| return false; | |||
| ApplicationCommandTarget::InvocationInfo info (info_); | |||
| info.commandFlags = commandInfo.flags; | |||
| sendListenerInvokeCallback (info); | |||
| const bool ok = target->invoke (info, asynchronously); | |||
| if (ApplicationCommandTarget* const target = getTargetForCommand (inf.commandID, commandInfo)) | |||
| { | |||
| ApplicationCommandTarget::InvocationInfo info (inf); | |||
| info.commandFlags = commandInfo.flags; | |||
| commandStatusChanged(); | |||
| sendListenerInvokeCallback (info); | |||
| ok = target->invoke (info, asynchronously); | |||
| commandStatusChanged(); | |||
| } | |||
| return ok; | |||
| } | |||
| @@ -239,9 +236,7 @@ ApplicationCommandTarget* ApplicationCommandManager::findDefaultComponentTarget( | |||
| if (c == nullptr) | |||
| { | |||
| TopLevelWindow* const activeWindow = TopLevelWindow::getActiveTopLevelWindow(); | |||
| if (activeWindow != nullptr) | |||
| if (TopLevelWindow* const activeWindow = TopLevelWindow::getActiveTopLevelWindow()) | |||
| { | |||
| c = activeWindow->getPeer()->getLastFocusedSubcomponent(); | |||
| @@ -252,16 +247,11 @@ ApplicationCommandTarget* ApplicationCommandManager::findDefaultComponentTarget( | |||
| if (c == nullptr && Process::isForegroundProcess()) | |||
| { | |||
| // getting a bit desperate now - try all desktop comps.. | |||
| // getting a bit desperate now: try all desktop comps.. | |||
| for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) | |||
| { | |||
| ApplicationCommandTarget* const target | |||
| = findTargetForComponent (Desktop::getInstance().getComponent (i) | |||
| ->getPeer()->getLastFocusedSubcomponent()); | |||
| if (target != nullptr) | |||
| if (ApplicationCommandTarget* const target = findTargetForComponent (Desktop::getInstance().getComponent (i) | |||
| ->getPeer()->getLastFocusedSubcomponent())) | |||
| return target; | |||
| } | |||
| } | |||
| if (c != nullptr) | |||
| @@ -275,9 +265,7 @@ ApplicationCommandTarget* ApplicationCommandManager::findDefaultComponentTarget( | |||
| if (resizableWindow != nullptr && resizableWindow->getContentComponent() != nullptr) | |||
| c = resizableWindow->getContentComponent(); | |||
| ApplicationCommandTarget* const target = findTargetForComponent (c); | |||
| if (target != nullptr) | |||
| if (ApplicationCommandTarget* const target = findTargetForComponent (c)) | |||
| return target; | |||
| } | |||
| @@ -109,13 +109,11 @@ public: | |||
| //============================================================================== | |||
| /** Clears the current list of all commands. | |||
| Note that this will also clear the contents of the KeyPressMappingSet. | |||
| */ | |||
| void clearCommands(); | |||
| /** Adds a command to the list of registered commands. | |||
| @see registerAllCommandsForTarget | |||
| */ | |||
| void registerCommand (const ApplicationCommandInfo& newCommand); | |||
| @@ -131,7 +129,6 @@ public: | |||
| void registerAllCommandsForTarget (ApplicationCommandTarget* target); | |||
| /** Removes the command with a specified ID. | |||
| Note that this will also remove any key mappings that are mapped to the command. | |||
| */ | |||
| void removeCommand (CommandID commandID); | |||
| @@ -150,13 +147,11 @@ public: | |||
| //============================================================================== | |||
| /** Returns the number of commands that have been registered. | |||
| @see registerCommand | |||
| */ | |||
| int getNumCommands() const noexcept { return commands.size(); } | |||
| /** Returns the details about one of the registered commands. | |||
| The index is between 0 and (getNumCommands() - 1). | |||
| */ | |||
| const ApplicationCommandInfo* getCommandForIndex (int index) const noexcept { return commands [index]; } | |||
| @@ -195,7 +190,6 @@ public: | |||
| StringArray getCommandCategories() const; | |||
| /** Returns a list of all the command UIDs in a particular category. | |||
| @see getCommandCategories() | |||
| */ | |||
| Array<CommandID> getCommandsInCategory (const String& categoryName) const; | |||
| @@ -214,7 +208,6 @@ public: | |||
| //============================================================================== | |||
| /** Invokes the given command directly, sending it to the default target. | |||
| This is just an easy way to call invoke() without having to fill out the InvocationInfo | |||
| structure. | |||
| */ | |||
| @@ -318,7 +311,7 @@ private: | |||
| ScopedPointer <KeyPressMappingSet> keyMappings; | |||
| ApplicationCommandTarget* firstTarget; | |||
| void sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo& info); | |||
| void sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo&); | |||
| void handleAsyncUpdate(); | |||
| void globalFocusChanged (Component*); | |||
| @@ -26,15 +26,14 @@ | |||
| class ApplicationCommandTarget::CommandMessage : public MessageManager::MessageBase | |||
| { | |||
| public: | |||
| CommandMessage (ApplicationCommandTarget* const owner_, const InvocationInfo& info_) | |||
| : owner (owner_), info (info_) | |||
| CommandMessage (ApplicationCommandTarget* const target, const InvocationInfo& inf) | |||
| : owner (target), info (inf) | |||
| { | |||
| } | |||
| void messageCallback() | |||
| { | |||
| ApplicationCommandTarget* const target = owner; | |||
| if (target != nullptr) | |||
| if (ApplicationCommandTarget* const target = owner) | |||
| target->tryToInvoke (info, false); | |||
| } | |||
| @@ -69,9 +68,9 @@ bool ApplicationCommandTarget::tryToInvoke (const InvocationInfo& info, const bo | |||
| { | |||
| const bool success = perform (info); | |||
| jassert (success); // hmm - your target should have been able to perform this command. If it can't | |||
| // do it at the moment for some reason, it should clear the 'isActive' flag when it | |||
| // returns the command's info. | |||
| jassert (success); // Hmm.. your target claimed that it could perform this command, but failed to do so. | |||
| // If it can't do it at the moment for some reason, it should clear the 'isActive' flag | |||
| // when it returns the command's info. | |||
| return success; | |||
| } | |||
| } | |||
| @@ -81,9 +80,7 @@ bool ApplicationCommandTarget::tryToInvoke (const InvocationInfo& info, const bo | |||
| ApplicationCommandTarget* ApplicationCommandTarget::findFirstTargetParentComponent() | |||
| { | |||
| Component* c = dynamic_cast <Component*> (this); | |||
| if (c != nullptr) | |||
| if (Component* const c = dynamic_cast <Component*> (this)) | |||
| return c->findParentComponentOfClass<ApplicationCommandTarget>(); | |||
| return nullptr; | |||
| @@ -180,8 +177,8 @@ bool ApplicationCommandTarget::invokeDirectly (const CommandID commandID, const | |||
| } | |||
| //============================================================================== | |||
| ApplicationCommandTarget::InvocationInfo::InvocationInfo (const CommandID commandID_) | |||
| : commandID (commandID_), | |||
| ApplicationCommandTarget::InvocationInfo::InvocationInfo (const CommandID command) | |||
| : commandID (command), | |||
| commandFlags (0), | |||
| invocationMethod (direct), | |||
| originatingComponent (nullptr), | |||
| @@ -57,6 +57,7 @@ public: | |||
| //============================================================================== | |||
| /** | |||
| Contains contextual details about the invocation of a command. | |||
| */ | |||
| struct JUCE_API InvocationInfo | |||
| { | |||
| @@ -68,7 +69,6 @@ public: | |||
| CommandID commandID; | |||
| /** The command's flags. | |||
| See ApplicationCommandInfo for a description of these flag values. | |||
| */ | |||
| int commandFlags; | |||
| @@ -124,7 +124,7 @@ public: | |||
| that command, this method is used to determine the next target that should | |||
| be tried. | |||
| It may return 0 if it doesn't know of another target. | |||
| It may return nullptr if it doesn't know of another target. | |||
| If your target is a Component, you would usually use the findFirstTargetParentComponent() | |||
| method to return a parent component that might want to handle it. | |||
| @@ -776,11 +776,8 @@ public: | |||
| TargetClass* findParentComponentOfClass() const | |||
| { | |||
| for (Component* p = parentComponent; p != nullptr; p = p->parentComponent) | |||
| { | |||
| TargetClass* const target = dynamic_cast <TargetClass*> (p); | |||
| if (target != nullptr) | |||
| if (TargetClass* const target = dynamic_cast <TargetClass*> (p)) | |||
| return target; | |||
| } | |||
| return nullptr; | |||
| } | |||
| @@ -368,6 +368,7 @@ CodeEditorComponent::CodeEditorComponent (CodeDocument& doc, CodeTokeniser* cons | |||
| selectionEnd (doc, 0, 0), | |||
| verticalScrollBar (true), | |||
| horizontalScrollBar (false), | |||
| appCommandManager (nullptr), | |||
| codeTokeniser (tokeniser) | |||
| { | |||
| pimpl = new Pimpl (*this); | |||
| @@ -590,6 +591,7 @@ void CodeEditorComponent::moveCaretTo (const CodeDocument::Position& newPos, con | |||
| { | |||
| caretPos = newPos; | |||
| columnToTryToMaintain = -1; | |||
| bool selectionWasActive = isHighlightActive(); | |||
| if (highlighting) | |||
| { | |||
| @@ -639,6 +641,9 @@ void CodeEditorComponent::moveCaretTo (const CodeDocument::Position& newPos, con | |||
| updateCaretPosition(); | |||
| scrollToKeepCaretOnScreen(); | |||
| updateScrollBars(); | |||
| if (appCommandManager != nullptr && selectionWasActive != isHighlightActive()) | |||
| appCommandManager->commandStatusChanged(); | |||
| } | |||
| void CodeEditorComponent::deselectAll() | |||
| @@ -1142,6 +1147,11 @@ void CodeEditorComponent::newTransaction() | |||
| pimpl->startTimer (600); | |||
| } | |||
| void CodeEditorComponent::setCommandManager (ApplicationCommandManager* newManager) noexcept | |||
| { | |||
| appCommandManager = newManager; | |||
| } | |||
| //============================================================================== | |||
| Range<int> CodeEditorComponent::getHighlightedRegion() const | |||
| { | |||
| @@ -1199,22 +1209,82 @@ void CodeEditorComponent::handleEscapeKey() | |||
| } | |||
| //============================================================================== | |||
| void CodeEditorComponent::addPopupMenuItems (PopupMenu& m, const MouseEvent*) | |||
| ApplicationCommandTarget* CodeEditorComponent::getNextCommandTarget() | |||
| { | |||
| m.addItem (StandardApplicationCommandIDs::cut, TRANS("Cut")); | |||
| m.addItem (StandardApplicationCommandIDs::copy, TRANS("Copy"), ! getHighlightedRegion().isEmpty()); | |||
| m.addItem (StandardApplicationCommandIDs::paste, TRANS("Paste")); | |||
| m.addItem (StandardApplicationCommandIDs::del, TRANS("Delete")); | |||
| m.addSeparator(); | |||
| m.addItem (StandardApplicationCommandIDs::selectAll, TRANS("Select All")); | |||
| m.addSeparator(); | |||
| m.addItem (StandardApplicationCommandIDs::undo, TRANS("Undo"), document.getUndoManager().canUndo()); | |||
| m.addItem (StandardApplicationCommandIDs::redo, TRANS("Redo"), document.getUndoManager().canRedo()); | |||
| return findFirstTargetParentComponent(); | |||
| } | |||
| void CodeEditorComponent::performPopupMenuAction (const int menuItemID) | |||
| void CodeEditorComponent::getAllCommands (Array <CommandID>& commands) | |||
| { | |||
| const CommandID ids[] = { StandardApplicationCommandIDs::cut, | |||
| StandardApplicationCommandIDs::copy, | |||
| StandardApplicationCommandIDs::paste, | |||
| StandardApplicationCommandIDs::del, | |||
| StandardApplicationCommandIDs::selectAll, | |||
| StandardApplicationCommandIDs::undo, | |||
| StandardApplicationCommandIDs::redo }; | |||
| commands.addArray (ids, numElementsInArray (ids)); | |||
| } | |||
| void CodeEditorComponent::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result) | |||
| { | |||
| switch (menuItemID) | |||
| const bool anythingSelected = isHighlightActive(); | |||
| switch (commandID) | |||
| { | |||
| case StandardApplicationCommandIDs::cut: | |||
| result.setInfo (TRANS ("Cut"), TRANS ("Copies the currently selected text to the clipboard and deletes it."), "Editing", 0); | |||
| result.setActive (anythingSelected); | |||
| result.defaultKeypresses.add (KeyPress ('x', ModifierKeys::commandModifier, 0)); | |||
| break; | |||
| case StandardApplicationCommandIDs::copy: | |||
| result.setInfo (TRANS ("Copy"), TRANS ("Copies the currently selected text to the clipboard."), "Editing", 0); | |||
| result.setActive (anythingSelected); | |||
| result.defaultKeypresses.add (KeyPress ('c', ModifierKeys::commandModifier, 0)); | |||
| break; | |||
| case StandardApplicationCommandIDs::paste: | |||
| result.setInfo (TRANS ("Paste"), TRANS ("Inserts text from the clipboard."), "Editing", 0); | |||
| result.defaultKeypresses.add (KeyPress ('v', ModifierKeys::commandModifier, 0)); | |||
| break; | |||
| case StandardApplicationCommandIDs::del: | |||
| result.setInfo (TRANS ("Delete"), TRANS ("Deletes any selected text."), "Editing", 0); | |||
| result.setActive (anythingSelected); | |||
| break; | |||
| case StandardApplicationCommandIDs::selectAll: | |||
| result.setInfo (TRANS ("Select All"), TRANS ("Selects all the text in the editor."), "Editing", 0); | |||
| result.defaultKeypresses.add (KeyPress ('a', ModifierKeys::commandModifier, 0)); | |||
| break; | |||
| case StandardApplicationCommandIDs::undo: | |||
| result.setInfo (TRANS ("Undo"), TRANS ("Undo"), "Editing", 0); | |||
| result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::commandModifier, 0)); | |||
| result.setActive (document.getUndoManager().canUndo()); | |||
| break; | |||
| case StandardApplicationCommandIDs::redo: | |||
| result.setInfo (TRANS ("Redo"), TRANS ("Redo"), "Editing", 0); | |||
| result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0)); | |||
| result.setActive (document.getUndoManager().canRedo()); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| bool CodeEditorComponent::perform (const InvocationInfo& info) | |||
| { | |||
| return performCommand (info.commandID); | |||
| } | |||
| bool CodeEditorComponent::performCommand (const int commandID) | |||
| { | |||
| switch (commandID) | |||
| { | |||
| case StandardApplicationCommandIDs::cut: cutToClipboard(); break; | |||
| case StandardApplicationCommandIDs::copy: copyToClipboard(); break; | |||
| @@ -1223,8 +1293,29 @@ void CodeEditorComponent::performPopupMenuAction (const int menuItemID) | |||
| case StandardApplicationCommandIDs::selectAll: selectAll(); break; | |||
| case StandardApplicationCommandIDs::undo: undo(); break; | |||
| case StandardApplicationCommandIDs::redo: redo(); break; | |||
| default: break; | |||
| default: return false; | |||
| } | |||
| return true; | |||
| } | |||
| //============================================================================== | |||
| void CodeEditorComponent::addPopupMenuItems (PopupMenu& m, const MouseEvent*) | |||
| { | |||
| m.addItem (StandardApplicationCommandIDs::cut, TRANS ("Cut")); | |||
| m.addItem (StandardApplicationCommandIDs::copy, TRANS ("Copy"), ! getHighlightedRegion().isEmpty()); | |||
| m.addItem (StandardApplicationCommandIDs::paste, TRANS ("Paste")); | |||
| m.addItem (StandardApplicationCommandIDs::del, TRANS ("Delete")); | |||
| m.addSeparator(); | |||
| m.addItem (StandardApplicationCommandIDs::selectAll, TRANS ("Select All")); | |||
| m.addSeparator(); | |||
| m.addItem (StandardApplicationCommandIDs::undo, TRANS ("Undo"), document.getUndoManager().canUndo()); | |||
| m.addItem (StandardApplicationCommandIDs::redo, TRANS ("Redo"), document.getUndoManager().canRedo()); | |||
| } | |||
| void CodeEditorComponent::performPopupMenuAction (const int menuItemID) | |||
| { | |||
| performCommand (menuItemID); | |||
| } | |||
| static void codeEditorMenuCallback (int menuResult, CodeEditorComponent* editor) | |||
| @@ -37,6 +37,7 @@ class CodeTokeniser; | |||
| files. | |||
| */ | |||
| class JUCE_API CodeEditorComponent : public Component, | |||
| public ApplicationCommandTarget, | |||
| public TextInputTarget | |||
| { | |||
| public: | |||
| @@ -300,6 +301,15 @@ public: | |||
| */ | |||
| virtual void performPopupMenuAction (int menuItemID); | |||
| /** Specifies a commmand-manager which the editor will notify whenever the state | |||
| of any of its commands changes. | |||
| If you're making use of the editor's ApplicationCommandTarget interface, then | |||
| you should also use this to tell it which command manager it should use. Make | |||
| sure that the manager does not go out of scope while the editor is using it. You | |||
| can pass a nullptr here to disable this. | |||
| */ | |||
| void setCommandManager (ApplicationCommandManager* newManager) noexcept; | |||
| //============================================================================== | |||
| /** @internal */ | |||
| void paint (Graphics&); | |||
| @@ -325,6 +335,14 @@ public: | |||
| bool isTextInputActive() const; | |||
| /** @internal */ | |||
| void setTemporaryUnderlining (const Array <Range<int> >&); | |||
| /** @internal */ | |||
| ApplicationCommandTarget* getNextCommandTarget(); | |||
| /** @internal */ | |||
| void getAllCommands (Array<CommandID>&); | |||
| /** @internal */ | |||
| void getCommandInfo (CommandID, ApplicationCommandInfo&); | |||
| /** @internal */ | |||
| bool perform (const InvocationInfo&); | |||
| private: | |||
| //============================================================================== | |||
| @@ -342,6 +360,7 @@ private: | |||
| ScopedPointer<CaretComponent> caret; | |||
| ScrollBar verticalScrollBar, horizontalScrollBar; | |||
| ApplicationCommandManager* appCommandManager; | |||
| class Pimpl; | |||
| friend class Pimpl; | |||
| @@ -375,13 +394,13 @@ private: | |||
| OwnedArray <CodeDocument::Iterator> cachedIterators; | |||
| void clearCachedIterators (int firstLineToBeInvalid); | |||
| void updateCachedIterators (int maxLineNum); | |||
| void getIteratorForPosition (int position, CodeDocument::Iterator& result); | |||
| void getIteratorForPosition (int position, CodeDocument::Iterator&); | |||
| void moveLineDelta (int delta, bool selecting); | |||
| int getGutterSize() const noexcept; | |||
| //============================================================================== | |||
| void insertText (const String& textToInsert); | |||
| void insertText (const String&); | |||
| void updateCaretPosition(); | |||
| void updateScrollBars(); | |||
| void scrollToLineInternal (int line); | |||
| @@ -390,6 +409,7 @@ private: | |||
| void cut(); | |||
| void indentSelectedLines (int spacesToAdd); | |||
| bool skipBackwardsToPreviousTab(); | |||
| bool performCommand (int); | |||
| int indexToColumn (int line, int index) const noexcept; | |||
| int columnToIndex (int line, int column) const noexcept; | |||