1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

Bug 289339 - CDT should support feature "Surround with..", patch by Axel Mueller

This commit is contained in:
Anton Leherbauer 2009-10-26 08:17:27 +00:00
parent 57ba53ae39
commit 86ab70a815
6 changed files with 516 additions and 2 deletions

View file

@ -11,6 +11,7 @@
# Anton Leherbauer (Wind River Systems)
# Sergey Prigogin (Google)
# QNX Software Systems - [272416] Rework the working set configurations
# Axel Mueller - [289339] Surround with
###############################################################################
pluginName=C/C++ Development Tools UI
providerName=Eclipse CDT
@ -152,6 +153,9 @@ ActionDefinition.implementMethod.description= Implements a method for a selected
ActionDefinition.gettersAndSetters.name = Generate Getters and Setters...
ActionDefinition.gettersAndSetters.description = Generates getters and setters for a selected field
ActionDefinition.surroundWith.quickMenu.name= Surround With Quick Menu
ActionDefinition.surroundWith.quickMenu.description= Shows the Surround With quick menu
# Action Set
CodingActionSet.label= C/C++ Coding
CodingActionSet.description= Action set containing coding related C/C++ actions
@ -459,6 +463,8 @@ SpecificContentAssist.name= C/C++ Content Assist
SpecificContentAssist.desc= A parameterizable command that invokes content assist with a single completion proposal category
SpecificContentAssist.param= type
SurroundWithTemplateAction.label= Surround &With
# CView context
cViewScope.name = In C/C++ Views
cViewScope.description = In C/C++ Views

View file

@ -1276,6 +1276,14 @@
id="org.eclipse.cdt.ui.actions.ImplementMethod"
retarget="true">
</action>
<action
class="org.eclipse.cdt.internal.ui.actions.SurroundWithTemplateMenuAction"
definitionId="org.eclipse.cdt.ui.edit.text.c.surround.with.quickMenu"
label="%SurroundWithTemplateAction.label"
menubarPath="org.eclipse.jdt.ui.source.menu/codeGroup"
id="org.eclipse.cdt.internal.ui.actions.SurroundWithTemplateMenuAction"
style="pulldown">
</action>
<action
class="org.eclipse.ltk.ui.refactoring.actions.ShowRefactoringHistoryAction"
definitionId="org.eclipse.ltk.ui.refactor.show.refactoring.history"
@ -1307,6 +1315,9 @@
<separator
name="generateGroup">
</separator>
<separator
name="codeGroup">
</separator>
</menu>
</actionSet>
<actionSet
@ -1588,6 +1599,22 @@
contextId="org.eclipse.cdt.ui.cEditorScope"
commandId="org.eclipse.cdt.ui.edit.text.c.indent"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
<key
sequence="M2+M3+Z"
contextId="org.eclipse.cdt.ui.cEditorScope"
commandId="org.eclipse.cdt.ui.edit.text.c.surround.with.quickMenu"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
<key
platform="carbon"
sequence="M2+M3+Z"
commandId=""
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
<key
platform="carbon"
sequence="COMMAND+ALT+Z"
contextId="org.eclipse.cdt.ui.cEditorScope"
commandId="org.eclipse.cdt.ui.edit.text.c.surround.with.quickMenu"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
<key
sequence="M1+M3+H"
contextId="org.eclipse.cdt.ui.cEditorScope"
@ -2152,6 +2179,12 @@
description="%ActionDefinition.gettersAndSetters.description"
categoryId="org.eclipse.cdt.ui.category.source"
id="org.eclipse.cdt.ui.refactor.getters.and.setters"/>
<command
name="%ActionDefinition.surroundWith.quickMenu.name"
description="%ActionDefinition.surroundWith.quickMenu.description"
categoryId="org.eclipse.cdt.ui.category.source"
id="org.eclipse.cdt.ui.edit.text.c.surround.with.quickMenu">
</command>
</extension>
<extension
id="pdomSearchPage"

View file

@ -8,6 +8,7 @@
# Contributors:
# IBM Corporation - initial API and implementation
# Anton Leherbauer (Wind River Systems)
# Axel Mueller - [289339] Surround with
###############################################################################
SourceMenu_label=Source
@ -72,3 +73,6 @@ ExcludeFromBuildAction.1=Exclude from build
BuildActiveConfigMenuAction_defaultTooltip=Build the active configurations of selected projects
BuildActiveConfigMenuAction_buildConfigTooltip =Build ''{0}'' for project ''{1}''
SurroundWithTemplateMenuAction.SubMenuName=Surround &With
SurroundWithTemplateMenuAction.ConfigureTemplatesActionName=&Configure Templates...
SurroundWithTemplateMenuAction.NoneApplicable=(no template applicable)

