]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.ui/src/org/simantics/ui/toolbar/ToolbarContributor.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / toolbar / ToolbarContributor.java
index 0f7d3e26d26f90b2aef60cfcbecb396d4b2ec557..036574fb3825f61e75c7636c982977b28f14b6c9 100644 (file)
-package org.simantics.ui.toolbar;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-import org.eclipse.core.commands.Command;\r
-import org.eclipse.core.commands.CommandEvent;\r
-import org.eclipse.core.commands.ExecutionException;\r
-import org.eclipse.core.commands.ICommandListener;\r
-import org.eclipse.core.commands.IParameter;\r
-import org.eclipse.core.commands.Parameterization;\r
-import org.eclipse.core.commands.ParameterizedCommand;\r
-import org.eclipse.core.commands.State;\r
-import org.eclipse.core.runtime.CoreException;\r
-import org.eclipse.core.runtime.IConfigurationElement;\r
-import org.eclipse.core.runtime.IExecutableExtension;\r
-import org.eclipse.jface.action.Action;\r
-import org.eclipse.jface.action.ActionContributionItem;\r
-import org.eclipse.jface.action.IContributionItem;\r
-import org.eclipse.jface.action.ICoolBarManager;\r
-import org.eclipse.jface.action.IToolBarManager;\r
-import org.eclipse.jface.action.ToolBarContributionItem;\r
-import org.eclipse.jface.resource.ImageDescriptor;\r
-import org.eclipse.nebula.widgets.tablecombo.TableCombo;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.events.SelectionListener;\r
-import org.eclipse.swt.layout.GridData;\r
-import org.eclipse.swt.layout.GridLayout;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.eclipse.swt.widgets.TableItem;\r
-import org.eclipse.ui.IEditorPart;\r
-import org.eclipse.ui.IPartListener;\r
-import org.eclipse.ui.IWorkbenchPart;\r
-import org.eclipse.ui.PlatformUI;\r
-import org.eclipse.ui.commands.ICommandService;\r
-import org.eclipse.ui.handlers.HandlerUtil;\r
-import org.eclipse.ui.handlers.IHandlerService;\r
-import org.eclipse.ui.handlers.RadioState;\r
-import org.eclipse.ui.handlers.RegistryToggleState;\r
-import org.eclipse.ui.menus.WorkbenchWindowControlContribution;\r
-import org.eclipse.ui.part.EditorActionBarContributor;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.ui.internal.Activator;\r
-import org.simantics.ui.toolbar.ToolBarCommandRegistry.Parameter;\r
-import org.simantics.ui.toolbar.ToolBarCommandRegistry.ToolbarCommandExtension;\r
-import org.simantics.utils.datastructures.MapList;\r
-import org.simantics.utils.ui.ExceptionUtils;\r
-\r
-\r
-/**\r
- * EditorBarContributor, which tracks toggle states separately for each command.\r
- * \r
- * @see org.simantics.g3d.toolbarCommand Extension Point\r
- * \r
- * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
- * \r
- * \r
- * \r
- * TODO : configuring the position of buttons. \r
- *\r
- */\r
-public class ToolbarContributor extends EditorActionBarContributor implements ICommandListener, IPartListener, CommandStateListener, IExecutableExtension {\r
-\r
-       private static boolean DEBUG = false;                   // Print debug messages to console\r
-       private boolean REUSE = true;                           // true: Reuse contribution items (leave toolbar in disabled state when editor closes)\r
-                                                       // false: delete items on dispose (remove toolbar editor closes) \r
-       \r
-       private static final String PLATFORM = "platform:/plugin/";\r
-\r
-       private String toolbarId;\r
-       \r
-       private IEditorPart    activePart;\r
-       private Set<IEditorPart> parts = new HashSet<IEditorPart>();\r
-    IToolBarManager        mgr;\r
-    \r
-    \r
-    ICommandService service;\r
-    IHandlerService handlerService;\r
-    List<IContributionItem> items = new ArrayList<IContributionItem>();\r
-    MapList<String, CommandAction> actions = new MapList<String, ToolbarContributor.CommandAction>();\r
-    \r
-    CommandStateRegistry stateRegistry;\r
-    \r
-    IPartListener partListener;\r
-       \r
-       private Map<String,ComboContribution> menus = new HashMap<String, ComboContribution>();\r
-       \r
-       public ToolbarContributor() {\r
-               service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); \r
-               handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);\r
-               stateRegistry = CommandStateRegistry.getInstance();\r
-               // we need part listener to be notified for other editor activations (i.e editors that do not use this contributor).\r
-               partListener = new IPartListener() {\r
-                       \r
-                       @Override\r
-                       public void partOpened(IWorkbenchPart part) {}\r
-                       \r
-                       @Override\r
-                       public void partDeactivated(IWorkbenchPart part) {}\r
-                       \r
-                       @Override\r
-                       public void partClosed(IWorkbenchPart part) {}\r
-                       \r
-                       @Override\r
-                       public void partBroughtToTop(IWorkbenchPart part) {}\r
-                       \r
-                       @Override\r
-                       public void partActivated(IWorkbenchPart part) {\r
-                               if (part instanceof IEditorPart)\r
-                                       setContext2((IEditorPart)part);\r
-                       }\r
-               };\r
-               PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().addPartListener(partListener);\r
-               \r
-       }\r
-       \r
-       @Override\r
-       public void setInitializationData(IConfigurationElement config,String propertyName, Object data) throws CoreException {\r
-               if (data instanceof String) {\r
-                        String[] parameters = ((String) data).split(";");\r
-                        for (String parameter : parameters) {\r
-                       String[] keyValue = parameter.split("=");\r
-                       if (keyValue.length > 2) {\r
-                           //ErrorLogger.defaultLogWarning("Invalid parameter '" + parameter + ". Complete view argument: " + data, null);\r
-                           continue;\r
-                       }\r
-                       String key = keyValue[0];\r
-                       String value = keyValue.length > 1 ? keyValue[1] : "";\r
-\r
-                       if ("toolbar".equals(key)) {\r
-                           toolbarId = value;\r
-                       }  else if ("hide".equals(key)) {\r
-                               REUSE = !Boolean.parseBoolean(value);\r
-                       }\r
-                   }\r
-               }\r
-               \r
-       }\r
-       \r
-       public String getToolbarId() {\r
-               return toolbarId;\r
-       }\r
-       \r
-       \r
-       private ICoolBarManager coolBarManager;\r
-       private IContributionItem toolBar;\r
-       public void contributeToCoolBar(ICoolBarManager coolBarManager) {\r
-               this.coolBarManager = coolBarManager;\r
-               toolBar = coolBarManager.find(getToolbarId());\r
-               \r
-                if (toolBar instanceof ToolBarContributionItem)\r
-                mgr = ((ToolBarContributionItem) toolBar).getToolBarManager();\r
-            if (mgr == null)\r
-                   return;\r
-            \r
-            createCommands();\r
-            \r
-            mgr.markDirty();\r
-            \r
-       }\r
-       \r
-       private void createCommands() {\r
-               for (ToolbarCommandExtension ext : ToolBarCommandRegistry.getInstance().getExtensions(getToolbarId())) {\r
-                       addCommand(ext);\r
-               }\r
-       }\r
-       \r
-       private void addCommand(ToolbarCommandExtension ext) {\r
-               if (DEBUG) System.out.println("Adding command to toolbar " +getToolbarId()  + " " + ext);\r
-               String commandId = ext.commandId;\r
-               Command command = service.getCommand(commandId);\r
-               ICommandWrapper wrapper = new CommandWrapper(command);\r
-               \r
-               ParameterizedCommand parameterizedCommand = null;\r
-               \r
-               if (ext.parameters.size() > 0) {\r
-                       try {\r
-                               Parameterization parameterizations[] = new Parameterization[ext.parameters.size()];\r
-                               for (int i = 0; i < ext.parameters.size(); i++) {\r
-                                       Parameter param = ext.parameters.get(i);\r
-                                       IParameter parameter = command.getParameter(param.name);\r
-                                       parameterizations[i] = new Parameterization(parameter, param.value);\r
-                               }\r
-                               parameterizedCommand = new ParameterizedCommand(command, parameterizations);\r
-                               wrapper = new ParameterizedCommandWrapper(parameterizedCommand);\r
-                       } catch (org.eclipse.core.commands.common.NotDefinedException e) {\r
-                               e.printStackTrace();\r
-                               ExceptionUtils.logError(e);\r
-                               return;\r
-                       }\r
-               }\r
-               \r
-               String type = ext.type;\r
-               \r
-               State toggleState = command.getState(RegistryToggleState.STATE_ID);\r
-               State radioState = command.getState(RadioState.STATE_ID);\r
-               \r
-               String name = ext.name;\r
-               \r
-               \r
-               ImageDescriptor image = getImage(ext);\r
-               \r
-               CommandAction a = null;\r
-               if (type.equals("toggle") && toggleState != null) {\r
-                       a = new CommandCheckboxAction(wrapper,name,image);\r
-\r
-                       stateRegistry.storeDefaultState(commandId);\r
-               } else if (radioState != null && ext.value != null) {\r
-                       stateRegistry.storeDefaultState(commandId);\r
-                       if (type.equals("radio")) {\r
-                               a = new CommandRadioAction(wrapper,name,ext.value,image);\r
-                       } else if (type.equals("combo")) {\r
-                               a = new CommandRadioAction(wrapper,name,ext.value,image);\r
-                               ComboContribution combo = menus.get(commandId);\r
-                               if (REUSE && combo == null) {\r
-                                       combo = (ComboContribution)mgr.find(commandId);\r
-                                       if (combo != null) {\r
-                                               menus.put(commandId, combo);\r
-                                               items.add(combo);\r
-                                               a.getCommand().addCommandListener(this);\r
-                                               CommandStateRegistry.getInstance().addListener(commandId, this);\r
-                                       }\r
-                               }\r
-                               if (combo == null) {\r
-                                       combo = new ComboContribution();\r
-                                       combo.setId(commandId);\r
-                                       menus.put(commandId, combo);\r
-                                       items.add(combo);\r
-                                       mgr.add(combo);\r
-                                       a.getCommand().addCommandListener(this);\r
-                                       CommandStateRegistry.getInstance().addListener(commandId, this);\r
-                               }\r
-                               actions.add(commandId,a);\r
-                               combo.addAction(a);\r
-                               return;\r
-                       }\r
-               } else if (type.equals("push")) {\r
-                       a = new CommandPushAction(wrapper,name,image);\r
-               } else {\r
-                       if (DEBUG) System.out.println(ext + " is not valid.");\r
-                       Logger.defaultLogError(ext + " is not valid.");\r
-                       return;\r
-               }\r
-               IContributionItem item = null;\r
-               if (REUSE) {\r
-                       String id = commandId;\r
-                       if (ext.value != null)\r
-                               id += "."+ext.value;\r
-                       item = mgr.find(id);\r
-                       if (item == null) {\r
-                               item =  new ActionContributionItem(a);\r
-                               ((ActionContributionItem)item).setId(id);\r
-                       } else {\r
-                               if (DEBUG) System.out.println("Reusing " + ext);\r
-                               a = (CommandAction)((ActionContributionItem)item).getAction();\r
-                       }\r
-               } else {\r
-                       item =  new ActionContributionItem(a);\r
-               }\r
-               a.getCommand().addCommandListener(this);\r
-               actions.add(commandId,a);\r
-               items.add(item);\r
-               mgr.add(item);\r
-               CommandStateRegistry.getInstance().addListener(commandId, this);\r
-       }\r
-       \r
-       private ImageDescriptor getImage(ToolbarCommandExtension ext) {\r
-               ImageDescriptor image = null;\r
-               if (ext.image != null) {\r
-                       String plugin = null;\r
-                       String file = null;\r
-                       if (ext.image.startsWith(PLATFORM)) {\r
-                               String s = ext.image.substring(PLATFORM.length());\r
-                               int i = s.indexOf("/");\r
-                               plugin = s.substring(0,i);\r
-                               file = s.substring(i+1);\r
-                       } else {\r
-                               plugin = ext.contributorId;\r
-                               file = ext.image;\r
-                       }\r
-                       image = Activator.imageDescriptorFromPlugin(plugin, file);\r
-               }\r
-               return image;\r
-       }\r
-       \r
-\r
-       \r
-       @Override\r
-       public void commandChanged(CommandEvent commandEvent) {\r
-               if (commandEvent.isHandledChanged()||commandEvent.isEnabledChanged()) {\r
-                       Command command = commandEvent.getCommand();\r
-                       String commandId = command.getId();\r
-                       for (CommandAction a : actions.getValues(commandId)) {\r
-                               a.setEnabled(command.isHandled() && command.isEnabled());\r
-                       }\r
-               }\r
-       }\r
-       \r
-       @Override\r
-       public void setActiveEditor(IEditorPart targetEditor) {\r
-               if (targetEditor == activePart)\r
-                       return;\r
-               setContext(targetEditor);\r
-       }\r
-       \r
-       @Override\r
-       public void stateChanged(IWorkbenchPart part, String commandId, String state) {\r
-               // TODO : update only given command\r
-               if (settingState)\r
-                       return;\r
-               if (part instanceof IEditorPart)\r
-                       setContext((IEditorPart)part);\r
-       }\r
-       \r
-       private void setContext2(IEditorPart part) {\r
-               if (REUSE)\r
-                       return;\r
-               if (this.activePart == part)\r
-                       return;\r
-               setContext(null);\r
-       }\r
-       \r
-       private void setContext(IEditorPart part) {\r
-               this.activePart = part;\r
-        if (activePart != null && !parts.contains(activePart)) {\r
-               activePart.getSite().getPage().addPartListener(this);\r
-        }\r
-        if (part != null) {\r
-               for (String commandId : actions.getKeys()) {\r
-                               for (CommandAction a : actions.getValues(commandId)) {\r
-                                       a.setEnabled(true);\r
-                               }\r
-                               ComboContribution menu = menus.get(commandId);\r
-                               if (menu != null) {\r
-                                       menu.setEnabled(true);\r
-                               }\r
-                       }\r
-            updateActionBars(part);\r
-        } else {\r
-                       for (String commandId : actions.getKeys()) {\r
-                               for (CommandAction a : actions.getValues(commandId)) {\r
-                                       a.setEnabled(false);\r
-                               }\r
-                               ComboContribution menu = menus.get(commandId);\r
-                               if (menu != null) {\r
-                                       menu.setEnabled(false);\r
-                               }\r
-                               \r
-                       }\r
-        }\r
-    }\r
-\r
-    private void updateActionBars(IEditorPart part) {\r
-       restoreActionStates();\r
-        part.getEditorSite().getActionBars().updateActionBars();\r
-    }\r
-       \r
-       @Override\r
-       public void dispose() {\r
-               if (DEBUG) System.out.println("ToolBarContributor.dispose()");\r
-               setActiveEditor(null);\r
-               if (mgr != null) {\r
-                       if (!REUSE) {\r
-                               for (IContributionItem item : items) {\r
-                                       mgr.remove(item);\r
-                                       item.dispose();\r
-                               }\r
-                       }\r
-                       items.clear();\r
-                       \r
-                       for (String commandId : actions.getKeys()) {\r
-                               for (CommandAction a : actions.getValues(commandId)) {\r
-                                       a.getCommand().removeCommandListener(this);\r
-                               }\r
-                               \r
-                       }\r
-                       actions.clear();\r
-                       \r
-                       // without this the contributed toolbar widgets would continue reserve the space even when they are destroyed.\r
-                       coolBarManager.update(true);\r
-                       mgr.update(true);\r
-               }\r
-               CommandStateRegistry.getInstance().removeListener(this);\r
-               super.dispose();\r
-               activePart = null;\r
-               if (partListener != null) {\r
-                       PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().addPartListener(partListener);\r
-                       partListener = null;\r
-               }\r
-       }\r
-       \r
-       boolean settingState = false;\r
-       private void storeRadioActionState(CommandRadioAction action, boolean checked) {\r
-               if (activePart == null)\r
-                       return;\r
-               settingState = true;\r
-               stateRegistry.setEditorState(activePart, action.getCommandId(), action.getValue());\r
-               settingState = false;\r
-       }\r
-       \r
-       private void storeToggleActionState(CommandAction action, boolean checked) {\r
-               if (activePart == null)\r
-                       return;\r
-               settingState = true;\r
-               stateRegistry.setEditorState(activePart, action.getCommandId(), checked);\r
-               settingState = false;\r
-       }\r
-       \r
-       \r
-       \r
-       private void restoreActionStates() {\r
-               if (activePart == null)\r
-                       return;\r
-               if (DEBUG)System.out.println("Restore " + activePart);\r
-               // toggles\r
-               Map<String,Boolean> defaultToggleStates = stateRegistry.getDefaultToggleStates();\r
-               for (String commandId : defaultToggleStates.keySet()) {\r
-                       for (CommandAction a : actions.getValues(commandId)) {\r
-                               if (DEBUG)System.out.println(commandId + " def " + defaultToggleStates.get(commandId));\r
-                               a.setChecked(defaultToggleStates.get(commandId));\r
-                       }\r
-               }\r
-               Map<String,Boolean> editorStates = stateRegistry.getEditorToggleStates(activePart);//toggleStates.get(activePart);\r
-               if (editorStates != null) {\r
-                       for (String commandId : editorStates.keySet()) {\r
-                               for (CommandAction a : actions.getValues(commandId)) {\r
-                                       if (DEBUG)System.out.println(commandId + " " + editorStates.get(commandId));\r
-                                       a.setChecked(editorStates.get(commandId));\r
-                               }\r
-                       }\r
-               }\r
-               // radios\r
-               Map<String,String> defaultRadioStates = stateRegistry.getDefaultRadioStates();\r
-               for (String commandId : defaultRadioStates.keySet()) {\r
-                       String defaultValue = defaultRadioStates.get(commandId);\r
-                       for (CommandAction a : actions.getValues(commandId)) {\r
-                               CommandRadioAction r = (CommandRadioAction)a;\r
-                               if (DEBUG)System.out.println(commandId + " def " + r.getValue().equals(defaultValue) +" " + r.getValue());\r
-                               r.setChecked(r.getValue().equals(defaultValue));\r
-                       }\r
-               }\r
-               \r
-               Map<String,String> editorRadioStates = stateRegistry.getEditorRadioStates(activePart);//radioStates.get(activePart);\r
-               if (editorRadioStates != null) {\r
-                       for (String commandId : editorRadioStates.keySet()) {\r
-                               String defaultValue = editorRadioStates.get(commandId);\r
-                               for (CommandAction a : actions.getValues(commandId)) {\r
-                                       CommandRadioAction r = (CommandRadioAction)a;\r
-                                       if (DEBUG)System.out.println(commandId + " " + r.getValue().equals(defaultValue) +" " + r.getValue());\r
-                                       r.setChecked(r.getValue().equals(defaultValue));\r
-                               }\r
-                       }\r
-               }\r
-               \r
-               for (ComboContribution c : menus.values()) {\r
-                       c.updateSelection();\r
-               }\r
-\r
-       }\r
-       \r
-       @Override\r
-       public void partActivated(IWorkbenchPart part) {\r
-\r
-       }\r
-       \r
-       @Override\r
-       public void partBroughtToTop(IWorkbenchPart part) {\r
-               \r
-       }\r
-       \r
-       @Override\r
-       public void partClosed(IWorkbenchPart part) {\r
-               parts.remove(part);\r
-               stateRegistry.clearStates(part);\r
-               part.getSite().getPage().removePartListener(this);\r
-               if (parts.size() == 0) {\r
-                       \r
-               }\r
-               if (part instanceof IEditorPart)\r
-                       ((IEditorPart)part).getEditorSite().getActionBars().updateActionBars();\r
-               \r
-       }\r
-       \r
-       @Override\r
-       public void partDeactivated(IWorkbenchPart part) {\r
-               \r
-       }\r
-       \r
-       @Override\r
-       public void partOpened(IWorkbenchPart part) {\r
-               \r
-       }\r
-       \r
-       private boolean getToggleState(Command command) {\r
-               State toggleState = command.getState(RegistryToggleState.STATE_ID);\r
-               return (Boolean)toggleState.getValue();\r
-       }\r
-       \r
-       private interface ICommandWrapper {\r
-               \r
-               public Command getCommand();\r
-               public String getCommandId();\r
-               public void run();\r
-       }\r
-       \r
-       private class CommandWrapper implements ICommandWrapper{\r
-               private Command command;\r
-               \r
-               public CommandWrapper(Command command) {\r
-                       this.command = command;\r
-               }\r
-               \r
-               @Override\r
-               public Command getCommand() {\r
-                       return command;\r
-               }\r
-               \r
-               @Override\r
-               public String getCommandId() {\r
-                       return command.getId();\r
-               }\r
-               \r
-               @Override\r
-               public void run() {\r
-                       try {\r
-                               handlerService.executeCommand(command.getId(), null);\r
-                       } catch (Exception e) {\r
-                               e.printStackTrace();\r
-                       }\r
-               }\r
-               \r
-               @Override\r
-               public boolean equals(Object obj) {\r
-                       if (obj.getClass() != getClass())\r
-                               return false;\r
-                       CommandWrapper other= (CommandWrapper)obj;\r
-                       return other.getCommandId().equals(getCommandId());\r
-               }\r
-       }\r
-       \r
-       private class ParameterizedCommandWrapper implements ICommandWrapper{\r
-               private ParameterizedCommand command;\r
-               \r
-               public ParameterizedCommandWrapper(ParameterizedCommand command) {\r
-                       this.command = command;\r
-               }\r
-               \r
-               @Override\r
-               public Command getCommand() {\r
-                       return command.getCommand();\r
-               }\r
-               \r
-               @Override\r
-               public String getCommandId() {\r
-                       return command.getId();\r
-               }\r
-               \r
-               @Override\r
-               public void run() {\r
-                       try {\r
-                               handlerService.executeCommand(command, null);\r
-                       } catch (Exception e) {\r
-                               e.printStackTrace();\r
-                       }\r
-               }\r
-               \r
-               @Override\r
-               public boolean equals(Object obj) {\r
-                       if (obj.getClass() != getClass())\r
-                               return false;\r
-                       ParameterizedCommandWrapper other= (ParameterizedCommandWrapper)obj;\r
-                       return other.command.equals(command);\r
-               }\r
-       }\r
-       \r
-       private abstract class CommandAction extends Action {\r
-               private ICommandWrapper command;\r
-               \r
-               public CommandAction(ICommandWrapper command, String name, ImageDescriptor image, int style) {\r
-                       super(name,style);\r
-                       this.command = command;\r
-                       if (image != null)\r
-                               setImageDescriptor(image);\r
-               }\r
-               \r
-               @Override\r
-               public void run() {\r
-                       command.run();\r
-               }\r
-               \r
-               public Command getCommand() {\r
-                       return command.getCommand();\r
-               }\r
-               \r
-               public String getCommandId() {\r
-                       return command.getCommandId();\r
-               }\r
-               \r
-\r
-               @Override\r
-               public boolean equals(Object obj) {\r
-                       if (obj.getClass() != getClass())\r
-                               return false;\r
-                       CommandAction other= (CommandAction)obj;\r
-                       return command.equals(other.command);\r
-               }\r
-\r
-               \r
-               @Override\r
-               public int hashCode() {\r
-                       return command.getCommandId().hashCode();\r
-               }\r
-       }\r
-       \r
-       \r
-       private class CommandCheckboxAction extends CommandAction {\r
-               \r
-               public CommandCheckboxAction(ICommandWrapper command, String name, ImageDescriptor image) {\r
-                       super(command,name,image,Action.AS_CHECK_BOX);\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public void run() {\r
-                       boolean checked = isChecked(); \r
-                       storeToggleActionState(this, checked);\r
-                       try {\r
-                               if (checked == getToggleState(getCommand()))\r
-                                       HandlerUtil.toggleCommandState(getCommand());\r
-                       } catch (ExecutionException e) {\r
-                               e.printStackTrace();\r
-                       }\r
-                       super.run();\r
-               }\r
-               \r
-       }\r
-       \r
-       private class CommandRadioAction extends CommandAction {\r
-\r
-               private String value;\r
-               \r
-               public CommandRadioAction(ICommandWrapper command, String name, String value, ImageDescriptor image) {\r
-                       super(command,name,image,Action.AS_RADIO_BUTTON);\r
-                       this.value = value;\r
-               }\r
-               \r
-               @Override\r
-               public void run() {\r
-                       boolean checked = isChecked(); \r
-                       storeRadioActionState(this, checked);\r
-                       try {\r
-                               HandlerUtil.updateRadioState(getCommand(), value);\r
-                       } catch (ExecutionException e) {\r
-                               e.printStackTrace();\r
-                               return;\r
-                       }\r
-                       super.run();\r
-               }\r
-               \r
-               public String getValue() {\r
-                       return value;\r
-               }\r
-               \r
-               @Override\r
-               public boolean equals(Object obj) {\r
-                       if (obj.getClass() != getClass())\r
-                               return false;\r
-                       CommandRadioAction other= (CommandRadioAction)obj;\r
-                       if (!other.getCommandId().equals(getCommandId()))\r
-                               return false;\r
-                       if (!other.value.equals(value))\r
-                               return false;\r
-                       return true;\r
-               }\r
-               \r
-       }\r
-\r
-       private class CommandPushAction extends CommandAction {\r
-               \r
-               public CommandPushAction(ICommandWrapper command, String name, ImageDescriptor image) {\r
-                       super(command,name,image,Action.AS_PUSH_BUTTON);\r
-               }\r
-\r
-       }\r
-       \r
-       private class ComboContribution extends WorkbenchWindowControlContribution {\r
-               private TableCombo combo;\r
-               \r
-               private List<Action> actions = new ArrayList<Action>();\r
-               \r
-               @Override\r
-               protected Control createControl(Composite parent) {\r
-                       Composite container = new Composite(parent, SWT.NONE);\r
-                       GridLayout glContainer = new GridLayout(1, false);\r
-                       glContainer.marginTop = 0;\r
-                       glContainer.marginHeight = 0;\r
-                       glContainer.marginWidth = 0;\r
-                       container.setLayout(glContainer);\r
-                       GridData glReader = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);\r
-                       combo = new TableCombo(container, SWT.BORDER | SWT.READ_ONLY);\r
-                       combo.setLayoutData(glReader);\r
-\r
-                       for (Action a : actions) {\r
-                               TableItem item = new TableItem(combo.getTable(), SWT.NONE);\r
-                               item.setText(a.getText());\r
-                               if (a.getImageDescriptor() != null)\r
-                                       item.setImage(a.getImageDescriptor().createImage());\r
-                       }\r
-                       \r
-                       combo.addSelectionListener(new SelectionListener() {\r
-                               \r
-                               @Override\r
-                               public void widgetSelected(SelectionEvent e) {\r
-                                       int index = combo.getSelectionIndex();\r
-                                       if (index == -1)\r
-                                               return;\r
-                                       actions.get(index).run();\r
-                               }\r
-                               \r
-                               @Override\r
-                               public void widgetDefaultSelected(SelectionEvent e) {\r
-                                       \r
-                               }\r
-                       });\r
-                       updateSelection();\r
-                       return container;\r
-               }\r
-               \r
-               public boolean addAction(Action a) {\r
-                       // old action must be replaced. (otherwise reused ComboContributor would use different instances to ToolBarContributor.) \r
-                       actions.remove(a);\r
-                       actions.add(a);\r
-                       return true;\r
-                       \r
-               }\r
-               \r
-               void updateSelection() {\r
-                       if (combo == null)\r
-                               return;\r
-                       for (int i = 0; i < actions.size(); i++) {\r
-                               if (actions.get(i).isChecked()) {\r
-                                       combo.select(i);\r
-                                       return;\r
-                               }\r
-                       }\r
-               }\r
-               \r
-               public void setEnabled(boolean enabled) {\r
-                       if (combo != null)\r
-                               combo.setEnabled(enabled);\r
-               }\r
-               \r
-               @Override\r
-               public void dispose() {\r
-                       combo.dispose();\r
-                       super.dispose();\r
-               }\r
-       }\r
-       \r
-}\r
+package org.simantics.ui.toolbar;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.CommandEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.ICommandListener;
+import org.eclipse.core.commands.IParameter;
+import org.eclipse.core.commands.Parameterization;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.State;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.ICoolBarManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.ToolBarContributionItem;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.nebula.widgets.tablecombo.TableCombo;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.ui.handlers.RadioState;
+import org.eclipse.ui.handlers.RegistryToggleState;
+import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
+import org.eclipse.ui.part.EditorActionBarContributor;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.ui.internal.Activator;
+import org.simantics.ui.toolbar.ToolBarCommandRegistry.Parameter;
+import org.simantics.ui.toolbar.ToolBarCommandRegistry.ToolbarCommandExtension;
+import org.simantics.utils.datastructures.MapList;
+import org.simantics.utils.ui.ExceptionUtils;
+
+
+/**
+ * EditorBarContributor, which tracks toggle states separately for each command.
+ * 
+ * @see org.simantics.g3d.toolbarCommand Extension Point
+ * 
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
+ * 
+ * 
+ * 
+ * TODO : configuring the position of buttons. 
+ *
+ */
+public class ToolbarContributor extends EditorActionBarContributor implements ICommandListener, IPartListener, CommandStateListener, IExecutableExtension {
+
+       private static boolean DEBUG = false;                   // Print debug messages to console
+       private boolean REUSE = true;                           // true: Reuse contribution items (leave toolbar in disabled state when editor closes)
+                                                       // false: delete items on dispose (remove toolbar editor closes) 
+       
+       private static final String PLATFORM = "platform:/plugin/";
+
+       private String toolbarId;
+       
+       private IEditorPart    activePart;
+       private Set<IEditorPart> parts = new HashSet<IEditorPart>();
+    IToolBarManager        mgr;
+    
+    
+    ICommandService service;
+    IHandlerService handlerService;
+    List<IContributionItem> items = new ArrayList<IContributionItem>();
+    MapList<String, CommandAction> actions = new MapList<String, ToolbarContributor.CommandAction>();
+    
+    CommandStateRegistry stateRegistry;
+    
+    IPartListener partListener;
+       
+       private Map<String,ComboContribution> menus = new HashMap<String, ComboContribution>();
+       
+       public ToolbarContributor() {
+               service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); 
+               handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
+               stateRegistry = CommandStateRegistry.getInstance();
+               // we need part listener to be notified for other editor activations (i.e editors that do not use this contributor).
+               partListener = new IPartListener() {
+                       
+                       @Override
+                       public void partOpened(IWorkbenchPart part) {}
+                       
+                       @Override
+                       public void partDeactivated(IWorkbenchPart part) {}
+                       
+                       @Override
+                       public void partClosed(IWorkbenchPart part) {}
+                       
+                       @Override
+                       public void partBroughtToTop(IWorkbenchPart part) {}
+                       
+                       @Override
+                       public void partActivated(IWorkbenchPart part) {
+                               if (part instanceof IEditorPart)
+                                       setContext2((IEditorPart)part);
+                       }
+               };
+               PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().addPartListener(partListener);
+               
+       }
+       
+       @Override
+       public void setInitializationData(IConfigurationElement config,String propertyName, Object data) throws CoreException {
+               if (data instanceof String) {
+                        String[] parameters = ((String) data).split(";");
+                        for (String parameter : parameters) {
+                       String[] keyValue = parameter.split("=");
+                       if (keyValue.length > 2) {
+                           //ErrorLogger.defaultLogWarning("Invalid parameter '" + parameter + ". Complete view argument: " + data, null);
+                           continue;
+                       }
+                       String key = keyValue[0];
+                       String value = keyValue.length > 1 ? keyValue[1] : "";
+
+                       if ("toolbar".equals(key)) {
+                           toolbarId = value;
+                       }  else if ("hide".equals(key)) {
+                               REUSE = !Boolean.parseBoolean(value);
+                       }
+                   }
+               }
+               
+       }
+       
+       public String getToolbarId() {
+               return toolbarId;
+       }
+       
+       
+       private ICoolBarManager coolBarManager;
+       private IContributionItem toolBar;
+       public void contributeToCoolBar(ICoolBarManager coolBarManager) {
+               this.coolBarManager = coolBarManager;
+               toolBar = coolBarManager.find(getToolbarId());
+               
+                if (toolBar instanceof ToolBarContributionItem)
+                mgr = ((ToolBarContributionItem) toolBar).getToolBarManager();
+            if (mgr == null)
+                   return;
+            
+            createCommands();
+            
+            mgr.markDirty();
+            
+       }
+       
+       private void createCommands() {
+               for (ToolbarCommandExtension ext : ToolBarCommandRegistry.getInstance().getExtensions(getToolbarId())) {
+                       addCommand(ext);
+               }
+       }
+       
+       private void addCommand(ToolbarCommandExtension ext) {
+               if (DEBUG) System.out.println("Adding command to toolbar " +getToolbarId()  + " " + ext);
+               String commandId = ext.commandId;
+               Command command = service.getCommand(commandId);
+               ICommandWrapper wrapper = new CommandWrapper(command);
+               
+               ParameterizedCommand parameterizedCommand = null;
+               
+               if (ext.parameters.size() > 0) {
+                       try {
+                               Parameterization parameterizations[] = new Parameterization[ext.parameters.size()];
+                               for (int i = 0; i < ext.parameters.size(); i++) {
+                                       Parameter param = ext.parameters.get(i);
+                                       IParameter parameter = command.getParameter(param.name);
+                                       parameterizations[i] = new Parameterization(parameter, param.value);
+                               }
+                               parameterizedCommand = new ParameterizedCommand(command, parameterizations);
+                               wrapper = new ParameterizedCommandWrapper(parameterizedCommand);
+                       } catch (org.eclipse.core.commands.common.NotDefinedException e) {
+                               e.printStackTrace();
+                               ExceptionUtils.logError(e);
+                               return;
+                       }
+               }
+               
+               String type = ext.type;
+               
+               State toggleState = command.getState(RegistryToggleState.STATE_ID);
+               State radioState = command.getState(RadioState.STATE_ID);
+               
+               String name = ext.name;
+               
+               
+               ImageDescriptor image = getImage(ext);
+               
+               CommandAction a = null;
+               if (type.equals("toggle") && toggleState != null) {
+                       a = new CommandCheckboxAction(wrapper,name,image);
+
+                       stateRegistry.storeDefaultState(commandId);
+               } else if (radioState != null && ext.value != null) {
+                       stateRegistry.storeDefaultState(commandId);
+                       if (type.equals("radio")) {
+                               a = new CommandRadioAction(wrapper,name,ext.value,image);
+                       } else if (type.equals("combo")) {
+                               a = new CommandRadioAction(wrapper,name,ext.value,image);
+                               ComboContribution combo = menus.get(commandId);
+                               if (REUSE && combo == null) {
+                                       combo = (ComboContribution)mgr.find(commandId);
+                                       if (combo != null) {
+                                               menus.put(commandId, combo);
+                                               items.add(combo);
+                                               a.getCommand().addCommandListener(this);
+                                               CommandStateRegistry.getInstance().addListener(commandId, this);
+                                       }
+                               }
+                               if (combo == null) {
+                                       combo = new ComboContribution();
+                                       combo.setId(commandId);
+                                       menus.put(commandId, combo);
+                                       items.add(combo);
+                                       mgr.add(combo);
+                                       a.getCommand().addCommandListener(this);
+                                       CommandStateRegistry.getInstance().addListener(commandId, this);
+                               }
+                               actions.add(commandId,a);
+                               combo.addAction(a);
+                               return;
+                       }
+               } else if (type.equals("push")) {
+                       a = new CommandPushAction(wrapper,name,image);
+               } else {
+                       if (DEBUG) System.out.println(ext + " is not valid.");
+                       Logger.defaultLogError(ext + " is not valid.");
+                       return;
+               }
+               IContributionItem item = null;
+               if (REUSE) {
+                       String id = commandId;
+                       if (ext.value != null)
+                               id += "."+ext.value;
+                       item = mgr.find(id);
+                       if (item == null) {
+                               item =  new ActionContributionItem(a);
+                               ((ActionContributionItem)item).setId(id);
+                       } else {
+                               if (DEBUG) System.out.println("Reusing " + ext);
+                               a = (CommandAction)((ActionContributionItem)item).getAction();
+                       }
+               } else {
+                       item =  new ActionContributionItem(a);
+               }
+               a.getCommand().addCommandListener(this);
+               actions.add(commandId,a);
+               items.add(item);
+               mgr.add(item);
+               CommandStateRegistry.getInstance().addListener(commandId, this);
+       }
+       
+       private ImageDescriptor getImage(ToolbarCommandExtension ext) {
+               ImageDescriptor image = null;
+               if (ext.image != null) {
+                       String plugin = null;
+                       String file = null;
+                       if (ext.image.startsWith(PLATFORM)) {
+                               String s = ext.image.substring(PLATFORM.length());
+                               int i = s.indexOf("/");
+                               plugin = s.substring(0,i);
+                               file = s.substring(i+1);
+                       } else {
+                               plugin = ext.contributorId;
+                               file = ext.image;
+                       }
+                       image = Activator.imageDescriptorFromPlugin(plugin, file);
+               }
+               return image;
+       }
+       
+
+       
+       @Override
+       public void commandChanged(CommandEvent commandEvent) {
+               if (commandEvent.isHandledChanged()||commandEvent.isEnabledChanged()) {
+                       Command command = commandEvent.getCommand();
+                       String commandId = command.getId();
+                       for (CommandAction a : actions.getValues(commandId)) {
+                               a.setEnabled(command.isHandled() && command.isEnabled());
+                       }
+               }
+       }
+       
+       @Override
+       public void setActiveEditor(IEditorPart targetEditor) {
+               if (targetEditor == activePart)
+                       return;
+               setContext(targetEditor);
+       }
+       
+       @Override
+       public void stateChanged(IWorkbenchPart part, String commandId, String state) {
+               // TODO : update only given command
+               if (settingState)
+                       return;
+               if (part instanceof IEditorPart)
+                       setContext((IEditorPart)part);
+       }
+       
+       private void setContext2(IEditorPart part) {
+               if (REUSE)
+                       return;
+               if (this.activePart == part)
+                       return;
+               setContext(null);
+       }
+       
+       private void setContext(IEditorPart part) {
+               this.activePart = part;
+        if (activePart != null && !parts.contains(activePart)) {
+               activePart.getSite().getPage().addPartListener(this);
+        }
+        if (part != null) {
+               for (String commandId : actions.getKeys()) {
+                               for (CommandAction a : actions.getValues(commandId)) {
+                                       a.setEnabled(true);
+                               }
+                               ComboContribution menu = menus.get(commandId);
+                               if (menu != null) {
+                                       menu.setEnabled(true);
+                               }
+                       }
+            updateActionBars(part);
+        } else {
+                       for (String commandId : actions.getKeys()) {
+                               for (CommandAction a : actions.getValues(commandId)) {
+                                       a.setEnabled(false);
+                               }
+                               ComboContribution menu = menus.get(commandId);
+                               if (menu != null) {
+                                       menu.setEnabled(false);
+                               }
+                               
+                       }
+        }
+    }
+
+    private void updateActionBars(IEditorPart part) {
+       restoreActionStates();
+        part.getEditorSite().getActionBars().updateActionBars();
+    }
+       
+       @Override
+       public void dispose() {
+               if (DEBUG) System.out.println("ToolBarContributor.dispose()");
+               setActiveEditor(null);
+               if (mgr != null) {
+                       if (!REUSE) {
+                               for (IContributionItem item : items) {
+                                       mgr.remove(item);
+                                       item.dispose();
+                               }
+                       }
+                       items.clear();
+                       
+                       for (String commandId : actions.getKeys()) {
+                               for (CommandAction a : actions.getValues(commandId)) {
+                                       a.getCommand().removeCommandListener(this);
+                               }
+                               
+                       }
+                       actions.clear();
+                       
+                       // without this the contributed toolbar widgets would continue reserve the space even when they are destroyed.
+                       coolBarManager.update(true);
+                       mgr.update(true);
+               }
+               CommandStateRegistry.getInstance().removeListener(this);
+               super.dispose();
+               activePart = null;
+               if (partListener != null) {
+                       PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().addPartListener(partListener);
+                       partListener = null;
+               }
+       }
+       
+       boolean settingState = false;
+       private void storeRadioActionState(CommandRadioAction action, boolean checked) {
+               if (activePart == null)
+                       return;
+               settingState = true;
+               stateRegistry.setEditorState(activePart, action.getCommandId(), action.getValue());
+               settingState = false;
+       }
+       
+       private void storeToggleActionState(CommandAction action, boolean checked) {
+               if (activePart == null)
+                       return;
+               settingState = true;
+               stateRegistry.setEditorState(activePart, action.getCommandId(), checked);
+               settingState = false;
+       }
+       
+       
+       
+       private void restoreActionStates() {
+               if (activePart == null)
+                       return;
+               if (DEBUG)System.out.println("Restore " + activePart);
+               // toggles
+               Map<String,Boolean> defaultToggleStates = stateRegistry.getDefaultToggleStates();
+               for (String commandId : defaultToggleStates.keySet()) {
+                       for (CommandAction a : actions.getValues(commandId)) {
+                               if (DEBUG)System.out.println(commandId + " def " + defaultToggleStates.get(commandId));
+                               a.setChecked(defaultToggleStates.get(commandId));
+                       }
+               }
+               Map<String,Boolean> editorStates = stateRegistry.getEditorToggleStates(activePart);//toggleStates.get(activePart);
+               if (editorStates != null) {
+                       for (String commandId : editorStates.keySet()) {
+                               for (CommandAction a : actions.getValues(commandId)) {
+                                       if (DEBUG)System.out.println(commandId + " " + editorStates.get(commandId));
+                                       a.setChecked(editorStates.get(commandId));
+                               }
+                       }
+               }
+               // radios
+               Map<String,String> defaultRadioStates = stateRegistry.getDefaultRadioStates();
+               for (String commandId : defaultRadioStates.keySet()) {
+                       String defaultValue = defaultRadioStates.get(commandId);
+                       for (CommandAction a : actions.getValues(commandId)) {
+                               CommandRadioAction r = (CommandRadioAction)a;
+                               if (DEBUG)System.out.println(commandId + " def " + r.getValue().equals(defaultValue) +" " + r.getValue());
+                               r.setChecked(r.getValue().equals(defaultValue));
+                       }
+               }
+               
+               Map<String,String> editorRadioStates = stateRegistry.getEditorRadioStates(activePart);//radioStates.get(activePart);
+               if (editorRadioStates != null) {
+                       for (String commandId : editorRadioStates.keySet()) {
+                               String defaultValue = editorRadioStates.get(commandId);
+                               for (CommandAction a : actions.getValues(commandId)) {
+                                       CommandRadioAction r = (CommandRadioAction)a;
+                                       if (DEBUG)System.out.println(commandId + " " + r.getValue().equals(defaultValue) +" " + r.getValue());
+                                       r.setChecked(r.getValue().equals(defaultValue));
+                               }
+                       }
+               }
+               
+               for (ComboContribution c : menus.values()) {
+                       c.updateSelection();
+               }
+
+       }
+       
+       @Override
+       public void partActivated(IWorkbenchPart part) {
+
+       }
+       
+       @Override
+       public void partBroughtToTop(IWorkbenchPart part) {
+               
+       }
+       
+       @Override
+       public void partClosed(IWorkbenchPart part) {
+               parts.remove(part);
+               stateRegistry.clearStates(part);
+               part.getSite().getPage().removePartListener(this);
+               if (parts.size() == 0) {
+                       
+               }
+               if (part instanceof IEditorPart)
+                       ((IEditorPart)part).getEditorSite().getActionBars().updateActionBars();
+               
+       }
+       
+       @Override
+       public void partDeactivated(IWorkbenchPart part) {
+               
+       }
+       
+       @Override
+       public void partOpened(IWorkbenchPart part) {
+               
+       }
+       
+       private boolean getToggleState(Command command) {
+               State toggleState = command.getState(RegistryToggleState.STATE_ID);
+               return (Boolean)toggleState.getValue();
+       }
+       
+       private interface ICommandWrapper {
+               
+               public Command getCommand();
+               public String getCommandId();
+               public void run();
+       }
+       
+       private class CommandWrapper implements ICommandWrapper{
+               private Command command;
+               
+               public CommandWrapper(Command command) {
+                       this.command = command;
+               }
+               
+               @Override
+               public Command getCommand() {
+                       return command;
+               }
+               
+               @Override
+               public String getCommandId() {
+                       return command.getId();
+               }
+               
+               @Override
+               public void run() {
+                       try {
+                               handlerService.executeCommand(command.getId(), null);
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                       }
+               }
+               
+               @Override
+               public boolean equals(Object obj) {
+                       if (obj.getClass() != getClass())
+                               return false;
+                       CommandWrapper other= (CommandWrapper)obj;
+                       return other.getCommandId().equals(getCommandId());
+               }
+       }
+       
+       private class ParameterizedCommandWrapper implements ICommandWrapper{
+               private ParameterizedCommand command;
+               
+               public ParameterizedCommandWrapper(ParameterizedCommand command) {
+                       this.command = command;
+               }
+               
+               @Override
+               public Command getCommand() {
+                       return command.getCommand();
+               }
+               
+               @Override
+               public String getCommandId() {
+                       return command.getId();
+               }
+               
+               @Override
+               public void run() {
+                       try {
+                               handlerService.executeCommand(command, null);
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                       }
+               }
+               
+               @Override
+               public boolean equals(Object obj) {
+                       if (obj.getClass() != getClass())
+                               return false;
+                       ParameterizedCommandWrapper other= (ParameterizedCommandWrapper)obj;
+                       return other.command.equals(command);
+               }
+       }
+       
+       private abstract class CommandAction extends Action {
+               private ICommandWrapper command;
+               
+               public CommandAction(ICommandWrapper command, String name, ImageDescriptor image, int style) {
+                       super(name,style);
+                       this.command = command;
+                       if (image != null)
+                               setImageDescriptor(image);
+               }
+               
+               @Override
+               public void run() {
+                       command.run();
+               }
+               
+               public Command getCommand() {
+                       return command.getCommand();
+               }
+               
+               public String getCommandId() {
+                       return command.getCommandId();
+               }
+               
+
+               @Override
+               public boolean equals(Object obj) {
+                       if (obj.getClass() != getClass())
+                               return false;
+                       CommandAction other= (CommandAction)obj;
+                       return command.equals(other.command);
+               }
+
+               
+               @Override
+               public int hashCode() {
+                       return command.getCommandId().hashCode();
+               }
+       }
+       
+       
+       private class CommandCheckboxAction extends CommandAction {
+               
+               public CommandCheckboxAction(ICommandWrapper command, String name, ImageDescriptor image) {
+                       super(command,name,image,Action.AS_CHECK_BOX);
+                       
+               }
+               
+               @Override
+               public void run() {
+                       boolean checked = isChecked(); 
+                       storeToggleActionState(this, checked);
+                       try {
+                               if (checked == getToggleState(getCommand()))
+                                       HandlerUtil.toggleCommandState(getCommand());
+                       } catch (ExecutionException e) {
+                               e.printStackTrace();
+                       }
+                       super.run();
+               }
+               
+       }
+       
+       private class CommandRadioAction extends CommandAction {
+
+               private String value;
+               
+               public CommandRadioAction(ICommandWrapper command, String name, String value, ImageDescriptor image) {
+                       super(command,name,image,Action.AS_RADIO_BUTTON);
+                       this.value = value;
+               }
+               
+               @Override
+               public void run() {
+                       boolean checked = isChecked(); 
+                       storeRadioActionState(this, checked);
+                       try {
+                               HandlerUtil.updateRadioState(getCommand(), value);
+                       } catch (ExecutionException e) {
+                               e.printStackTrace();
+                               return;
+                       }
+                       super.run();
+               }
+               
+               public String getValue() {
+                       return value;
+               }
+               
+               @Override
+               public boolean equals(Object obj) {
+                       if (obj.getClass() != getClass())
+                               return false;
+                       CommandRadioAction other= (CommandRadioAction)obj;
+                       if (!other.getCommandId().equals(getCommandId()))
+                               return false;
+                       if (!other.value.equals(value))
+                               return false;
+                       return true;
+               }
+               
+       }
+
+       private class CommandPushAction extends CommandAction {
+               
+               public CommandPushAction(ICommandWrapper command, String name, ImageDescriptor image) {
+                       super(command,name,image,Action.AS_PUSH_BUTTON);
+               }
+
+       }
+       
+       private class ComboContribution extends WorkbenchWindowControlContribution {
+               private TableCombo combo;
+               
+               private List<Action> actions = new ArrayList<Action>();
+               
+               @Override
+               protected Control createControl(Composite parent) {
+                       Composite container = new Composite(parent, SWT.NONE);
+                       GridLayout glContainer = new GridLayout(1, false);
+                       glContainer.marginTop = 0;
+                       glContainer.marginHeight = 0;
+                       glContainer.marginWidth = 0;
+                       container.setLayout(glContainer);
+                       GridData glReader = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
+                       combo = new TableCombo(container, SWT.BORDER | SWT.READ_ONLY);
+                       combo.setLayoutData(glReader);
+
+                       for (Action a : actions) {
+                               TableItem item = new TableItem(combo.getTable(), SWT.NONE);
+                               item.setText(a.getText());
+                               if (a.getImageDescriptor() != null)
+                                       item.setImage(a.getImageDescriptor().createImage());
+                       }
+                       
+                       combo.addSelectionListener(new SelectionListener() {
+                               
+                               @Override
+                               public void widgetSelected(SelectionEvent e) {
+                                       int index = combo.getSelectionIndex();
+                                       if (index == -1)
+                                               return;
+                                       actions.get(index).run();
+                               }
+                               
+                               @Override
+                               public void widgetDefaultSelected(SelectionEvent e) {
+                                       
+                               }
+                       });
+                       updateSelection();
+                       return container;
+               }
+               
+               public boolean addAction(Action a) {
+                       // old action must be replaced. (otherwise reused ComboContributor would use different instances to ToolBarContributor.) 
+                       actions.remove(a);
+                       actions.add(a);
+                       return true;
+                       
+               }
+               
+               void updateSelection() {
+                       if (combo == null)
+                               return;
+                       for (int i = 0; i < actions.size(); i++) {
+                               if (actions.get(i).isChecked()) {
+                                       combo.select(i);
+                                       return;
+                               }
+                       }
+               }
+               
+               public void setEnabled(boolean enabled) {
+                       if (combo != null)
+                               combo.setEnabled(enabled);
+               }
+               
+               @Override
+               public void dispose() {
+                       combo.dispose();
+                       super.dispose();
+               }
+       }
+       
+}