X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=org.simantics.g3d%2Fsrc%2Forg%2Fsimantics%2Fg3d%2Ftoolbar%2FToolbarContributor.java;fp=org.simantics.g3d%2Fsrc%2Forg%2Fsimantics%2Fg3d%2Ftoolbar%2FToolbarContributor.java;h=9f87b327e70ce3e8ccb41993658316de2fb2f7c6;hb=87b3241ec277ba3d8e414b26186a032c9cdcaeed;hp=0000000000000000000000000000000000000000;hpb=1f0bcd66274375f2278d2e6c486cb28257a5f7b2;p=simantics%2F3d.git 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 index 00000000..9f87b327 --- /dev/null +++ b/org.simantics.g3d/src/org/simantics/g3d/toolbar/ToolbarContributor.java @@ -0,0 +1,482 @@ +package org.simantics.g3d.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.State; +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.ErrorLogger; +import org.simantics.g3d.Activator; +import org.simantics.g3d.toolbar.ToolBarCommandRegistry.ToolbarCommandExtension; +import org.simantics.utils.datastructures.MapList; + + +/** + * EditorBarContributor, which tracks toggle states separately for each command. + * + * @see org.simantics.g3d.toolbarCommand Extension Point + * + * @author Marko Luukkainen + * + * + * + * TODO : test radio buttons. + * TODO : configuring the position of buttons. + * + */ +public abstract class ToolbarContributor extends EditorActionBarContributor implements ICommandListener, IPartListener { + + private static final String PLATFORM = "platform:/plugin/"; + + private IEditorPart activePart; + private Set parts = new HashSet(); + IToolBarManager mgr; + + + ICommandService service; + IHandlerService handlerService; + List items = new ArrayList(); + MapList actions = new MapList(); + + CommandStateRegistry stateRegistry; + + private Map menus = new HashMap(); + + public ToolbarContributor() { + service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class); + stateRegistry = CommandStateRegistry.getInstance(); + } + + public abstract String getToolbarId(); + + public void contributeToCoolBar(ICoolBarManager coolBarManager) { + IContributionItem 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) { + String commandId = ext.commandId; + Command command = service.getCommand(commandId); + + 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(command,name,image); + + stateRegistry.storeDefaultState(commandId); + } else if (radioState != null && ext.value != null) { + stateRegistry.storeDefaultState(commandId); + if (type.equals("radio")) { + a = new CommandRadioAction(command,name,ext.value,image); + } else if (type.equals("combo")) { + a = new CommandRadioAction(command,name,ext.value,image); + ComboContribution combo = menus.get(commandId); + if (combo == null) { + combo = new ComboContribution(); + menus.put(commandId, combo); + items.add(combo); + mgr.add(combo); + a.getCommand().addCommandListener(this); + } + actions.add(commandId,a); + combo.addAction(a); + return; + } + } else if (type.equals("push")) { + a = new CommandPushAction(command,name,image); + } else { + ErrorLogger.defaultLogError(ext + " is not valid."); + return; + } + a.getCommand().addCommandListener(this); + IContributionItem item = new ActionContributionItem(a); + actions.add(commandId,a); + items.add(item); + mgr.add(item); + } + + 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); + } + + private void setContext(IEditorPart part) { + this.activePart = part; + if (!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); + } + } + updateActionBars(part); + } else { + for (String commandId : actions.getKeys()) { + for (CommandAction a : actions.getValues(commandId)) { + a.setEnabled(false); + } + } + } + } + + private void updateActionBars(IEditorPart part) { + restoreActionStates(); + part.getEditorSite().getActionBars().updateActionBars(); + } + + @Override + public void dispose() { + if (mgr != null) { + for (IContributionItem item : items) { + mgr.remove(item); + item.dispose(); + } + mgr.markDirty(); + mgr.update(true); + if (activePart != null) { + activePart.getEditorSite().getActionBars().updateActionBars(); + } + + for (String commandId : actions.getKeys()) { + for (CommandAction a : actions.getValues(commandId)) { + a.getCommand().removeCommandListener(this); + } + } + actions.clear(); + } + + super.dispose(); + activePart = null; + } + + + private void storeRadioActionState(CommandRadioAction action, boolean checked) { + if (activePart == null) + return; + stateRegistry.setEditorState(activePart, action.getCommandId(), action.getValue()); + } + + private void storeToggleActionState(CommandAction action, boolean checked) { + if (activePart == null) + return; + stateRegistry.setEditorState(activePart, action.getCommandId(), checked); + } + + private void restoreActionStates() { + if (activePart == null) + return; + // toggles + Map defaultToggleStates = stateRegistry.getDefaultToggleStates(); + for (String commandId : defaultToggleStates.keySet()) { + for (CommandAction a : actions.getValues(commandId)) { + a.setChecked(defaultToggleStates.get(commandId)); + } + } + Map editorStates = stateRegistry.getEditorToggleStates(activePart);//toggleStates.get(activePart); + if (editorStates != null) { + for (String commandId : editorStates.keySet()) { + for (CommandAction a : actions.getValues(commandId)) { + a.setChecked(editorStates.get(commandId)); + } + } + } + // radios + Map defaultRadioStates = stateRegistry.getDefaultRadioStates(); + for (String commandId : defaultRadioStates.keySet()) { + String defaultValue = defaultRadioStates.get(commandId); + for (CommandAction a : actions.getValues(commandId)) { + CommandRadioAction r = (CommandRadioAction)a; + r.setChecked(r.getValue().equals(defaultValue)); + } + } + + Map 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; + 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); + } + + @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 abstract class CommandAction extends Action { + private Command command; + + public CommandAction(Command command, String name, ImageDescriptor image, int style) { + super(name,style); + this.command = command; + if (image != null) + setImageDescriptor(image); + } + + @Override + public void run() { + try { + handlerService.executeCommand(command.getId(), null); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public Command getCommand() { + return command; + } + + public String getCommandId() { + return command.getId(); + } + } + + private class CommandCheckboxAction extends CommandAction { + + public CommandCheckboxAction(Command 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(Command 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; + } + + } + + private class CommandPushAction extends CommandAction { + + public CommandPushAction(Command command, String name, ImageDescriptor image) { + super(command,name,image,Action.AS_PUSH_BUTTON); + } + + } + + private class ComboContribution extends WorkbenchWindowControlContribution { + private TableCombo combo; + + private List actions = new ArrayList(); + + @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 void addAction(Action a) { + actions.add(a); + } + + void updateSelection() { + if (combo == null) + return; + for (int i = 0; i < actions.size(); i++) { + if (actions.get(i).isChecked()) { + combo.select(i); + return; + } + } + } + } + +}