/******************************************************************************* * Copyright (c) 2005, 2006 Eclipse Foundation * 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: * Bjorn Freeman-Benson - initial implementation * Ward Cunningham - initial implementation * Channing Walton - bug 143456 *******************************************************************************/ package org.eclipse.eclipsemonkey.actions; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.runtime.IPath; import org.eclipse.eclipsemonkey.EclipseMonkeyPlugin; import org.eclipse.eclipsemonkey.MenuRunMonkeyScript; import org.eclipse.eclipsemonkey.RunMonkeyException; import org.eclipse.eclipsemonkey.ScriptMetadata; import org.eclipse.eclipsemonkey.StoredScript; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.bindings.keys.KeyStroke; import org.eclipse.jface.bindings.keys.ParseException; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.ActionSetContributionItem; import org.eclipse.ui.internal.WorkbenchWindow; /** * */ public class RecreateMonkeyMenuAction implements IWorkbenchWindowActionDelegate { /** * */ public RecreateMonkeyMenuAction() { } /** * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) */ public void run(IAction action) { clearTheMenu(); Collection metaDatas = getAllMetadatas(); List menuData = createMenuFromMetadatas(metaDatas); createTheMenu(menuData, action); } private Collection getAllMetadatas() { ArrayList result = new ArrayList(); Iterator iter = EclipseMonkeyPlugin.getDefault().getScriptStore().values().iterator(); for (; iter.hasNext();) { StoredScript element = (StoredScript) iter.next(); result.add(element.metadata); } return result; } private void clearTheMenu() { MenuManager manager = ((WorkbenchWindow) window).getMenuManager(); if (manager != null) { IContributionItem two = manager.findUsingPath("eclipsemonkeyMenu"); //$NON-NLS-1$ if (two != null) { IMenuManager three = (IMenuManager) ((ActionSetContributionItem) two).getInnerItem(); if (three != null) { three.removeAll(); } } } } private Pattern submenu_pattern = Pattern.compile("^(.+?)>(.*)$"); //$NON-NLS-1$ class MonkeyMenuStruct { String key; IMenuManager menu; MonkeyMenuStruct submenu; } private void createTheMenu(List menuData, final IAction action) { MenuManager outerManager = ((WorkbenchWindow) window).getMenuManager(); IContributionItem contribution = outerManager.findUsingPath("eclipsemonkeyMenu"); //$NON-NLS-1$ if (contribution == null) { return; } IMenuManager menuManager = (IMenuManager) ((ActionSetContributionItem) contribution).getInnerItem(); MonkeyMenuStruct current = new MonkeyMenuStruct(); current.key = ""; //$NON-NLS-1$ current.menu = menuManager; current.submenu = new MonkeyMenuStruct(); SortedSet sorted = new TreeSet(); sorted.addAll(menuData); Iterator iter = sorted.iterator(); while (iter.hasNext()) { Association element = (Association) iter.next(); String menu_string = element.key; final IPath script_file_to_run = element.path; String accelerator = element.accelerator; addNestedMenuAction(current, menu_string, script_file_to_run, accelerator, element.imagePath); } final IWorkbenchWindow _window = this.window; if (sorted.size() != 0) menuManager.add(new Separator()); if (MenuRunMonkeyScript.last_run != null) { String lastScriptText = MessageFormat.format(Messages.RecreateMonkeyMenuAction_LBL_Run_last_script, MenuRunMonkeyScript.last_run.metadata.getMenuName()); Action rerunAction = menuAction(lastScriptText, MenuRunMonkeyScript.last_run.scriptPath, "CTRL+ALT+M", null); //$NON-NLS-1$ menuManager.add(rerunAction); } menuManager.add(new Action(Messages.RecreateMonkeyMenuAction_LBL_Paste_new_script) { public void run() { IWorkbenchWindowActionDelegate delegate = new PasteScriptFromClipboardAction(); delegate.init(_window); delegate.run(action); } }); if (sorted.size() == 0) { menuManager.add(new Action(Messages.RecreateMonkeyMenuAction_LBL_Examples) { public void run() { IWorkbenchWindowActionDelegate delegate = new CreateMonkeyExamplesAction(); delegate.init(_window); delegate.run(action); } }); } menuManager.updateAll(true); } private void addNestedMenuAction(MonkeyMenuStruct current, String menu_string, final IPath script_file_to_run, String accelerator, String imagePath) { if (menu_string == null) return; Matcher match = submenu_pattern.matcher(menu_string); if (match.find()) { String primary_key = match.group(1).trim(); String secondary_key = match.group(2).trim(); if (!primary_key.equals(current.submenu.key)) { IMenuManager submenu = new MenuManager(primary_key); current.menu.add(submenu); current.submenu.menu = submenu; current.submenu.key = primary_key; current.submenu.submenu = new MonkeyMenuStruct(); } addNestedMenuAction(current.submenu, secondary_key, script_file_to_run, accelerator, imagePath); } else { current.menu.add(menuAction(menu_string, script_file_to_run, accelerator, imagePath)); } } private Action menuAction(String key, final IPath path, String accelerator, String imagePath) { final MenuRunMonkeyScript runner = new MenuRunMonkeyScript(path, window); Action action = new Action(key) { public void run() { try { runner.run("main", new Object[] {}); //$NON-NLS-1$ } catch (RunMonkeyException x) { MessageDialog.openError(window.getShell(), x.exceptionName, x.errorMessage + "\n" + x.fileName //$NON-NLS-1$ + x.optionalLineNumber()); } } }; if (accelerator != null) { action.setAccelerator(getAccelerator(accelerator)); } if (imagePath != null) { IPath newPath = path.removeLastSegments(1).append(imagePath); ImageDescriptor id = ImageDescriptor.createFromFile(null, newPath.toFile().getAbsolutePath()); if (id != null) { action.setImageDescriptor(id); } } return action; } private int getAccelerator(String accelerator) { try { KeyStroke instance = KeyStroke.getInstance(accelerator); if (instance != null) { return instance.getNaturalKey() | instance.getModifierKeys(); } } catch (ParseException e) { reportKeyStrokeInvalid(accelerator); } catch (IllegalArgumentException e) { reportKeyStrokeInvalid(accelerator); } return KeyStroke.NO_KEY; } private void reportKeyStrokeInvalid(String accelerator) { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); MessageDialog.openError(shell, Messages.RecreateMonkeyMenuAction_ERR_TTL_Keystroke_not_valid, MessageFormat .format(Messages.RecreateMonkeyMenuAction_ERR_MSG_Keystroke_not_valid, accelerator)); } private List createMenuFromMetadatas(Collection metaDatas) { List menuData = new ArrayList(); for (Iterator iter = metaDatas.iterator(); iter.hasNext();) { ScriptMetadata data = (ScriptMetadata) iter.next(); if (data.getMenuName() != null) menuData .add(new Association(data.getMenuName(), data.getPath(), data.getAccelerator(), data.getImage())); } return menuData; } private static int id = 0; class Association implements Comparable { String accelerator; String key; IPath path; int uniqueId; String imagePath; Association(String k, IPath p, String accelerator, String imagePath) { this.key = k; this.path = p; this.accelerator = accelerator; this.uniqueId = id++; this.imagePath = imagePath; } /** * @see java.lang.Comparable#compareTo(java.lang.Object) */ public int compareTo(Object arg0) { Association b = (Association) arg0; int value = key.compareTo(b.key); if (value == 0) { if (uniqueId < b.uniqueId) return -1; else return 1; } else return value; } } /** * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, * org.eclipse.jface.viewers.ISelection) */ public void selectionChanged(IAction action, ISelection selection) { } /** * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() */ public void dispose() { } /** * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow) */ public void init(IWorkbenchWindow window) { this.window = window; } private IWorkbenchWindow window; }