package org.simantics.ui.toolbar; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.State; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.handlers.RadioState; import org.eclipse.ui.handlers.RegistryToggleState; import org.simantics.utils.datastructures.MapList; /** * Registry for storing command states separately for each IEditorPart * * TODO : cleaning editor states and listeners is now implemented through ToolBarContributor. Is this OK? * * @author Marko Luukkainen * */ public class CommandStateRegistry { private static CommandStateRegistry instance; public static CommandStateRegistry getInstance() { if (instance == null) instance = new CommandStateRegistry(); return instance; } private Map> toggleStates = new HashMap>(); private Map defaultToggleStates = new HashMap(); private Map defaultRadioStates = new HashMap(); private Map> radioStates = new HashMap>(); private ICommandService service; private IHandlerService handlerService; private CommandStateRegistry() { service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class); } /** * Stores default state for a command. * * Note: uses current state as default. * * @param commandId */ public void storeDefaultState(String commandId) { Command command = service.getCommand(commandId); State toggleState = command.getState(RegistryToggleState.STATE_ID); State radioState = command.getState(RadioState.STATE_ID); if (toggleState != null) { if (!defaultToggleStates.containsKey(commandId)) defaultToggleStates.put(commandId, getToggleState(command)); } else if (radioState != null) { String value = (String) radioState.getValue(); if (!defaultRadioStates.containsKey(commandId)) defaultRadioStates.put(commandId, value); } else { throw new IllegalArgumentException("Command " + commandId + " does not have a state"); } } /** * Stores toggle state of a command. * @param part * @param commandId * @param checked */ public void setEditorState(IWorkbenchPart part, String commandId, boolean checked) { Map editorStates = toggleStates.get(part); if (editorStates == null) { editorStates = new HashMap(); toggleStates.put(part, editorStates); } editorStates.put(commandId, checked); fireStateChange(part, commandId, Boolean.toString(checked)); } /** * Stores radio state of a command. * @param part * @param commandId * @param value */ public void setEditorState(IWorkbenchPart part, String commandId, String value) { Map editorStates = radioStates.get(part); if (editorStates == null) { editorStates = new HashMap(); radioStates.put(part, editorStates); } editorStates.put(commandId, value); fireStateChange(part, commandId, value); } public Map getDefaultToggleStates() { return defaultToggleStates; } public Map getDefaultRadioStates() { return defaultRadioStates; } public Map getEditorToggleStates(IWorkbenchPart part) { return toggleStates.get(part); } public Map getEditorRadioStates(IWorkbenchPart part) { return radioStates.get(part); } public Boolean getToggleState(IWorkbenchPart part, String commandId) { if (part == null) return defaultToggleStates.get(commandId); Map editorStates = toggleStates.get(part); if (editorStates == null) { return defaultToggleStates.get(commandId); } return editorStates.get(commandId); } public String getRadioState(IWorkbenchPart part, String commandId) { if (part == null) return defaultRadioStates.get(commandId); Map editorStates = radioStates.get(part); if (editorStates == null) { return defaultRadioStates.get(commandId); } return editorStates.get(commandId); } public void clearStates(IWorkbenchPart part) { toggleStates.remove(part); radioStates.remove(part); listenerWithPart.remove(part); } private boolean getToggleState(Command command) { State toggleState = command.getState(RegistryToggleState.STATE_ID); return (Boolean)toggleState.getValue(); } private List listeners = new ArrayList(); private MapList listenerWithCommandId = new MapList(); private MapList listenerWithPart = new MapList(); /** * Attaches a listener that receives all state changes of all commands and all workbench parts. * @param listener */ public void addListener(CommandStateListener listener) { if (!listeners.contains(listener)) listeners.add(listener); } /** * Attaches a listener to receive state changes of specific workbench part. * @param part * @param listener */ public void addListener(IWorkbenchPart part, CommandStateListener listener) { if (!listenerWithPart.contains(part,listener)) listenerWithPart.add(part,listener); } /** * Attaches a listener to receive state changes of specific command. * @param part * @param listener */ public void addListener(String commandId, CommandStateListener listener) { if (!listenerWithCommandId.contains(commandId,listener)) listenerWithCommandId.add(commandId, listener); } /** * Removes the listener from the registry. * @param listener */ public void removeListener(CommandStateListener listener) { listeners.remove(listener); Set commandIds = new HashSet(); commandIds.addAll(listenerWithCommandId.getKeys()); for (String commandId : commandIds) { listenerWithCommandId.remove(commandId, listener); } commandIds.clear(); Set parts = new HashSet(); parts.addAll(listenerWithPart.getKeys()); for (IWorkbenchPart part : parts) { listenerWithPart.remove(part, listener); } parts.clear(); } private List fireList = new ArrayList(); private void fireStateChange(IWorkbenchPart part, String commandId, String state) { fireList.clear(); fireList.addAll(listeners); List list = listenerWithCommandId.getValues(commandId); if (list != null) { fireList.addAll(list); } list = listenerWithPart.getValues(part); if (list != null) { fireList.addAll(list); } for (CommandStateListener l : fireList) { l.stateChanged(part, commandId, state); } } }