blob: a33cb74a647fd3d3d454c389fe205dcf68a5734d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.commands;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import org.eclipse.jface.action.ContextResolver;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContextResolver;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.commands.HandlerServiceEvent;
import org.eclipse.ui.commands.IHandler;
import org.eclipse.ui.commands.IHandlerService;
import org.eclipse.ui.commands.IHandlerServiceListener;
import org.eclipse.ui.contexts.IContextActivationService;
import org.eclipse.ui.contexts.IContextManager;
import org.eclipse.ui.contexts.IContextManagerEvent;
import org.eclipse.ui.contexts.IContextManagerListener;
import org.eclipse.ui.internal.AcceleratorMenu;
import org.eclipse.ui.internal.IWorkbenchConstants;
import org.eclipse.ui.internal.PartSite;
import org.eclipse.ui.internal.Workbench;
import org.eclipse.ui.internal.WorkbenchWindow;
import org.eclipse.ui.internal.commands.registry.ContextBinding;
import org.eclipse.ui.internal.commands.registry.CoreRegistry;
import org.eclipse.ui.internal.commands.registry.IMutableRegistry;
import org.eclipse.ui.internal.commands.registry.IRegistry;
import org.eclipse.ui.internal.commands.registry.LocalRegistry;
import org.eclipse.ui.internal.commands.registry.PreferenceRegistry;
import org.eclipse.ui.internal.commands.util.KeySupport;
import org.eclipse.ui.internal.commands.util.Sequence;
import org.eclipse.ui.internal.commands.util.Stroke;
public class ContextAndHandlerManager implements IContextResolver {
private final StatusLineContributionItem modeContributionItem = new StatusLineContributionItem("ModeContributionItem"); //$NON-NLS-1$
private final IContextManagerListener contextManagerListener = new IContextManagerListener() {
public void contextManagerChanged(IContextManagerEvent contextManagerEvent) {
update();
}
};
private final IHandlerServiceListener handlerServiceListener = new IHandlerServiceListener() {
public void handlerServiceChanged(HandlerServiceEvent handlerServiceEvent) {
update();
}
};
private final IPartListener partListener = new IPartListener() {
public void partActivated(IWorkbenchPart workbenchPart) {
partEvent();
}
public void partBroughtToTop(IWorkbenchPart workbenchPart) {
}
public void partClosed(IWorkbenchPart workbenchPart) {
partEvent();
}
public void partDeactivated(IWorkbenchPart workbenchPart) {
partEvent();
}
public void partOpened(IWorkbenchPart workbenchPart) {
partEvent();
}
};
private final ShellListener shellListener = new ShellAdapter() {
public void shellActivated(ShellEvent shellEvent) {
shellEvent();
}
public void shellDeactivated(ShellEvent shellEvent) {
shellEvent();
}
};
private final VerifyListener verifyListener = new VerifyListener() {
public void verifyText(VerifyEvent verifyEvent) {
verifyEvent.doit = false;
clear();
}
};
private AcceleratorMenu acceleratorMenu;
private IContextActivationService activeWorkbenchPartContextService;
private IHandlerService activeWorkbenchPartHandlerService;
private WorkbenchWindow workbenchWindow;
private IContextActivationService workbenchWindowContextService;
private IHandlerService workbenchWindowHandlerService;
private Map contextsByCommand;
private IContextManager contextManager;
private boolean start = false;
public ContextAndHandlerManager(WorkbenchWindow workbenchWindow) {
super();
this.workbenchWindow = workbenchWindow;
IWorkbench workbench = workbenchWindow.getWorkbench();
contextManager = ((Workbench) workbench).getContextManager(); // TODO temporary cast
contextManager.addContextManagerListener(contextManagerListener);
workbenchWindowHandlerService = ((WorkbenchWindow) workbenchWindow).getHandlerService();
workbenchWindowHandlerService.addHandlerServiceListener(handlerServiceListener);
workbenchWindow.getStatusLineManager().add(modeContributionItem);
reset();
this.workbenchWindow.addPageListener(new IPageListener() {
public void pageActivated(IWorkbenchPage workbenchPage) {
workbenchPage.addPartListener(partListener);
}
public void pageClosed(IWorkbenchPage workbenchPage) {
workbenchPage.removePartListener(partListener);
}
public void pageOpened(IWorkbenchPage workbenchPage) {
workbenchPage.addPartListener(partListener);
}
});
workbenchWindow.getPartService().addPartListener(partListener);
Shell shell = workbenchWindow.getShell();
if (shell != null)
shell.addShellListener(shellListener);
partEvent();
}
private void partEvent() {
IContextActivationService activeWorkbenchPartContextService = null;
IHandlerService activeWorkbenchPartHandlerService = null;
IWorkbenchPage activeWorkbenchPage = workbenchWindow.getActivePage();
if (activeWorkbenchPage != null) {
IWorkbenchPart activeWorkbenchPart = activeWorkbenchPage.getActivePart();
if (activeWorkbenchPart != null) {
IWorkbenchPartSite activeWorkbenchPartSite = activeWorkbenchPart.getSite();
if (activeWorkbenchPartSite != null) {
activeWorkbenchPartContextService = ((PartSite) activeWorkbenchPartSite).getContextActivationService();
activeWorkbenchPartHandlerService = ((PartSite) activeWorkbenchPartSite).getHandlerService();
}
}
}
if (this.activeWorkbenchPartHandlerService != activeWorkbenchPartHandlerService) {
if (this.activeWorkbenchPartHandlerService != null)
this.activeWorkbenchPartHandlerService.removeHandlerServiceListener(handlerServiceListener);
this.activeWorkbenchPartHandlerService = activeWorkbenchPartHandlerService;
if (this.activeWorkbenchPartHandlerService != null)
this.activeWorkbenchPartHandlerService.addHandlerServiceListener(handlerServiceListener);
start = true;
update();
}
}
private void shellEvent() {
start = true;
update();
}
private void clear() {
Manager.getInstance().getKeyMachine().setMode(Sequence.create());
modeContributionItem.setText(""); //$NON-NLS-1$
update();
}
private void pressed(Stroke stroke, Event event) {
SequenceMachine keyMachine = Manager.getInstance().getKeyMachine();
List strokes = new ArrayList(keyMachine.getMode().getStrokes());
strokes.add(stroke);
Sequence childMode = Sequence.create(strokes);
Map sequenceMapForMode = keyMachine.getSequenceMapForMode();
keyMachine.setMode(childMode);
Map childSequenceMapForMode = keyMachine.getSequenceMapForMode();
if (childSequenceMapForMode.isEmpty()) {
clear();
IHandler handler = getHandler((String) sequenceMapForMode.get(childMode));
if (handler != null && handler.isEnabled())
try {
handler.execute(event);
} catch (Exception e) {
// TODO
}
}
else {
modeContributionItem.setText(KeySupport.formatSequence(childMode, true));
update();
}
}
private IHandler getHandler(String command) {
if (command != null) {
if (activeWorkbenchPartHandlerService != null) {
SortedMap handlerMap = activeWorkbenchPartHandlerService.getHandlerMap();
if (handlerMap != null) {
Object object = handlerMap.get(command);
if (object instanceof IHandler)
return (IHandler) object;
}
}
if (workbenchWindowHandlerService != null) {
SortedMap handlerMap = workbenchWindowHandlerService.getHandlerMap();
if (handlerMap != null) {
Object object = handlerMap.get(command);
if (object instanceof IHandler)
return (IHandler) object;
}
}
}
return null;
}
public void update() {
SortedSet activeContextIds = contextManager.getActiveContextIds();
List contexts = new ArrayList(activeContextIds);
// TODO: these should be sorted somehow
SequenceMachine keyMachine = Manager.getInstance().getKeyMachine();
try {
// TODO: get rid of this
if (contexts.size() == 0)
contexts.add(IWorkbenchConstants.DEFAULT_ACCELERATOR_SCOPE_ID);
keyMachine.setContexts((String[]) contexts.toArray(new String[contexts.size()]));
} catch (IllegalArgumentException eIllegalArgument) {
System.err.println(eIllegalArgument);
}
Sequence mode = keyMachine.getMode();
List strokes = mode.getStrokes();
int size = strokes.size();
Map sequenceMapForMode = keyMachine.getSequenceMapForMode();
SortedSet strokeSetForMode = new TreeSet();
Iterator iterator = sequenceMapForMode.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
Sequence sequence = (Sequence) entry.getKey();
String command = (String) entry.getValue();
if (sequence.isChildOf(mode, false)) {
IHandler handler = getHandler(command);
if (handler != null)
strokeSetForMode.add(sequence.getStrokes().get(size));
}
}
iterator = strokeSetForMode.iterator();
int[] accelerators = new int[strokeSetForMode.size()];
int i = 0;
while (iterator.hasNext())
accelerators[i++] = ((Stroke) iterator.next()).getValue();
if (!start)
return;
if (acceleratorMenu == null || acceleratorMenu.isDisposed()) {
Shell shell = workbenchWindow.getShell();
if (shell == null || shell.isDisposed())
return;
Menu parent = shell.getMenuBar();
if (parent == null || parent.isDisposed() || parent.getItemCount() < 1)
return;
MenuItem parentItem = parent.getItem(parent.getItemCount() - 1);
if (parentItem == null || parentItem.isDisposed())
return;
parent = parentItem.getMenu();
if (parent == null || parent.isDisposed())
return;
if (acceleratorMenu != null)
acceleratorMenu.dispose();
acceleratorMenu = new AcceleratorMenu(parent);
acceleratorMenu.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent selectionEvent) {
Event event = new Event();
event.item = selectionEvent.item;
event.detail = selectionEvent.detail;
event.x = selectionEvent.x;
event.y = selectionEvent.y;
event.width = selectionEvent.width;
event.height = selectionEvent.height;
event.stateMask = selectionEvent.stateMask;
event.doit = selectionEvent.doit;
event.data = selectionEvent.data;
event.display = selectionEvent.display;
event.time = selectionEvent.time;
event.widget = selectionEvent.widget;
pressed(Stroke.create(selectionEvent.detail), event);
//pressed(Stroke.create(selectionEvent.detail));
}
});
}
acceleratorMenu.setAccelerators(accelerators);
if (size == 0)
acceleratorMenu.removeVerifyListener(verifyListener);
else
acceleratorMenu.addVerifyListener(verifyListener);
ContextResolver.getInstance().setContextResolver(this);
MenuManager menuManager = ((WorkbenchWindow) workbenchWindow).getMenuManager();
menuManager.update(IAction.TEXT);
/* TODO make this work like it does for menus
CoolBarManager coolBarManager = ((WorkbenchWindow) workbenchWindow).getCoolBarManager();
if (coolBarManager != null)
coolBarManager.update(true);
*/
}
public boolean inContext(String commandId) {
if (commandId != null) {
Set set = (Set) contextsByCommand.get(commandId);
if (set != null) {
/*
if (activeWorkbenchPartContextService != null) {
List contexts = Arrays.asList(activeWorkbenchPartContextService.getActiveContextIds());
if (contexts != null) {
// TODO: get rid of this
contexts = new ArrayList(contexts);
if (contexts.size() == 0)
contexts.add(IWorkbenchConstants.DEFAULT_ACCELERATOR_SCOPE_ID);
Iterator iterator = contexts.iterator();
while (iterator.hasNext()) {
String context = (String) iterator.next();
if (set.contains(context))
return true;
}
}
}
if (workbenchWindowContextService != null) {
List contexts = Arrays.asList(workbenchWindowContextService.getActiveContextIds());
if (contexts != null) {
// TODO: get rid of this
contexts = new ArrayList(contexts);
if (contexts.size() == 0)
contexts.add(IWorkbenchConstants.DEFAULT_ACCELERATOR_SCOPE_ID);
Iterator iterator = contexts.iterator();
while (iterator.hasNext()) {
String context = (String) iterator.next();
if (set.contains(context))
return true;
}
}
}
*/
return false;
}
}
return true;
}
void reset() {
IRegistry coreRegistry = CoreRegistry.getInstance();
IMutableRegistry localRegistry = LocalRegistry.getInstance();
IMutableRegistry preferenceRegistry = PreferenceRegistry.getInstance();
try {
coreRegistry.load();
} catch (IOException eIO) {
}
try {
localRegistry.load();
} catch (IOException eIO) {
}
try {
preferenceRegistry.load();
} catch (IOException eIO) {
}
List contextBindings = new ArrayList();
contextBindings.addAll(coreRegistry.getContextBindings());
contextBindings.addAll(localRegistry.getContextBindings());
contextBindings.addAll(preferenceRegistry.getContextBindings());
contextsByCommand = new TreeMap();
Iterator iterator = contextBindings.iterator();
while (iterator.hasNext()) {
ContextBinding contextBinding = (ContextBinding) iterator.next();
String command = contextBinding.getCommand();
String context = contextBinding.getContext();
Set set = (Set) contextsByCommand.get(command);
if (set == null) {
set = new TreeSet();
contextsByCommand.put(command, set);
}
set.add(context);
}
}
}