]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d/src/org/simantics/g3d/toolbar/ToolbarContributor.java
9f87b327e70ce3e8ccb41993658316de2fb2f7c6
[simantics/3d.git] / org.simantics.g3d / src / org / simantics / g3d / toolbar / ToolbarContributor.java
1 package org.simantics.g3d.toolbar;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.HashMap;\r
5 import java.util.HashSet;\r
6 import java.util.List;\r
7 import java.util.Map;\r
8 import java.util.Set;\r
9 \r
10 import org.eclipse.core.commands.Command;\r
11 import org.eclipse.core.commands.CommandEvent;\r
12 import org.eclipse.core.commands.ExecutionException;\r
13 import org.eclipse.core.commands.ICommandListener;\r
14 import org.eclipse.core.commands.State;\r
15 import org.eclipse.jface.action.Action;\r
16 import org.eclipse.jface.action.ActionContributionItem;\r
17 import org.eclipse.jface.action.IContributionItem;\r
18 import org.eclipse.jface.action.ICoolBarManager;\r
19 import org.eclipse.jface.action.IToolBarManager;\r
20 import org.eclipse.jface.action.ToolBarContributionItem;\r
21 import org.eclipse.jface.resource.ImageDescriptor;\r
22 import org.eclipse.nebula.widgets.tablecombo.TableCombo;\r
23 import org.eclipse.swt.SWT;\r
24 import org.eclipse.swt.events.SelectionEvent;\r
25 import org.eclipse.swt.events.SelectionListener;\r
26 import org.eclipse.swt.layout.GridData;\r
27 import org.eclipse.swt.layout.GridLayout;\r
28 import org.eclipse.swt.widgets.Composite;\r
29 import org.eclipse.swt.widgets.Control;\r
30 import org.eclipse.swt.widgets.TableItem;\r
31 import org.eclipse.ui.IEditorPart;\r
32 import org.eclipse.ui.IPartListener;\r
33 import org.eclipse.ui.IWorkbenchPart;\r
34 import org.eclipse.ui.PlatformUI;\r
35 import org.eclipse.ui.commands.ICommandService;\r
36 import org.eclipse.ui.handlers.HandlerUtil;\r
37 import org.eclipse.ui.handlers.IHandlerService;\r
38 import org.eclipse.ui.handlers.RadioState;\r
39 import org.eclipse.ui.handlers.RegistryToggleState;\r
40 import org.eclipse.ui.menus.WorkbenchWindowControlContribution;\r
41 import org.eclipse.ui.part.EditorActionBarContributor;\r
42 import org.simantics.db.common.utils.ErrorLogger;\r
43 import org.simantics.g3d.Activator;\r
44 import org.simantics.g3d.toolbar.ToolBarCommandRegistry.ToolbarCommandExtension;\r
45 import org.simantics.utils.datastructures.MapList;\r
46 \r
47 \r
48 /**\r
49  * EditorBarContributor, which tracks toggle states separately for each command.\r
50  * \r
51  * @see org.simantics.g3d.toolbarCommand Extension Point\r
52  * \r
53  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
54  * \r
55  * \r
56  * \r
57  * TODO : test radio buttons.\r
58  * TODO : configuring the position of buttons. \r
59  *\r
60  */\r
61 public abstract class ToolbarContributor extends EditorActionBarContributor implements ICommandListener, IPartListener {\r
62 \r
63         private static final String PLATFORM = "platform:/plugin/";\r
64         \r
65         private IEditorPart    activePart;\r
66         private Set<IEditorPart> parts = new HashSet<IEditorPart>();\r
67     IToolBarManager        mgr;\r
68     \r
69     \r
70     ICommandService service;\r
71     IHandlerService handlerService;\r
72     List<IContributionItem> items = new ArrayList<IContributionItem>();\r
73     MapList<String, CommandAction> actions = new MapList<String, ToolbarContributor.CommandAction>();\r
74     \r
75     CommandStateRegistry stateRegistry;\r
76         \r
77         private Map<String,ComboContribution> menus = new HashMap<String, ComboContribution>();\r
78         \r
79         public ToolbarContributor() {\r
80                 service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); \r
81                 handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);\r
82                 stateRegistry = CommandStateRegistry.getInstance();\r
83         }\r
84         \r
85         public abstract String getToolbarId();\r
86         \r
87         public void contributeToCoolBar(ICoolBarManager coolBarManager) {\r
88                 IContributionItem toolBar = coolBarManager.find(getToolbarId());\r
89                  if (toolBar instanceof ToolBarContributionItem)\r
90                  mgr = ((ToolBarContributionItem) toolBar).getToolBarManager();\r
91              if (mgr == null)\r
92                     return;\r
93              \r
94              createCommands();\r
95              \r
96              mgr.markDirty();\r
97              \r
98         }\r
99         \r
100         private void createCommands() {\r
101                 for (ToolbarCommandExtension ext : ToolBarCommandRegistry.getInstance().getExtensions(getToolbarId())) {\r
102                         addCommand(ext);\r
103                 }\r
104         }\r
105         \r
106         private void addCommand(ToolbarCommandExtension ext) {\r
107                 String commandId = ext.commandId;\r
108                 Command command = service.getCommand(commandId);\r
109                 \r
110                 String type = ext.type;\r
111                 \r
112                 State toggleState = command.getState(RegistryToggleState.STATE_ID);\r
113                 State radioState = command.getState(RadioState.STATE_ID);\r
114                 \r
115                 String name = ext.name;\r
116                 \r
117                 \r
118                 ImageDescriptor image = getImage(ext);\r
119                 \r
120                 CommandAction a = null;\r
121                 if (type.equals("toggle") && toggleState != null) {\r
122                         a = new CommandCheckboxAction(command,name,image);\r
123 \r
124                         stateRegistry.storeDefaultState(commandId);\r
125                 } else if (radioState != null && ext.value != null) {\r
126                         stateRegistry.storeDefaultState(commandId);\r
127                         if (type.equals("radio")) {\r
128                                 a = new CommandRadioAction(command,name,ext.value,image);\r
129                         } else if (type.equals("combo")) {\r
130                                 a = new CommandRadioAction(command,name,ext.value,image);\r
131                                 ComboContribution combo = menus.get(commandId);\r
132                                 if (combo == null) {\r
133                                         combo = new ComboContribution();\r
134                                         menus.put(commandId, combo);\r
135                                         items.add(combo);\r
136                                         mgr.add(combo);\r
137                                         a.getCommand().addCommandListener(this);\r
138                                 }\r
139                                 actions.add(commandId,a);\r
140                                 combo.addAction(a);\r
141                                 return;\r
142                         }\r
143                 } else if (type.equals("push")) {\r
144                         a = new CommandPushAction(command,name,image);\r
145                 } else {\r
146                         ErrorLogger.defaultLogError(ext + " is not valid.");\r
147                         return;\r
148                 }\r
149                 a.getCommand().addCommandListener(this);\r
150                 IContributionItem item =  new ActionContributionItem(a);\r
151                 actions.add(commandId,a);\r
152                 items.add(item);\r
153                 mgr.add(item);\r
154         }\r
155         \r
156         private ImageDescriptor getImage(ToolbarCommandExtension ext) {\r
157                 ImageDescriptor image = null;\r
158                 if (ext.image != null) {\r
159                         String plugin = null;\r
160                         String file = null;\r
161                         if (ext.image.startsWith(PLATFORM)) {\r
162                                 String s = ext.image.substring(PLATFORM.length());\r
163                                 int i = s.indexOf("/");\r
164                                 plugin = s.substring(0,i);\r
165                                 file = s.substring(i+1);\r
166                         } else {\r
167                                 plugin = ext.contributorId;\r
168                                 file = ext.image;\r
169                         }\r
170                         image = Activator.imageDescriptorFromPlugin(plugin, file);\r
171                 }\r
172                 return image;\r
173         }\r
174         \r
175 \r
176         \r
177         @Override\r
178         public void commandChanged(CommandEvent commandEvent) {\r
179                 if (commandEvent.isHandledChanged()||commandEvent.isEnabledChanged()) {\r
180                         Command command = commandEvent.getCommand();\r
181                         String commandId = command.getId();\r
182                         for (CommandAction a : actions.getValues(commandId)) {\r
183                                 a.setEnabled(command.isHandled() && command.isEnabled());\r
184                         }\r
185                 }\r
186         }\r
187         \r
188         @Override\r
189         public void setActiveEditor(IEditorPart targetEditor) {\r
190                 if (targetEditor == activePart)\r
191                         return;\r
192                 setContext(targetEditor);\r
193         }\r
194         \r
195         private void setContext(IEditorPart part) {\r
196                 this.activePart = part;\r
197         if (!parts.contains(activePart)) {\r
198                 activePart.getSite().getPage().addPartListener(this);\r
199         }\r
200         if (part != null) {\r
201                 for (String commandId : actions.getKeys()) {\r
202                                 for (CommandAction a : actions.getValues(commandId)) {\r
203                                         a.setEnabled(true);\r
204                                 }\r
205                         }\r
206             updateActionBars(part);\r
207         } else {\r
208                         for (String commandId : actions.getKeys()) {\r
209                                 for (CommandAction a : actions.getValues(commandId)) {\r
210                                         a.setEnabled(false);\r
211                                 }\r
212                         }\r
213         }\r
214     }\r
215 \r
216     private void updateActionBars(IEditorPart part) {\r
217         restoreActionStates();\r
218         part.getEditorSite().getActionBars().updateActionBars();\r
219     }\r
220         \r
221         @Override\r
222         public void dispose() {\r
223                 if (mgr != null) {\r
224                         for (IContributionItem item : items) {\r
225                                 mgr.remove(item);\r
226                                 item.dispose();\r
227                         }\r
228                         mgr.markDirty();\r
229                         mgr.update(true);\r
230                         if (activePart != null) {\r
231                                  activePart.getEditorSite().getActionBars().updateActionBars();\r
232                         }\r
233                         \r
234                         for (String commandId : actions.getKeys()) {\r
235                                 for (CommandAction a : actions.getValues(commandId)) {\r
236                                         a.getCommand().removeCommandListener(this);\r
237                                 }\r
238                         }\r
239                         actions.clear();\r
240                 }\r
241                 \r
242                 super.dispose();\r
243                 activePart = null;\r
244         }\r
245         \r
246 \r
247         private void storeRadioActionState(CommandRadioAction action, boolean checked) {\r
248                 if (activePart == null)\r
249                         return;\r
250                 stateRegistry.setEditorState(activePart, action.getCommandId(), action.getValue());\r
251         }\r
252         \r
253         private void storeToggleActionState(CommandAction action, boolean checked) {\r
254                 if (activePart == null)\r
255                         return;\r
256                 stateRegistry.setEditorState(activePart, action.getCommandId(), checked);\r
257         }\r
258         \r
259         private void restoreActionStates() {\r
260                 if (activePart == null)\r
261                         return;\r
262                 // toggles\r
263                 Map<String,Boolean> defaultToggleStates = stateRegistry.getDefaultToggleStates();\r
264                 for (String commandId : defaultToggleStates.keySet()) {\r
265                         for (CommandAction a : actions.getValues(commandId)) {\r
266                                 a.setChecked(defaultToggleStates.get(commandId));\r
267                         }\r
268                 }\r
269                 Map<String,Boolean> editorStates = stateRegistry.getEditorToggleStates(activePart);//toggleStates.get(activePart);\r
270                 if (editorStates != null) {\r
271                         for (String commandId : editorStates.keySet()) {\r
272                                 for (CommandAction a : actions.getValues(commandId)) {\r
273                                         a.setChecked(editorStates.get(commandId));\r
274                                 }\r
275                         }\r
276                 }\r
277                 // radios\r
278                 Map<String,String> defaultRadioStates = stateRegistry.getDefaultRadioStates();\r
279                 for (String commandId : defaultRadioStates.keySet()) {\r
280                         String defaultValue = defaultRadioStates.get(commandId);\r
281                         for (CommandAction a : actions.getValues(commandId)) {\r
282                                 CommandRadioAction r = (CommandRadioAction)a;\r
283                                 r.setChecked(r.getValue().equals(defaultValue));\r
284                         }\r
285                 }\r
286                 \r
287                 Map<String,String> editorRadioStates = stateRegistry.getEditorRadioStates(activePart);//radioStates.get(activePart);\r
288                 if (editorRadioStates != null) {\r
289                         for (String commandId : editorRadioStates.keySet()) {\r
290                                 String defaultValue = editorRadioStates.get(commandId);\r
291                                 for (CommandAction a : actions.getValues(commandId)) {\r
292                                         CommandRadioAction r = (CommandRadioAction)a;\r
293                                         r.setChecked(r.getValue().equals(defaultValue));\r
294                                 }\r
295                         }\r
296                 }\r
297                 \r
298                 for (ComboContribution c : menus.values()) {\r
299                         c.updateSelection();\r
300                 }\r
301                 \r
302 \r
303         }\r
304         \r
305         @Override\r
306         public void partActivated(IWorkbenchPart part) {\r
307 \r
308         }\r
309         \r
310         @Override\r
311         public void partBroughtToTop(IWorkbenchPart part) {\r
312                 \r
313         }\r
314         \r
315         @Override\r
316         public void partClosed(IWorkbenchPart part) {\r
317                 parts.remove(part);\r
318                 stateRegistry.clearStates(part);\r
319                 part.getSite().getPage().removePartListener(this);\r
320         }\r
321         \r
322         @Override\r
323         public void partDeactivated(IWorkbenchPart part) {\r
324                 \r
325         }\r
326         \r
327         @Override\r
328         public void partOpened(IWorkbenchPart part) {\r
329                 \r
330         }\r
331         \r
332         private boolean getToggleState(Command command) {\r
333                 State toggleState = command.getState(RegistryToggleState.STATE_ID);\r
334                 return (Boolean)toggleState.getValue();\r
335         }\r
336         \r
337         private abstract class CommandAction extends Action {\r
338                 private Command command;\r
339                 \r
340                 public CommandAction(Command command, String name, ImageDescriptor image, int style) {\r
341                         super(name,style);\r
342                         this.command = command;\r
343                         if (image != null)\r
344                                 setImageDescriptor(image);\r
345                 }\r
346                 \r
347                 @Override\r
348                 public void run() {\r
349                         try {\r
350                                 handlerService.executeCommand(command.getId(), null);\r
351                         } catch (Exception e) {\r
352                                 e.printStackTrace();\r
353                         }\r
354                 }\r
355                 \r
356                 public Command getCommand() {\r
357                         return command;\r
358                 }\r
359                 \r
360                 public String getCommandId() {\r
361                         return command.getId();\r
362                 }\r
363         }\r
364         \r
365         private class CommandCheckboxAction extends CommandAction {\r
366                 \r
367                 public CommandCheckboxAction(Command command, String name, ImageDescriptor image) {\r
368                         super(command,name,image,Action.AS_CHECK_BOX);\r
369                         \r
370                 }\r
371                 \r
372                 @Override\r
373                 public void run() {\r
374                         boolean checked = isChecked(); \r
375                         storeToggleActionState(this, checked);\r
376                         try {\r
377                                 if (checked == getToggleState(getCommand()))\r
378                                         HandlerUtil.toggleCommandState(getCommand());\r
379                         } catch (ExecutionException e) {\r
380                                 e.printStackTrace();\r
381                         }\r
382                         super.run();\r
383                 }\r
384                 \r
385         }\r
386         \r
387         private class CommandRadioAction extends CommandAction {\r
388 \r
389                 private String value;\r
390                 \r
391                 public CommandRadioAction(Command command, String name, String value, ImageDescriptor image) {\r
392                         super(command,name,image,Action.AS_RADIO_BUTTON);\r
393                         this.value = value;\r
394                 }\r
395                 \r
396                 @Override\r
397                 public void run() {\r
398                         boolean checked = isChecked(); \r
399                         storeRadioActionState(this, checked);\r
400                         try {\r
401                                 HandlerUtil.updateRadioState(getCommand(), value);\r
402                         } catch (ExecutionException e) {\r
403                                 e.printStackTrace();\r
404                                 return;\r
405                         }\r
406                         super.run();\r
407                 }\r
408                 \r
409                 public String getValue() {\r
410                         return value;\r
411                 }\r
412                 \r
413         }\r
414 \r
415         private class CommandPushAction extends CommandAction {\r
416                 \r
417                 public CommandPushAction(Command command, String name, ImageDescriptor image) {\r
418                         super(command,name,image,Action.AS_PUSH_BUTTON);\r
419                 }\r
420 \r
421         }\r
422         \r
423         private class ComboContribution extends WorkbenchWindowControlContribution {\r
424                 private TableCombo combo;\r
425                 \r
426                 private List<Action> actions = new ArrayList<Action>();\r
427                 \r
428                 @Override\r
429                 protected Control createControl(Composite parent) {\r
430                         Composite container = new Composite(parent, SWT.NONE);\r
431                         GridLayout glContainer = new GridLayout(1, false);\r
432                         glContainer.marginTop = 0;\r
433                         glContainer.marginHeight = 0;\r
434                         glContainer.marginWidth = 0;\r
435                         container.setLayout(glContainer);\r
436                         GridData glReader = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);\r
437                         combo = new TableCombo(container, SWT.BORDER | SWT.READ_ONLY);\r
438                         combo.setLayoutData(glReader);\r
439 \r
440                         for (Action a : actions) {\r
441                                 TableItem item = new TableItem(combo.getTable(), SWT.NONE);\r
442                                 item.setText(a.getText());\r
443                                 if (a.getImageDescriptor() != null)\r
444                                         item.setImage(a.getImageDescriptor().createImage());\r
445                         }\r
446                         \r
447                         combo.addSelectionListener(new SelectionListener() {\r
448                                 \r
449                                 @Override\r
450                                 public void widgetSelected(SelectionEvent e) {\r
451                                         int index = combo.getSelectionIndex();\r
452                                         if (index == -1)\r
453                                                 return;\r
454                                         actions.get(index).run();\r
455                                 }\r
456                                 \r
457                                 @Override\r
458                                 public void widgetDefaultSelected(SelectionEvent e) {\r
459                                         \r
460                                 }\r
461                         });\r
462                         updateSelection();\r
463                         return container;\r
464                 }\r
465                 \r
466                 public void addAction(Action a) {\r
467                         actions.add(a);\r
468                 }\r
469                 \r
470                 void updateSelection() {\r
471                         if (combo == null)\r
472                                 return;\r
473                         for (int i = 0; i < actions.size(); i++) {\r
474                                 if (actions.get(i).isChecked()) {\r
475                                         combo.select(i);\r
476                                         return;\r
477                                 }\r
478                         }\r
479                 }\r
480         }\r
481         \r
482 }\r