View file

@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2000, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Axel Mueller - [289339] ported from JDT to CDT
*******************************************************************************/
package org.eclipse.cdt.internal.ui.actions;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ui.actions.ActionGroup;
import org.eclipse.cdt.internal.ui.editor.CEditor;
public class SurroundWithActionGroup extends ActionGroup {
private CEditor fEditor;
private final String fGroup;
public SurroundWithActionGroup(CEditor editor, String group) {
fEditor= editor;
fGroup= group;
}
/**
* The Menu to show when right click on the editor
* {@inheritDoc}
*/
@Override
public void fillContextMenu(IMenuManager menu) {
ISelectionProvider selectionProvider= fEditor.getSelectionProvider();
if (selectionProvider == null)
return;
ISelection selection= selectionProvider.getSelection();
if (!(selection instanceof ITextSelection))
return;
ITextSelection textSelection= (ITextSelection)selection;
if (textSelection.getLength() == 0)
return;
String menuText= ActionMessages.getString("SurroundWithTemplateMenuAction.SubMenuName"); //$NON-NLS-1$
MenuManager subMenu = new MenuManager(menuText, SurroundWithTemplateMenuAction.SURROUND_WITH_QUICK_MENU_ACTION_ID);
subMenu.setActionDefinitionId(SurroundWithTemplateMenuAction.SURROUND_WITH_QUICK_MENU_ACTION_ID);
menu.appendToGroup(fGroup, subMenu);
subMenu.add(new Action() {});
subMenu.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
manager.removeAll();
SurroundWithTemplateMenuAction.fillMenu(manager, fEditor);
}
});
}
}

View file

