]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.ui.toolbar;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Set;
9
10 import org.eclipse.core.commands.Command;
11 import org.eclipse.core.commands.CommandEvent;
12 import org.eclipse.core.commands.ExecutionException;
13 import org.eclipse.core.commands.ICommandListener;
14 import org.eclipse.core.commands.IParameter;
15 import org.eclipse.core.commands.Parameterization;
16 import org.eclipse.core.commands.ParameterizedCommand;
17 import org.eclipse.core.commands.State;
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IConfigurationElement;
20 import org.eclipse.core.runtime.IExecutableExtension;
21 import org.eclipse.jface.action.Action;
22 import org.eclipse.jface.action.ActionContributionItem;
23 import org.eclipse.jface.action.IContributionItem;
24 import org.eclipse.jface.action.ICoolBarManager;
25 import org.eclipse.jface.action.IToolBarManager;
26 import org.eclipse.jface.action.ToolBarContributionItem;
27 import org.eclipse.jface.resource.ImageDescriptor;
28 import org.eclipse.nebula.widgets.tablecombo.TableCombo;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.events.SelectionEvent;
31 import org.eclipse.swt.events.SelectionListener;
32 import org.eclipse.swt.layout.GridData;
33 import org.eclipse.swt.layout.GridLayout;
34 import org.eclipse.swt.widgets.Composite;
35 import org.eclipse.swt.widgets.Control;
36 import org.eclipse.swt.widgets.TableItem;
37 import org.eclipse.ui.IEditorPart;
38 import org.eclipse.ui.IPartListener;
39 import org.eclipse.ui.IWorkbenchPart;
40 import org.eclipse.ui.PlatformUI;
41 import org.eclipse.ui.commands.ICommandService;
42 import org.eclipse.ui.handlers.HandlerUtil;
43 import org.eclipse.ui.handlers.IHandlerService;
44 import org.eclipse.ui.handlers.RadioState;
45 import org.eclipse.ui.handlers.RegistryToggleState;
46 import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
47 import org.eclipse.ui.part.EditorActionBarContributor;
48 import org.simantics.db.common.utils.Logger;
49 import org.simantics.ui.internal.Activator;
50 import org.simantics.ui.toolbar.ToolBarCommandRegistry.Parameter;
51 import org.simantics.ui.toolbar.ToolBarCommandRegistry.ToolbarCommandExtension;
52 import org.simantics.utils.datastructures.MapList;
53 import org.simantics.utils.ui.ExceptionUtils;
54
55
56 /**
57  * EditorBarContributor, which tracks toggle states separately for each command.
58  * 
59  * @see org.simantics.g3d.toolbarCommand Extension Point
60  * 
61  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
62  * 
63  * 
64  * 
65  * TODO : configuring the position of buttons. 
66  *
67  */
68 public class ToolbarContributor extends EditorActionBarContributor implements ICommandListener, IPartListener, CommandStateListener, IExecutableExtension {
69
70         private static boolean DEBUG = false;                   // Print debug messages to console
71         private boolean REUSE = true;                           // true: Reuse contribution items (leave toolbar in disabled state when editor closes)
72                                                         // false: delete items on dispose (remove toolbar editor closes) 
73         
74         private static final String PLATFORM = "platform:/plugin/";
75
76         private String toolbarId;
77         
78         private IEditorPart    activePart;
79         private Set<IEditorPart> parts = new HashSet<IEditorPart>();
80     IToolBarManager        mgr;
81     
82     
83     ICommandService service;
84     IHandlerService handlerService;
85     List<IContributionItem> items = new ArrayList<IContributionItem>();
86     MapList<String, CommandAction> actions = new MapList<String, ToolbarContributor.CommandAction>();
87     
88     CommandStateRegistry stateRegistry;
89     
90     IPartListener partListener;
91         
92         private Map<String,ComboContribution> menus = new HashMap<String, ComboContribution>();
93         
94         public ToolbarContributor() {
95                 service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); 
96                 handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
97                 stateRegistry = CommandStateRegistry.getInstance();
98                 // we need part listener to be notified for other editor activations (i.e editors that do not use this contributor).
99                 partListener = new IPartListener() {
100                         
101                         @Override
102                         public void partOpened(IWorkbenchPart part) {}
103                         
104                         @Override
105                         public void partDeactivated(IWorkbenchPart part) {}
106                         
107                         @Override
108                         public void partClosed(IWorkbenchPart part) {}
109                         
110                         @Override
111                         public void partBroughtToTop(IWorkbenchPart part) {}
112                         
113                         @Override
114                         public void partActivated(IWorkbenchPart part) {
115                                 if (part instanceof IEditorPart)
116                                         setContext2((IEditorPart)part);
117                         }
118                 };
119                 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().addPartListener(partListener);
120                 
121         }
122         
123         @Override
124         public void setInitializationData(IConfigurationElement config,String propertyName, Object data) throws CoreException {
125                 if (data instanceof String) {
126                          String[] parameters = ((String) data).split(";");
127                          for (String parameter : parameters) {
128                         String[] keyValue = parameter.split("=");
129                         if (keyValue.length > 2) {
130                             //ErrorLogger.defaultLogWarning("Invalid parameter '" + parameter + ". Complete view argument: " + data, null);
131                             continue;
132                         }
133                         String key = keyValue[0];
134                         String value = keyValue.length > 1 ? keyValue[1] : "";
135
136                         if ("toolbar".equals(key)) {
137                             toolbarId = value;
138                         }  else if ("hide".equals(key)) {
139                                 REUSE = !Boolean.parseBoolean(value);
140                         }
141                     }
142                 }
143                 
144         }
145         
146         public String getToolbarId() {
147                 return toolbarId;
148         }
149         
150         
151         private ICoolBarManager coolBarManager;
152         private IContributionItem toolBar;
153         public void contributeToCoolBar(ICoolBarManager coolBarManager) {
154                 this.coolBarManager = coolBarManager;
155                 toolBar = coolBarManager.find(getToolbarId());
156                 
157                  if (toolBar instanceof ToolBarContributionItem)
158                  mgr = ((ToolBarContributionItem) toolBar).getToolBarManager();
159              if (mgr == null)
160                     return;
161              
162              createCommands();
163              
164              mgr.markDirty();
165              
166         }
167         
168         private void createCommands() {
169                 for (ToolbarCommandExtension ext : ToolBarCommandRegistry.getInstance().getExtensions(getToolbarId())) {
170                         addCommand(ext);
171                 }
172         }
173         
174         private void addCommand(ToolbarCommandExtension ext) {
175                 if (DEBUG) System.out.println("Adding command to toolbar " +getToolbarId()  + " " + ext);
176                 String commandId = ext.commandId;
177                 Command command = service.getCommand(commandId);
178                 ICommandWrapper wrapper = new CommandWrapper(command);
179                 
180                 ParameterizedCommand parameterizedCommand = null;
181                 
182                 if (ext.parameters.size() > 0) {
183                         try {
184                                 Parameterization parameterizations[] = new Parameterization[ext.parameters.size()];
185                                 for (int i = 0; i < ext.parameters.size(); i++) {
186                                         Parameter param = ext.parameters.get(i);
187                                         IParameter parameter = command.getParameter(param.name);
188                                         parameterizations[i] = new Parameterization(parameter, param.value);
189                                 }
190                                 parameterizedCommand = new ParameterizedCommand(command, parameterizations);
191                                 wrapper = new ParameterizedCommandWrapper(parameterizedCommand);
192                         } catch (org.eclipse.core.commands.common.NotDefinedException e) {
193                                 e.printStackTrace();
194                                 ExceptionUtils.logError(e);
195                                 return;
196                         }
197                 }
198                 
199                 String type = ext.type;
200                 
201                 State toggleState = command.getState(RegistryToggleState.STATE_ID);
202                 State radioState = command.getState(RadioState.STATE_ID);
203                 
204                 String name = ext.name;
205                 
206                 
207                 ImageDescriptor image = getImage(ext);
208                 
209                 CommandAction a = null;
210                 if (type.equals("toggle") && toggleState != null) {
211                         a = new CommandCheckboxAction(wrapper,name,image);
212
213                         stateRegistry.storeDefaultState(commandId);
214                 } else if (radioState != null && ext.value != null) {
215                         stateRegistry.storeDefaultState(commandId);
216                         if (type.equals("radio")) {
217                                 a = new CommandRadioAction(wrapper,name,ext.value,image);
218                         } else if (type.equals("combo")) {
219                                 a = new CommandRadioAction(wrapper,name,ext.value,image);
220                                 ComboContribution combo = menus.get(commandId);
221                                 if (REUSE && combo == null) {
222                                         combo = (ComboContribution)mgr.find(commandId);
223                                         if (combo != null) {
224                                                 menus.put(commandId, combo);
225                                                 items.add(combo);
226                                                 a.getCommand().addCommandListener(this);
227                                                 CommandStateRegistry.getInstance().addListener(commandId, this);
228                                         }
229                                 }
230                                 if (combo == null) {
231                                         combo = new ComboContribution();
232                                         combo.setId(commandId);
233                                         menus.put(commandId, combo);
234                                         items.add(combo);
235                                         mgr.add(combo);
236                                         a.getCommand().addCommandListener(this);
237                                         CommandStateRegistry.getInstance().addListener(commandId, this);
238                                 }
239                                 actions.add(commandId,a);
240                                 combo.addAction(a);
241                                 return;
242                         }
243                 } else if (type.equals("push")) {
244                         a = new CommandPushAction(wrapper,name,image);
245                 } else {
246                         if (DEBUG) System.out.println(ext + " is not valid.");
247                         Logger.defaultLogError(ext + " is not valid.");
248                         return;
249                 }
250                 IContributionItem item = null;
251                 if (REUSE) {
252                         String id = commandId;
253                         if (ext.value != null)
254                                 id += "."+ext.value;
255                         item = mgr.find(id);
256                         if (item == null) {
257                                 item =  new ActionContributionItem(a);
258                                 ((ActionContributionItem)item).setId(id);
259                         } else {
260                                 if (DEBUG) System.out.println("Reusing " + ext);
261                                 a = (CommandAction)((ActionContributionItem)item).getAction();
262                         }
263                 } else {
264                         item =  new ActionContributionItem(a);
265                 }
266                 a.getCommand().addCommandListener(this);
267                 actions.add(commandId,a);
268                 items.add(item);
269                 mgr.add(item);
270                 CommandStateRegistry.getInstance().addListener(commandId, this);
271         }
272         
273         private ImageDescriptor getImage(ToolbarCommandExtension ext) {
274                 ImageDescriptor image = null;
275                 if (ext.image != null) {
276                         String plugin = null;
277                         String file = null;
278                         if (ext.image.startsWith(PLATFORM)) {
279                                 String s = ext.image.substring(PLATFORM.length());
280                                 int i = s.indexOf("/");
281                                 plugin = s.substring(0,i);
282                                 file = s.substring(i+1);
283                         } else {
284                                 plugin = ext.contributorId;
285                                 file = ext.image;
286                         }
287                         image = Activator.imageDescriptorFromPlugin(plugin, file);
288                 }
289                 return image;
290         }
291         
292
293         
294         @Override
295         public void commandChanged(CommandEvent commandEvent) {
296                 if (commandEvent.isHandledChanged()||commandEvent.isEnabledChanged()) {
297                         Command command = commandEvent.getCommand();
298                         String commandId = command.getId();
299                         for (CommandAction a : actions.getValues(commandId)) {
300                                 a.setEnabled(command.isHandled() && command.isEnabled());
301                         }
302                 }
303         }
304         
305         @Override
306         public void setActiveEditor(IEditorPart targetEditor) {
307                 if (targetEditor == activePart)
308                         return;
309                 setContext(targetEditor);
310         }
311         
312         @Override
313         public void stateChanged(IWorkbenchPart part, String commandId, String state) {
314                 // TODO : update only given command
315                 if (settingState)
316                         return;
317                 if (part instanceof IEditorPart)
318                         setContext((IEditorPart)part);
319         }
320         
321         private void setContext2(IEditorPart part) {
322                 if (REUSE)
323                         return;
324                 if (this.activePart == part)
325                         return;
326                 setContext(null);
327         }
328         
329         private void setContext(IEditorPart part) {
330                 this.activePart = part;
331         if (activePart != null && !parts.contains(activePart)) {
332                 activePart.getSite().getPage().addPartListener(this);
333         }
334         if (part != null) {
335                 for (String commandId : actions.getKeys()) {
336                                 for (CommandAction a : actions.getValues(commandId)) {
337                                         a.setEnabled(true);
338                                 }
339                                 ComboContribution menu = menus.get(commandId);
340                                 if (menu != null) {
341                                         menu.setEnabled(true);
342                                 }
343                         }
344             updateActionBars(part);
345         } else {
346                         for (String commandId : actions.getKeys()) {
347                                 for (CommandAction a : actions.getValues(commandId)) {
348                                         a.setEnabled(false);
349                                 }
350                                 ComboContribution menu = menus.get(commandId);
351                                 if (menu != null) {
352                                         menu.setEnabled(false);
353                                 }
354                                 
355                         }
356         }
357     }
358
359     private void updateActionBars(IEditorPart part) {
360         restoreActionStates();
361         part.getEditorSite().getActionBars().updateActionBars();
362     }
363         
364         @Override
365         public void dispose() {
366                 if (DEBUG) System.out.println("ToolBarContributor.dispose()");
367                 setActiveEditor(null);
368                 if (mgr != null) {
369                         if (!REUSE) {
370                                 for (IContributionItem item : items) {
371                                         mgr.remove(item);
372                                         item.dispose();
373                                 }
374                         }
375                         items.clear();
376                         
377                         for (String commandId : actions.getKeys()) {
378                                 for (CommandAction a : actions.getValues(commandId)) {
379                                         a.getCommand().removeCommandListener(this);
380                                 }
381                                 
382                         }
383                         actions.clear();
384                         
385                         // without this the contributed toolbar widgets would continue reserve the space even when they are destroyed.
386                         coolBarManager.update(true);
387                         mgr.update(true);
388                 }
389                 CommandStateRegistry.getInstance().removeListener(this);
390                 super.dispose();
391                 activePart = null;
392                 if (partListener != null) {
393                         PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().addPartListener(partListener);
394                         partListener = null;
395                 }
396         }
397         
398         boolean settingState = false;
399         private void storeRadioActionState(CommandRadioAction action, boolean checked) {
400                 if (activePart == null)
401                         return;
402                 settingState = true;
403                 stateRegistry.setEditorState(activePart, action.getCommandId(), action.getValue());
404                 settingState = false;
405         }
406         
407         private void storeToggleActionState(CommandAction action, boolean checked) {
408                 if (activePart == null)
409                         return;
410                 settingState = true;
411                 stateRegistry.setEditorState(activePart, action.getCommandId(), checked);
412                 settingState = false;
413         }
414         
415         
416         
417         private void restoreActionStates() {
418                 if (activePart == null)
419                         return;
420                 if (DEBUG)System.out.println("Restore " + activePart);
421                 // toggles
422                 Map<String,Boolean> defaultToggleStates = stateRegistry.getDefaultToggleStates();
423                 for (String commandId : defaultToggleStates.keySet()) {
424                         for (CommandAction a : actions.getValues(commandId)) {
425                                 if (DEBUG)System.out.println(commandId + " def " + defaultToggleStates.get(commandId));
426                                 a.setChecked(defaultToggleStates.get(commandId));
427                         }
428                 }
429                 Map<String,Boolean> editorStates = stateRegistry.getEditorToggleStates(activePart);//toggleStates.get(activePart);
430                 if (editorStates != null) {
431                         for (String commandId : editorStates.keySet()) {
432                                 for (CommandAction a : actions.getValues(commandId)) {
433                                         if (DEBUG)System.out.println(commandId + " " + editorStates.get(commandId));
434                                         a.setChecked(editorStates.get(commandId));
435                                 }
436                         }
437                 }
438                 // radios
439                 Map<String,String> defaultRadioStates = stateRegistry.getDefaultRadioStates();
440                 for (String commandId : defaultRadioStates.keySet()) {
441                         String defaultValue = defaultRadioStates.get(commandId);
442                         for (CommandAction a : actions.getValues(commandId)) {
443                                 CommandRadioAction r = (CommandRadioAction)a;
444                                 if (DEBUG)System.out.println(commandId + " def " + r.getValue().equals(defaultValue) +" " + r.getValue());
445                                 r.setChecked(r.getValue().equals(defaultValue));
446                         }
447                 }
448                 
449                 Map<String,String> editorRadioStates = stateRegistry.getEditorRadioStates(activePart);//radioStates.get(activePart);
450                 if (editorRadioStates != null) {
451                         for (String commandId : editorRadioStates.keySet()) {
452                                 String defaultValue = editorRadioStates.get(commandId);
453                                 for (CommandAction a : actions.getValues(commandId)) {
454                                         CommandRadioAction r = (CommandRadioAction)a;
455                                         if (DEBUG)System.out.println(commandId + " " + r.getValue().equals(defaultValue) +" " + r.getValue());
456                                         r.setChecked(r.getValue().equals(defaultValue));
457                                 }
458                         }
459                 }
460                 
461                 for (ComboContribution c : menus.values()) {
462                         c.updateSelection();
463                 }
464
465         }
466         
467         @Override
468         public void partActivated(IWorkbenchPart part) {
469
470         }
471         
472         @Override
473         public void partBroughtToTop(IWorkbenchPart part) {
474                 
475         }
476         
477         @Override
478         public void partClosed(IWorkbenchPart part) {
479                 parts.remove(part);
480                 stateRegistry.clearStates(part);
481                 part.getSite().getPage().removePartListener(this);
482                 if (parts.size() == 0) {
483                         
484                 }
485                 if (part instanceof IEditorPart)
486                         ((IEditorPart)part).getEditorSite().getActionBars().updateActionBars();
487                 
488         }
489         
490         @Override
491         public void partDeactivated(IWorkbenchPart part) {
492                 
493         }
494         
495         @Override
496         public void partOpened(IWorkbenchPart part) {
497                 
498         }
499         
500         private boolean getToggleState(Command command) {
501                 State toggleState = command.getState(RegistryToggleState.STATE_ID);
502                 return (Boolean)toggleState.getValue();
503         }
504         
505         private interface ICommandWrapper {
506                 
507                 public Command getCommand();
508                 public String getCommandId();
509                 public void run();
510         }
511         
512         private class CommandWrapper implements ICommandWrapper{
513                 private Command command;
514                 
515                 public CommandWrapper(Command command) {
516                         this.command = command;
517                 }
518                 
519                 @Override
520                 public Command getCommand() {
521                         return command;
522                 }
523                 
524                 @Override
525                 public String getCommandId() {
526                         return command.getId();
527                 }
528                 
529                 @Override
530                 public void run() {
531                         try {
532                                 handlerService.executeCommand(command.getId(), null);
533                         } catch (Exception e) {
534                                 e.printStackTrace();
535                         }
536                 }
537                 
538                 @Override
539                 public boolean equals(Object obj) {
540                         if (obj.getClass() != getClass())
541                                 return false;
542                         CommandWrapper other= (CommandWrapper)obj;
543                         return other.getCommandId().equals(getCommandId());
544                 }
545         }
546         
547         private class ParameterizedCommandWrapper implements ICommandWrapper{
548                 private ParameterizedCommand command;
549                 
550                 public ParameterizedCommandWrapper(ParameterizedCommand command) {
551                         this.command = command;
552                 }
553                 
554                 @Override
555                 public Command getCommand() {
556                         return command.getCommand();
557                 }
558                 
559                 @Override
560                 public String getCommandId() {
561                         return command.getId();
562                 }
563                 
564                 @Override
565                 public void run() {
566                         try {
567                                 handlerService.executeCommand(command, null);
568                         } catch (Exception e) {
569                                 e.printStackTrace();
570                         }
571                 }
572                 
573                 @Override
574                 public boolean equals(Object obj) {
575                         if (obj.getClass() != getClass())
576                                 return false;
577                         ParameterizedCommandWrapper other= (ParameterizedCommandWrapper)obj;
578                         return other.command.equals(command);
579                 }
580         }
581         
582         private abstract class CommandAction extends Action {
583                 private ICommandWrapper command;
584                 
585                 public CommandAction(ICommandWrapper command, String name, ImageDescriptor image, int style) {
586                         super(name,style);
587                         this.command = command;
588                         if (image != null)
589                                 setImageDescriptor(image);
590                 }
591                 
592                 @Override
593                 public void run() {
594                         command.run();
595                 }
596                 
597                 public Command getCommand() {
598                         return command.getCommand();
599                 }
600                 
601                 public String getCommandId() {
602                         return command.getCommandId();
603                 }
604                 
605
606                 @Override
607                 public boolean equals(Object obj) {
608                         if (obj.getClass() != getClass())
609                                 return false;
610                         CommandAction other= (CommandAction)obj;
611                         return command.equals(other.command);
612                 }
613
614                 
615                 @Override
616                 public int hashCode() {
617                         return command.getCommandId().hashCode();
618                 }
619         }
620         
621         
622         private class CommandCheckboxAction extends CommandAction {
623                 
624                 public CommandCheckboxAction(ICommandWrapper command, String name, ImageDescriptor image) {
625                         super(command,name,image,Action.AS_CHECK_BOX);
626                         
627                 }
628                 
629                 @Override
630                 public void run() {
631                         boolean checked = isChecked(); 
632                         storeToggleActionState(this, checked);
633                         try {
634                                 if (checked == getToggleState(getCommand()))
635                                         HandlerUtil.toggleCommandState(getCommand());
636                         } catch (ExecutionException e) {
637                                 e.printStackTrace();
638                         }
639                         super.run();
640                 }
641                 
642         }
643         
644         private class CommandRadioAction extends CommandAction {
645
646                 private String value;
647                 
648                 public CommandRadioAction(ICommandWrapper command, String name, String value, ImageDescriptor image) {
649                         super(command,name,image,Action.AS_RADIO_BUTTON);
650                         this.value = value;
651                 }
652                 
653                 @Override
654                 public void run() {
655                         boolean checked = isChecked(); 
656                         storeRadioActionState(this, checked);
657                         try {
658                                 HandlerUtil.updateRadioState(getCommand(), value);
659                         } catch (ExecutionException e) {
660                                 e.printStackTrace();
661                                 return;
662                         }
663                         super.run();
664                 }
665                 
666                 public String getValue() {
667                         return value;
668                 }
669                 
670                 @Override
671                 public boolean equals(Object obj) {
672                         if (obj.getClass() != getClass())
673                                 return false;
674                         CommandRadioAction other= (CommandRadioAction)obj;
675                         if (!other.getCommandId().equals(getCommandId()))
676                                 return false;
677                         if (!other.value.equals(value))
678                                 return false;
679                         return true;
680                 }
681                 
682         }
683
684         private class CommandPushAction extends CommandAction {
685                 
686                 public CommandPushAction(ICommandWrapper command, String name, ImageDescriptor image) {
687                         super(command,name,image,Action.AS_PUSH_BUTTON);
688                 }
689
690         }
691         
692         private class ComboContribution extends WorkbenchWindowControlContribution {
693                 private TableCombo combo;
694                 
695                 private List<Action> actions = new ArrayList<Action>();
696                 
697                 @Override
698                 protected Control createControl(Composite parent) {
699                         Composite container = new Composite(parent, SWT.NONE);
700                         GridLayout glContainer = new GridLayout(1, false);
701                         glContainer.marginTop = 0;
702                         glContainer.marginHeight = 0;
703                         glContainer.marginWidth = 0;
704                         container.setLayout(glContainer);
705                         GridData glReader = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
706                         combo = new TableCombo(container, SWT.BORDER | SWT.READ_ONLY);
707                         combo.setLayoutData(glReader);
708
709                         for (Action a : actions) {
710                                 TableItem item = new TableItem(combo.getTable(), SWT.NONE);
711                                 item.setText(a.getText());
712                                 if (a.getImageDescriptor() != null)
713                                         item.setImage(a.getImageDescriptor().createImage());
714                         }
715                         
716                         combo.addSelectionListener(new SelectionListener() {
717                                 
718                                 @Override
719                                 public void widgetSelected(SelectionEvent e) {
720                                         int index = combo.getSelectionIndex();
721                                         if (index == -1)
722                                                 return;
723                                         actions.get(index).run();
724                                 }
725                                 
726                                 @Override
727                                 public void widgetDefaultSelected(SelectionEvent e) {
728                                         
729                                 }
730                         });
731                         updateSelection();
732                         return container;
733                 }
734                 
735                 public boolean addAction(Action a) {
736                         // old action must be replaced. (otherwise reused ComboContributor would use different instances to ToolBarContributor.) 
737                         actions.remove(a);
738                         actions.add(a);
739                         return true;
740                         
741                 }
742                 
743                 void updateSelection() {
744                         if (combo == null)
745                                 return;
746                         for (int i = 0; i < actions.size(); i++) {
747                                 if (actions.get(i).isChecked()) {
748                                         combo.select(i);
749                                         return;
750                                 }
751                         }
752                 }
753                 
754                 public void setEnabled(boolean enabled) {
755                         if (combo != null)
756                                 combo.setEnabled(enabled);
757                 }
758                 
759                 @Override
760                 public void dispose() {
761                         combo.dispose();
762                         super.dispose();
763                 }
764         }
765         
766 }