]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.g3d/src/org/simantics/g3d/toolbar/ToolbarContributor.java
3D framework (Simca 2012)
[simantics/3d.git] / org.simantics.g3d / src / org / simantics / g3d / toolbar / ToolbarContributor.java
diff --git a/org.simantics.g3d/src/org/simantics/g3d/toolbar/ToolbarContributor.java b/org.simantics.g3d/src/org/simantics/g3d/toolbar/ToolbarContributor.java
new file mode 100644 (file)
index 0000000..9f87b32
--- /dev/null
@@ -0,0 +1,482 @@
+package org.simantics.g3d.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.State;\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.ErrorLogger;\r
+import org.simantics.g3d.Activator;\r
+import org.simantics.g3d.toolbar.ToolBarCommandRegistry.ToolbarCommandExtension;\r
+import org.simantics.utils.datastructures.MapList;\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 : test radio buttons.\r
+ * TODO : configuring the position of buttons. \r
+ *\r
+ */\r
+public abstract class ToolbarContributor extends EditorActionBarContributor implements ICommandListener, IPartListener {\r
+\r
+       private static final String PLATFORM = "platform:/plugin/";\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
+       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
+       }\r
+       \r
+       public abstract String getToolbarId();\r
+       \r
+       public void contributeToCoolBar(ICoolBarManager coolBarManager) {\r
+               IContributionItem toolBar = coolBarManager.find(getToolbarId());\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
+               String commandId = ext.commandId;\r
+               Command command = service.getCommand(commandId);\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(command,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(command,name,ext.value,image);\r
+                       } else if (type.equals("combo")) {\r
+                               a = new CommandRadioAction(command,name,ext.value,image);\r
+                               ComboContribution combo = menus.get(commandId);\r
+                               if (combo == null) {\r
+                                       combo = new ComboContribution();\r
+                                       menus.put(commandId, combo);\r
+                                       items.add(combo);\r
+                                       mgr.add(combo);\r
+                                       a.getCommand().addCommandListener(this);\r
+                               }\r
+                               actions.add(commandId,a);\r
+                               combo.addAction(a);\r
+                               return;\r
+                       }\r
+               } else if (type.equals("push")) {\r
+                       a = new CommandPushAction(command,name,image);\r
+               } else {\r
+                       ErrorLogger.defaultLogError(ext + " is not valid.");\r
+                       return;\r
+               }\r
+               a.getCommand().addCommandListener(this);\r
+               IContributionItem item =  new ActionContributionItem(a);\r
+               actions.add(commandId,a);\r
+               items.add(item);\r
+               mgr.add(item);\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
+       private void setContext(IEditorPart part) {\r
+               this.activePart = part;\r
+        if (!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
+                       }\r
+            updateActionBars(part);\r
+        } else {\r
+                       for (String commandId : actions.getKeys()) {\r
+                               for (CommandAction a : actions.getValues(commandId)) {\r
+                                       a.setEnabled(false);\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 (mgr != null) {\r
+                       for (IContributionItem item : items) {\r
+                               mgr.remove(item);\r
+                               item.dispose();\r
+                       }\r
+                       mgr.markDirty();\r
+                       mgr.update(true);\r
+                       if (activePart != null) {\r
+                                activePart.getEditorSite().getActionBars().updateActionBars();\r
+                       }\r
+                       \r
+                       for (String commandId : actions.getKeys()) {\r
+                               for (CommandAction a : actions.getValues(commandId)) {\r
+                                       a.getCommand().removeCommandListener(this);\r
+                               }\r
+                       }\r
+                       actions.clear();\r
+               }\r
+               \r
+               super.dispose();\r
+               activePart = null;\r
+       }\r
+       \r
+\r
+       private void storeRadioActionState(CommandRadioAction action, boolean checked) {\r
+               if (activePart == null)\r
+                       return;\r
+               stateRegistry.setEditorState(activePart, action.getCommandId(), action.getValue());\r
+       }\r
+       \r
+       private void storeToggleActionState(CommandAction action, boolean checked) {\r
+               if (activePart == null)\r
+                       return;\r
+               stateRegistry.setEditorState(activePart, action.getCommandId(), checked);\r
+       }\r
+       \r
+       private void restoreActionStates() {\r
+               if (activePart == null)\r
+                       return;\r
+               // toggles\r
+               Map<String,Boolean> defaultToggleStates = stateRegistry.getDefaultToggleStates();\r
+               for (String commandId : defaultToggleStates.keySet()) {\r
+                       for (CommandAction a : actions.getValues(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
+                                       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
+                               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
+                                       r.setChecked(r.getValue().equals(defaultValue));\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               for (ComboContribution c : menus.values()) {\r
+                       c.updateSelection();\r
+               }\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
+       }\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 abstract class CommandAction extends Action {\r
+               private Command command;\r
+               \r
+               public CommandAction(Command 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
+                       try {\r
+                               handlerService.executeCommand(command.getId(), null);\r
+                       } catch (Exception e) {\r
+                               e.printStackTrace();\r
+                       }\r
+               }\r
+               \r
+               public Command getCommand() {\r
+                       return command;\r
+               }\r
+               \r
+               public String getCommandId() {\r
+                       return command.getId();\r
+               }\r
+       }\r
+       \r
+       private class CommandCheckboxAction extends CommandAction {\r
+               \r
+               public CommandCheckboxAction(Command 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(Command 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
+       }\r
+\r
+       private class CommandPushAction extends CommandAction {\r
+               \r
+               public CommandPushAction(Command 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 void addAction(Action a) {\r
+                       actions.add(a);\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
+       \r
+}\r