@ -0,0 +1,389 @@
/*******************************************************************************
* Copyright (c) 2000, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Axel Mueller - [289339] ported from JDT to CDT
*******************************************************************************/
package org.eclipse.cdt.internal.ui.actions;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IEditingSupport;
import org.eclipse.jface.text.IEditingSupportRegistry;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowPulldownDelegate2;
import org.eclipse.ui.actions.QuickMenuCreator;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistInvocationContext;
import org.eclipse.cdt.internal.ui.text.contentassist.TemplateCompletionProposalComputer;
public class SurroundWithTemplateMenuAction implements IWorkbenchWindowPulldownDelegate2 {
public static final String SURROUND_WITH_QUICK_MENU_ACTION_ID= "org.eclipse.cdt.ui.edit.text.c.surround.with.quickMenu"; //$NON-NLS-1$
private static final String C_TEMPLATE_PREFERENCE_PAGE_ID= "org.eclipse.cdt.ui.preferences.TemplatePreferencePage"; //$NON-NLS-1$
private static final String TEMPLATE_GROUP= "templateGroup"; //$NON-NLS-1$
private static final String CONFIG_GROUP= "configGroup"; //$NON-NLS-1$
private static class ConfigureTemplatesAction extends Action {
public ConfigureTemplatesAction() {
super(ActionMessages.getString("SurroundWithTemplateMenuAction.ConfigureTemplatesActionName")); //$NON-NLS-1$
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
PreferencesUtil.createPreferenceDialogOn(getShell(), C_TEMPLATE_PREFERENCE_PAGE_ID, new String[] {C_TEMPLATE_PREFERENCE_PAGE_ID}, null).open();
}
private Shell getShell() {
return CUIPlugin.getActiveWorkbenchShell();
}
}
private static Action NONE_APPLICABLE_ACTION= new Action(ActionMessages.getString("SurroundWithTemplateMenuAction.NoneApplicable")) { //$NON-NLS-1$
@Override
public void run() {
//Do nothing
}
@Override
public boolean isEnabled() {
return false;
}
};
private Menu fMenu;
private IPartService fPartService;
private IPartListener fPartListener= new IPartListener() {
public void partActivated(IWorkbenchPart part) {
}
public void partBroughtToTop(IWorkbenchPart part) {
}
public void partClosed(IWorkbenchPart part) {
}
public void partDeactivated(IWorkbenchPart part) {
disposeMenuItems();
}
public void partOpened(IWorkbenchPart part) {
}
};
protected void disposeMenuItems() {
if (fMenu == null || fMenu.isDisposed()) {
return;
}
MenuItem[] items = fMenu.getItems();
for (int i=0; i < items.length; i++) {
MenuItem menuItem= items[i];
if (!menuItem.isDisposed()) {
menuItem.dispose();
}
}
}
/**
* {@inheritDoc}
*/
public Menu getMenu(Menu parent) {
setMenu(new Menu(parent));
fillMenu(fMenu);
initMenu();
return fMenu;
}
/**
* {@inheritDoc}
*/
public Menu getMenu(Control parent) {
setMenu(new Menu(parent));
fillMenu(fMenu);
initMenu();
return fMenu;
}
public static void fillMenu(IMenuManager menu, CEditor editor) {
IAction[] actions= getTemplateActions(editor);
if (actions == null || actions.length == 0) {
menu.add(NONE_APPLICABLE_ACTION);
} else {
menu.add(new Separator(TEMPLATE_GROUP));
for (int i= 0; i < actions.length; i++)
menu.add(actions[i]);
}
menu.add(new Separator(CONFIG_GROUP));
menu.add(new ConfigureTemplatesAction());
}
/**
* {@inheritDoc}
*/
public void dispose() {
if (fPartService != null) {
fPartService.removePartListener(fPartListener);
fPartService= null;
}
setMenu(null);
}
/**
* {@inheritDoc}
*/
public void init(IWorkbenchWindow window) {
if (fPartService != null) {
fPartService.removePartListener(fPartListener);
fPartService= null;
}
if (window != null) {
IPartService partService= window.getPartService();
if (partService != null) {
fPartService= partService;
partService.addPartListener(fPartListener);
}
}
}
/**
* {@inheritDoc}
*/
public void run(IAction action) {
IWorkbenchPart activePart= CUIPlugin.getActivePage().getActivePart();
if (!(activePart instanceof CEditor))
return;
final CEditor editor= (CEditor)activePart;
new QuickMenuCreator() {
@Override
protected void fillMenu(IMenuManager menu) {
SurroundWithTemplateMenuAction.fillMenu(menu, editor);
}
}.createMenu();
}
/**
* {@inheritDoc}
*/
public void selectionChanged(IAction action, ISelection selection) {
// Default do nothing
}
/**
* The menu to show in the workbench menu
* @param menu the menu to fill entries into it
*/
protected void fillMenu(Menu menu) {
IWorkbenchPart activePart= CUIPlugin.getActivePage().getActivePart();
if (!(activePart instanceof CEditor)) {
ActionContributionItem item= new ActionContributionItem(NONE_APPLICABLE_ACTION);
item.fill(menu, -1);
return;
}
CEditor editor= (CEditor)activePart;
IAction[] actions= getTemplateActions(editor);
if ( actions == null || actions.length <= 0) {
ActionContributionItem item= new ActionContributionItem(NONE_APPLICABLE_ACTION);
item.fill(menu, -1);
} else {
for (int i= 0; i < actions.length; i++) {
ActionContributionItem item= new ActionContributionItem(actions[i]);
item.fill(menu, -1);
}
}
Separator configGroup= new Separator(CONFIG_GROUP);
configGroup.fill(menu, -1);
ActionContributionItem configAction= new ActionContributionItem(new ConfigureTemplatesAction());
configAction.fill(menu, -1);
}
protected void initMenu() {
fMenu.addMenuListener(new MenuAdapter() {
@Override
public void menuShown(MenuEvent e) {
Menu m = (Menu)e.widget;
MenuItem[] items = m.getItems();
for (int i=0; i < items.length; i++) {
items[i].dispose();
}
fillMenu(m);
}
});
}
private void setMenu(Menu menu) {
if (fMenu != null) {
fMenu.dispose();
}
fMenu = menu;
}
private static IAction[] getTemplateActions(CEditor editor) {
ITextSelection textSelection= getTextSelection(editor);
if (textSelection == null || textSelection.getLength() == 0)
return null;
ITranslationUnit tu= CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
if (tu == null)
return null;
TemplateCompletionProposalComputer templateComputer = new TemplateCompletionProposalComputer();
CContentAssistInvocationContext context = new CContentAssistInvocationContext( editor.getViewer(), textSelection.getOffset(), editor, true, false );
List<ICompletionProposal> proposals= templateComputer.computeCompletionProposals(context, null);
if (proposals == null || proposals.size() == 0)
return null;
return getActionsFromProposals(proposals, context.getInvocationOffset(), editor.getViewer());
}
private static ITextSelection getTextSelection(CEditor editor) {
ISelectionProvider selectionProvider= editor.getSelectionProvider();
if (selectionProvider == null)
return null;
ISelection selection= selectionProvider.getSelection();
if (!(selection instanceof ITextSelection))
return null;
return (ITextSelection)selection;
}
private static IAction[] getActionsFromProposals(List<ICompletionProposal> proposals, final int offset, final ITextViewer viewer) {
List<Action> result= new ArrayList<Action>();
int j = 1;
for (Iterator<ICompletionProposal> it= proposals.iterator(); it.hasNext();) {
final ICompletionProposal proposal= it.next();
StringBuffer actionName= new StringBuffer();
if (j<10) {
actionName.append('&').append(j).append(' ');
}
actionName.append(proposal.getDisplayString());
Action action= new Action(actionName.toString()) {
/**
* {@inheritDoc}
*/
@Override
public void run() {
applyProposal(proposal, viewer, (char)0, 0, offset);
}
};
result.add(action);
j++;
}
if (result.size() == 0)
return null;
return result.toArray(new IAction[result.size()]);
}
private static void applyProposal(ICompletionProposal proposal, ITextViewer viewer, char trigger, int stateMask, final int offset) {
Assert.isTrue(proposal instanceof ICompletionProposalExtension2);
IRewriteTarget target= null;
IEditingSupportRegistry registry= null;
IEditingSupport helper= new IEditingSupport() {
public boolean isOriginator(DocumentEvent event, IRegion focus) {
return focus.getOffset() <= offset && focus.getOffset() + focus.getLength() >= offset;
}
public boolean ownsFocusShell() {
return false;
}
};
try {
IDocument document= viewer.getDocument();
if (viewer instanceof ITextViewerExtension) {
ITextViewerExtension extension= (ITextViewerExtension) viewer;
target= extension.getRewriteTarget();
}
if (target != null)
target.beginCompoundChange();
if (viewer instanceof IEditingSupportRegistry) {
registry= (IEditingSupportRegistry) viewer;
registry.register(helper);
}
((ICompletionProposalExtension2)proposal).apply(viewer, trigger, stateMask, offset);
Point selection= proposal.getSelection(document);
if (selection != null) {
viewer.setSelectedRange(selection.x, selection.y);
viewer.revealRange(selection.x, selection.y);
}
} finally {
if (target != null)
target.endCompoundChange();
if (registry != null)
registry.unregister(helper);
}
}
}

