1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-28 02:30:05 +00:00

Updated CodeEditorComponent to act as an ApplicationCommandTarget

This commit is contained in:
jules 2012-09-17 21:20:18 +01:00
parent 5428554cda
commit 3831af62ef
14 changed files with 187 additions and 154 deletions

View file

@ -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();
}

View file

@ -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
};
}

View file

@ -259,7 +259,7 @@ void MainWindow::showNewProjectWizard()
//==============================================================================
ApplicationCommandTarget* MainWindow::getNextCommandTarget()
{
return 0;
return nullptr;
}
void MainWindow::getAllCommands (Array <CommandID>& commands)

View file

@ -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()

View file

@ -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())

View file

@ -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;

View file

@ -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());
}
}

View file

@ -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;
if (ApplicationCommandTarget* const target = getTargetForCommand (inf.commandID, commandInfo))
{
ApplicationCommandTarget::InvocationInfo info (inf);
info.commandFlags = commandInfo.flags;
ApplicationCommandTarget::InvocationInfo info (info_);
info.commandFlags = commandInfo.flags;
sendListenerInvokeCallback (info);
const bool ok = target->invoke (info, asynchronously);
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;
}

View file

@ -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*);

View file

@ -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),

View file

@ -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.

View file

@ -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;
}

View file

@ -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)
{
switch (menuItemID)
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)
{
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)

View file

@ -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;