001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.actions;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: import org.eclipse.core.runtime.Assert;
016: import org.eclipse.core.runtime.CoreException;
017:
018: import org.eclipse.swt.events.MenuAdapter;
019: import org.eclipse.swt.events.MenuEvent;
020: import org.eclipse.swt.graphics.Point;
021: import org.eclipse.swt.widgets.Control;
022: import org.eclipse.swt.widgets.Menu;
023: import org.eclipse.swt.widgets.MenuItem;
024: import org.eclipse.swt.widgets.Shell;
025:
026: import org.eclipse.jface.action.Action;
027: import org.eclipse.jface.action.ActionContributionItem;
028: import org.eclipse.jface.action.IAction;
029: import org.eclipse.jface.action.IMenuManager;
030: import org.eclipse.jface.action.Separator;
031: import org.eclipse.jface.viewers.ISelection;
032: import org.eclipse.jface.viewers.ISelectionProvider;
033:
034: import org.eclipse.jface.text.DocumentEvent;
035: import org.eclipse.jface.text.IDocument;
036: import org.eclipse.jface.text.IEditingSupport;
037: import org.eclipse.jface.text.IEditingSupportRegistry;
038: import org.eclipse.jface.text.IRegion;
039: import org.eclipse.jface.text.IRewriteTarget;
040: import org.eclipse.jface.text.ITextSelection;
041: import org.eclipse.jface.text.ITextViewer;
042: import org.eclipse.jface.text.ITextViewerExtension;
043: import org.eclipse.jface.text.contentassist.ICompletionProposal;
044: import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
045:
046: import org.eclipse.ui.IPartListener;
047: import org.eclipse.ui.IPartService;
048: import org.eclipse.ui.IWorkbenchPart;
049: import org.eclipse.ui.IWorkbenchWindow;
050: import org.eclipse.ui.IWorkbenchWindowPulldownDelegate2;
051: import org.eclipse.ui.dialogs.PreferencesUtil;
052:
053: import org.eclipse.jdt.core.ICompilationUnit;
054:
055: import org.eclipse.jdt.ui.JavaUI;
056: import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds;
057: import org.eclipse.jdt.ui.actions.SurroundWithTryCatchAction;
058: import org.eclipse.jdt.ui.text.java.IInvocationContext;
059: import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
060:
061: import org.eclipse.jdt.internal.ui.JavaPlugin;
062: import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
063: import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
064: import org.eclipse.jdt.internal.ui.text.correction.AssistContext;
065: import org.eclipse.jdt.internal.ui.text.correction.QuickTemplateProcessor;
066:
067: public class SurroundWithTemplateMenuAction implements
068: IWorkbenchWindowPulldownDelegate2 {
069:
070: //TODO make api
071: public static final String SURROUND_WITH_QUICK_MENU_ACTION_ID = "org.eclipse.jdt.ui.edit.text.java.surround.with.quickMenu"; //$NON-NLS-1$
072:
073: private static final String JAVA_TEMPLATE_PREFERENCE_PAGE_ID = "org.eclipse.jdt.ui.preferences.JavaTemplatePreferencePage"; //$NON-NLS-1$
074:
075: private static final String TEMPLATE_GROUP = "templateGroup"; //$NON-NLS-1$
076:
077: private static final String CONFIG_GROUP = "configGroup"; //$NON-NLS-1$
078:
079: private static class ConfigureTemplatesAction extends Action {
080:
081: public ConfigureTemplatesAction() {
082: super (
083: ActionMessages.SurroundWithTemplateMenuAction_ConfigureTemplatesActionName);
084: }
085:
086: /**
087: * {@inheritDoc}
088: */
089: public void run() {
090: PreferencesUtil.createPreferenceDialogOn(getShell(),
091: JAVA_TEMPLATE_PREFERENCE_PAGE_ID,
092: new String[] { JAVA_TEMPLATE_PREFERENCE_PAGE_ID },
093: null).open();
094: }
095:
096: private Shell getShell() {
097: return JavaPlugin.getActiveWorkbenchWindow().getShell();
098: }
099: }
100:
101: private static Action NONE_APPLICABLE_ACTION = new Action(
102: ActionMessages.SurroundWithTemplateMenuAction_NoneApplicable) {
103: public void run() {
104: //Do nothing
105: }
106:
107: public boolean isEnabled() {
108: return false;
109: }
110: };
111:
112: private Menu fMenu;
113: private IPartService fPartService;
114: private IPartListener fPartListener = new IPartListener() {
115:
116: public void partActivated(IWorkbenchPart part) {
117: }
118:
119: public void partBroughtToTop(IWorkbenchPart part) {
120: }
121:
122: public void partClosed(IWorkbenchPart part) {
123: }
124:
125: public void partDeactivated(IWorkbenchPart part) {
126: disposeMenuItems();
127: }
128:
129: public void partOpened(IWorkbenchPart part) {
130: }
131:
132: };
133:
134: protected void disposeMenuItems() {
135: if (fMenu == null || fMenu.isDisposed()) {
136: return;
137: }
138: MenuItem[] items = fMenu.getItems();
139: for (int i = 0; i < items.length; i++) {
140: MenuItem menuItem = items[i];
141: if (!menuItem.isDisposed()) {
142: menuItem.dispose();
143: }
144: }
145: }
146:
147: /**
148: * {@inheritDoc}
149: */
150: public Menu getMenu(Menu parent) {
151: setMenu(new Menu(parent));
152: fillMenu(fMenu);
153: initMenu();
154: return fMenu;
155: }
156:
157: /**
158: * {@inheritDoc}
159: */
160: public Menu getMenu(Control parent) {
161: setMenu(new Menu(parent));
162: fillMenu(fMenu);
163: initMenu();
164: return fMenu;
165: }
166:
167: public static void fillMenu(IMenuManager menu,
168: CompilationUnitEditor editor,
169: SurroundWithTryCatchAction surroundWithTryCatchAction) {
170: IAction[] actions = getTemplateActions(editor);
171: surroundWithTryCatchAction.update(editor.getSelectionProvider()
172: .getSelection());
173:
174: if (actions == null && !surroundWithTryCatchAction.isEnabled()) {
175: menu.add(NONE_APPLICABLE_ACTION);
176: } else {
177: menu.add(surroundWithTryCatchAction);
178: menu.add(new Separator(TEMPLATE_GROUP));
179:
180: if (actions == null) {
181: menu.add(NONE_APPLICABLE_ACTION);
182: } else {
183: for (int i = 0; i < actions.length; i++) {
184: menu.add(actions[i]);
185: }
186: }
187: }
188:
189: menu.add(new Separator(CONFIG_GROUP));
190: menu.add(new ConfigureTemplatesAction());
191: }
192:
193: /**
194: * {@inheritDoc}
195: */
196: public void dispose() {
197: if (fPartService != null) {
198: fPartService.removePartListener(fPartListener);
199: fPartService = null;
200: }
201: setMenu(null);
202: }
203:
204: /**
205: * {@inheritDoc}
206: */
207: public void init(IWorkbenchWindow window) {
208: if (fPartService != null) {
209: fPartService.removePartListener(fPartListener);
210: fPartService = null;
211: }
212:
213: if (window != null) {
214: IPartService partService = window.getPartService();
215: if (partService != null) {
216: fPartService = partService;
217: partService.addPartListener(fPartListener);
218: }
219: }
220: }
221:
222: /**
223: * {@inheritDoc}
224: */
225: public void run(IAction action) {
226: IWorkbenchPart activePart = JavaPlugin.getActivePage()
227: .getActivePart();
228: if (!(activePart instanceof CompilationUnitEditor))
229: return;
230:
231: final CompilationUnitEditor editor = (CompilationUnitEditor) activePart;
232:
233: (new JDTQuickMenuAction(editor,
234: SURROUND_WITH_QUICK_MENU_ACTION_ID) {
235: protected void fillMenu(IMenuManager menu) {
236: SurroundWithTryCatchAction surroundWithTryCatch = createSurroundWithTryCatchAction(editor);
237: SurroundWithTemplateMenuAction.fillMenu(menu, editor,
238: surroundWithTryCatch);
239: }
240: }).run();
241: }
242:
243: /**
244: * {@inheritDoc}
245: */
246: public void selectionChanged(IAction action, ISelection selection) {
247: // Default do nothing
248: }
249:
250: /**
251: * The menu to show in the workbench menu
252: */
253: protected void fillMenu(Menu menu) {
254:
255: IWorkbenchPart activePart = JavaPlugin.getActivePage()
256: .getActivePart();
257: if (!(activePart instanceof CompilationUnitEditor)) {
258: ActionContributionItem item = new ActionContributionItem(
259: NONE_APPLICABLE_ACTION);
260: item.fill(menu, -1);
261: return;
262: }
263:
264: CompilationUnitEditor editor = (CompilationUnitEditor) activePart;
265:
266: IAction[] actions = getTemplateActions(editor);
267:
268: SurroundWithTryCatchAction surroundAction = createSurroundWithTryCatchAction(editor);
269: ActionContributionItem surroundItem = new ActionContributionItem(
270: surroundAction);
271: surroundItem.fill(menu, -1);
272:
273: Separator templateGroup = new Separator(TEMPLATE_GROUP);
274: templateGroup.fill(menu, -1);
275:
276: if (actions == null || actions.length == 0) {
277: ActionContributionItem item = new ActionContributionItem(
278: NONE_APPLICABLE_ACTION);
279: item.fill(menu, -1);
280: } else {
281: for (int i = 0; i < actions.length; i++) {
282: ActionContributionItem item = new ActionContributionItem(
283: actions[i]);
284: item.fill(menu, -1);
285: }
286: }
287:
288: Separator configGroup = new Separator(CONFIG_GROUP);
289: configGroup.fill(menu, -1);
290:
291: ActionContributionItem configAction = new ActionContributionItem(
292: new ConfigureTemplatesAction());
293: configAction.fill(menu, -1);
294:
295: }
296:
297: private static SurroundWithTryCatchAction createSurroundWithTryCatchAction(
298: CompilationUnitEditor editor) {
299: SurroundWithTryCatchAction result = new SurroundWithTryCatchAction(
300: editor);
301: result
302: .setText(ActionMessages.SurroundWithTemplateMenuAction_SurroundWithTryCatchActionName);
303: result
304: .setActionDefinitionId(IJavaEditorActionDefinitionIds.SURROUND_WITH_TRY_CATCH);
305: editor.setAction("SurroundWithTryCatch", result); //$NON-NLS-1$
306: return result;
307: }
308:
309: protected void initMenu() {
310: fMenu.addMenuListener(new MenuAdapter() {
311: public void menuShown(MenuEvent e) {
312: Menu m = (Menu) e.widget;
313: MenuItem[] items = m.getItems();
314: for (int i = 0; i < items.length; i++) {
315: items[i].dispose();
316: }
317: fillMenu(m);
318: }
319: });
320: }
321:
322: private void setMenu(Menu menu) {
323: if (fMenu != null) {
324: fMenu.dispose();
325: }
326: fMenu = menu;
327: }
328:
329: private static IAction[] getTemplateActions(JavaEditor editor) {
330: ISelectionProvider selectionProvider = editor
331: .getSelectionProvider();
332: if (selectionProvider == null)
333: return null;
334:
335: ISelection selection = selectionProvider.getSelection();
336: if (!(selection instanceof ITextSelection))
337: return null;
338:
339: ITextSelection textSelection = (ITextSelection) selection;
340: if (textSelection.getLength() == 0)
341: return null;
342:
343: ICompilationUnit cu = JavaUI.getWorkingCopyManager()
344: .getWorkingCopy(editor.getEditorInput());
345: if (cu == null)
346: return null;
347:
348: QuickTemplateProcessor quickTemplateProcessor = new QuickTemplateProcessor();
349: IInvocationContext context = new AssistContext(cu,
350: textSelection.getOffset(), textSelection.getLength());
351:
352: try {
353: IJavaCompletionProposal[] proposals = quickTemplateProcessor
354: .getAssists(context, null);
355: if (proposals == null || proposals.length == 0)
356: return null;
357:
358: return getActionsFromProposals(proposals, context
359: .getSelectionOffset(), editor.getViewer());
360: } catch (CoreException e) {
361: JavaPlugin.log(e);
362: }
363: return null;
364: }
365:
366: private static IAction[] getActionsFromProposals(
367: IJavaCompletionProposal[] proposals, final int offset,
368: final ITextViewer viewer) {
369: List result = new ArrayList();
370:
371: for (int i = 0, j = 1; i < proposals.length; i++) {
372: if (proposals[i] instanceof ICompletionProposalExtension2) {
373: final IJavaCompletionProposal proposal = proposals[i];
374:
375: StringBuffer actionName = new StringBuffer();
376: if (j < 10) {
377: actionName.append('&').append(j).append(' ');
378: }
379: actionName.append(proposals[i].getDisplayString());
380:
381: Action action = new Action(actionName.toString()) {
382: /**
383: * {@inheritDoc}
384: */
385: public void run() {
386: applyProposal(proposal, viewer, (char) 0, 0,
387: offset);
388: }
389: };
390:
391: result.add(action);
392: j++;
393: }
394: }
395: if (result.size() == 0)
396: return null;
397:
398: return (IAction[]) result.toArray(new IAction[result.size()]);
399: }
400:
401: private static void applyProposal(ICompletionProposal proposal,
402: ITextViewer viewer, char trigger, int stateMask,
403: final int offset) {
404: Assert
405: .isTrue(proposal instanceof ICompletionProposalExtension2);
406:
407: IRewriteTarget target = null;
408: IEditingSupportRegistry registry = null;
409: IEditingSupport helper = new IEditingSupport() {
410:
411: public boolean isOriginator(DocumentEvent event,
412: IRegion focus) {
413: return focus.getOffset() <= offset
414: && focus.getOffset() + focus.getLength() >= offset;
415: }
416:
417: public boolean ownsFocusShell() {
418: return false;
419: }
420:
421: };
422:
423: try {
424: IDocument document = viewer.getDocument();
425:
426: if (viewer instanceof ITextViewerExtension) {
427: ITextViewerExtension extension = (ITextViewerExtension) viewer;
428: target = extension.getRewriteTarget();
429: }
430:
431: if (target != null)
432: target.beginCompoundChange();
433:
434: if (viewer instanceof IEditingSupportRegistry) {
435: registry = (IEditingSupportRegistry) viewer;
436: registry.register(helper);
437: }
438:
439: ((ICompletionProposalExtension2) proposal).apply(viewer,
440: trigger, stateMask, offset);
441:
442: Point selection = proposal.getSelection(document);
443: if (selection != null) {
444: viewer.setSelectedRange(selection.x, selection.y);
445: viewer.revealRange(selection.x, selection.y);
446: }
447: } finally {
448: if (target != null)
449: target.endCompoundChange();
450:
451: if (registry != null)
452: registry.unregister(helper);
453: }
454: }
455: }
|