View file

@ -11,6 +11,7 @@
* Anton Leherbauer (Wind River Systems)
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
* Axel Mueller - [289339] Surround with
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
@ -200,6 +201,7 @@ import org.eclipse.cdt.internal.ui.actions.GoToNextPreviousMemberAction;
import org.eclipse.cdt.internal.ui.actions.GotoNextBookmarkAction;
import org.eclipse.cdt.internal.ui.actions.IndentAction;
import org.eclipse.cdt.internal.ui.actions.RemoveBlockCommentAction;
import org.eclipse.cdt.internal.ui.actions.SurroundWithActionGroup;
import org.eclipse.cdt.internal.ui.search.OccurrencesFinder;
import org.eclipse.cdt.internal.ui.search.IOccurrencesFinder.OccurrenceLocation;
import org.eclipse.cdt.internal.ui.search.actions.SelectionSearchGroup;
@ -1207,6 +1209,9 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
/** Generate action group filling the "Source" submenu */
private GenerateActionGroup fGenerateActionGroup;
/** Generate action group filling the "Surround with" submenu */
private SurroundWithActionGroup fSurroundWithActionGroup;
/** Pairs of brackets, used to match. */
protected final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']', '<', '>' };
@ -2049,6 +2054,11 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
fGenerateActionGroup= null;
}
if (fSurroundWithActionGroup != null) {
fSurroundWithActionGroup.dispose();
fSurroundWithActionGroup= null;
}
if (fEditorSelectionChangedListener != null) {
fEditorSelectionChangedListener.uninstall(getSelectionProvider());
fEditorSelectionChangedListener = null;
@ -2198,6 +2208,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
fRefactoringActionGroup= new CRefactoringActionGroup(this, ITextEditorActionConstants.GROUP_EDIT);
fOpenInViewGroup= createOpenViewActionGroup();
fGenerateActionGroup= new GenerateActionGroup(this, ITextEditorActionConstants.GROUP_EDIT);
fSurroundWithActionGroup = new SurroundWithActionGroup(this, ITextEditorActionConstants.GROUP_EDIT);
action = getAction(ITextEditorActionConstants.SHIFT_RIGHT);
if (action != null) {
@ -2259,6 +2270,10 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
fGenerateActionGroup.fillContextMenu(menu);
fGenerateActionGroup.setContext(null);
fSurroundWithActionGroup.setContext(context);
fSurroundWithActionGroup.fillContextMenu(menu);
fSurroundWithActionGroup.setContext(null);
if (hasCElement) {
fSelectionSearchGroup.fillContextMenu(menu);
}
@ -2984,6 +2999,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
fRefactoringActionGroup.fillActionBars(actionBars);
fGenerateActionGroup.fillActionBars(actionBars);
fFoldingGroup.updateActionBars();
fSurroundWithActionGroup.fillActionBars(actionBars);
}
/*