blob: b02df01f572d6af745c79b596b1152f1e1f7e355 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.gef.ui.parts;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.rap.swt.SWT;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.internal.ui.palette.editparts.DrawerEditPart;
import org.eclipse.gef.internal.ui.palette.editparts.GroupEditPart;
import org.eclipse.gef.internal.ui.palette.editparts.IPaletteStackEditPart;
import org.eclipse.gef.internal.ui.palette.editparts.PaletteStackEditPart;
import org.eclipse.gef.internal.ui.palette.editparts.PinnablePaletteStackEditPart;
import org.eclipse.gef.internal.ui.palette.editparts.TemplateEditPart;
import org.eclipse.gef.internal.ui.palette.editparts.ToolEntryEditPart;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.gef.palette.PaletteStack;
import org.eclipse.gef.ui.palette.PaletteViewer;
/**
* KeyHandler for the {@link org.eclipse.gef.ui.palette.PaletteViewer Palette}.
* Handles selection traversal of Palette entries and collapse/expand of
* categories.
*/
public class PaletteViewerKeyHandler extends GraphicalViewerKeyHandler {
/**
* Constructs a key handler for the specified palette viewer.
*
* @param viewer
* the palette viewer
*/
public PaletteViewerKeyHandler(PaletteViewer viewer) {
super(viewer);
}
private boolean acceptCollapseDrawer(KeyEvent event) {
boolean result = isViewerMirrored() ? event.keyCode == SWT.ARROW_RIGHT
: event.keyCode == SWT.ARROW_LEFT;
return result && isExpandedDrawer(getFocusEditPart());
}
private boolean acceptExpandDrawer(KeyEvent event) {
boolean result = isViewerMirrored() ? event.keyCode == SWT.ARROW_LEFT
: event.keyCode == SWT.ARROW_RIGHT;
return result && isCollapsedDrawer(getFocusEditPart());
}
private boolean acceptIntoExpandedDrawer(KeyEvent event) {
boolean result = event.keyCode == SWT.ARROW_DOWN;
result = result
|| (isViewerMirrored() ? event.keyCode == SWT.ARROW_LEFT
: event.keyCode == SWT.ARROW_RIGHT);
return result && isExpandedDrawer(getFocusEditPart());
}
private boolean acceptExpandStack(KeyEvent event) {
return event.keyCode == SWT.ARROW_DOWN
&& (event.stateMask & SWT.ALT) > 0
&& isCollapsedStack(getFocusEditPart());
}
private boolean acceptCollapseStack(KeyEvent event) {
return event.keyCode == SWT.ARROW_UP && (event.stateMask & SWT.ALT) > 0
&& isExpandedStack(getFocusEditPart());
}
private boolean acceptSetFocusOnDrawer(KeyEvent event) {
boolean result = isViewerMirrored() ? event.keyCode == SWT.ARROW_RIGHT
: event.keyCode == SWT.ARROW_LEFT;
return (result || event.keyCode == SWT.ARROW_UP)
&& (getFocusEditPart().getParent() instanceof DrawerEditPart || (getFocusEditPart()
.getParent() instanceof IPaletteStackEditPart && getFocusEditPart()
.getParent().getParent() instanceof DrawerEditPart));
}
private boolean acceptNextContainer(KeyEvent event) {
return event.keyCode == SWT.ARROW_DOWN;
}
private void buildNavigationList(EditPart palettePart, EditPart exclusion,
ArrayList navList, EditPart stackPart) {
if (palettePart != exclusion) {
if (isCollapsedDrawer(palettePart)) {
navList.add(palettePart);
return;
} else if (stackPart instanceof PaletteStackEditPart
&& stackPart.getChildren().contains(palettePart)) {
// we only want to add the top level item to the navlist
if (((PaletteStack) stackPart.getModel()).getActiveEntry()
.equals(palettePart.getModel()))
navList.add(palettePart);
} else if (stackPart instanceof PinnablePaletteStackEditPart
&& stackPart.getChildren().contains(palettePart)) {
// we only want to add the top level item to the navlist unless
// the palette stack is expanded
if (((PinnablePaletteStackEditPart) stackPart).isExpanded()
|| ((PaletteStack) stackPart.getModel())
.getActiveEntry()
.equals(palettePart.getModel())) {
navList.add(palettePart);
}
} else if ((palettePart instanceof ToolEntryEditPart
|| palettePart instanceof DrawerEditPart || palettePart instanceof TemplateEditPart)) {
navList.add(palettePart);
}
}
List children = palettePart.getChildren();
for (int k = 0; k < children.size(); k++) {
EditPart ep = (EditPart) children.get(k);
if (ep instanceof IPaletteStackEditPart)
stackPart = ep;
buildNavigationList(ep, exclusion, navList, stackPart);
}
}
private void collapseDrawer() {
DrawerEditPart drawer = (DrawerEditPart) getFocusEditPart();
drawer.setExpanded(false);
}
private void expandDrawer() {
DrawerEditPart drawer = (DrawerEditPart) getFocusEditPart();
drawer.setExpanded(true);
}
/**
* Figures' navigation points are used to determine their direction compared
* to one another, and the distance between them.
*
* @param figure
* the figure whose navigation point is to be returned
* @return the top-left of the given figure
*/
protected Point getNavigationPoint(IFigure figure) {
return figure.getBounds().getTopLeft();
}
/**
* @return a list of {@link org.eclipse.gef.EditPart EditParts} that can be
* traversed to from the current
* {@link GraphicalViewerKeyHandler#getFocusEditPart() focus part}
*/
protected List getNavigationSiblings() {
ArrayList siblingsList = new ArrayList();
EditPart focusPart = getFocusEditPart();
EditPart parent = focusPart.getParent();
if (parent == null) {
siblingsList.add(focusPart);
return siblingsList;
}
if (parent instanceof GroupEditPart
|| parent instanceof IPaletteStackEditPart) {
EditPart grandParent = parent.getParent();
buildNavigationList(grandParent, grandParent, siblingsList,
grandParent);
} else
buildNavigationList(parent, parent, siblingsList, parent);
return siblingsList;
}
/**
* Returns <code>true</code> if the passed Editpart is a collapsed
* {@link org.eclipse.gef.ui.palette.DrawerEditPart Drawer}, false
* otherwise.
*/
boolean isCollapsedDrawer(EditPart part) {
return part instanceof DrawerEditPart
&& !((DrawerEditPart) part).isExpanded();
}
/**
* Returns <code>true</code> if the passed Editpart is an expanded
* {@link org.eclipse.gef.ui.palette.DrawerEditPart Drawer}, false
* otherwise.
*/
boolean isExpandedDrawer(EditPart part) {
return part instanceof DrawerEditPart
&& ((DrawerEditPart) part).isExpanded();
}
/**
* Returns <code>true</code> if the passed focusPart is a collapsed pinnable
* palette stack, false otherwise.
*/
boolean isCollapsedStack(EditPart focusPart) {
EditPart parent = focusPart.getParent();
return parent instanceof PaletteStackEditPart
|| (parent instanceof PinnablePaletteStackEditPart && !((PinnablePaletteStackEditPart) parent)
.isExpanded());
}
/**
* Returns <code>true</code> if the passed focusPart is an expanded pinnable
* palette stack, false otherwise.
*/
boolean isExpandedStack(EditPart focusPart) {
EditPart parent = focusPart.getParent();
return parent instanceof PaletteStackEditPart
|| (parent instanceof PinnablePaletteStackEditPart && ((PinnablePaletteStackEditPart) parent)
.isExpanded());
}
/**
* Extends keyPressed to look for palette navigation keys.
*
* @see org.eclipse.gef.KeyHandler#keyPressed(org.eclipse.swt.events.KeyEvent)
*/
public boolean keyPressed(KeyEvent event) {
if (acceptExpandDrawer(event)) {
expandDrawer();
return true;
}
if (acceptCollapseDrawer(event)) {
collapseDrawer();
return true;
}
if (acceptExpandStack(event)) {
expandStack();
return true;
}
if (acceptCollapseStack(event)) {
collapseStack(event);
return true;
}
if (acceptIntoExpandedDrawer(event)) {
if (navigateIntoExpandedDrawer(event))
return true;
}
if (super.keyPressed(event))
return true;
if (acceptSetFocusOnDrawer(event)) {
if (navigateToDrawer(event))
return true;
}
if (acceptNextContainer(event)) {
if (navigateToNextContainer(event))
return true;
}
return false;
}
private boolean navigateIntoExpandedDrawer(KeyEvent event) {
ArrayList potentials = new ArrayList();
EditPart focusPart = getFocusEditPart();
buildNavigationList(focusPart, focusPart, potentials, focusPart);
if (!potentials.isEmpty()) {
navigateTo((EditPart) potentials.get(0), event);
return true;
}
return false;
}
/**
* @see GraphicalViewerKeyHandler#navigateTo(EditPart, KeyEvent)
*/
protected void navigateTo(EditPart part, KeyEvent event) {
if (part == null)
return;
if (part instanceof IPaletteStackEditPart) {
PaletteEntry activeEntry = ((PaletteStack) part.getModel())
.getActiveEntry();
part = (EditPart) getViewer().getEditPartRegistry()
.get(activeEntry);
}
getViewer().select(part);
getViewer().reveal(part);
}
private boolean navigateToDrawer(KeyEvent event) {
boolean found = false;
EditPart parent = getFocusEditPart().getParent();
while (parent != null && !found) {
if (parent instanceof DrawerEditPart) {
navigateTo(parent, event);
found = true;
}
parent = parent.getParent();
}
return false;
}
private boolean navigateToNextContainer(KeyEvent event) {
EditPart current = getFocusEditPart();
while (current != null) {
if (current instanceof DrawerEditPart
|| current instanceof GroupEditPart) {
List siblings = current.getParent().getChildren();
int index = siblings.indexOf(current);
if (index != -1 && siblings.size() > index + 1) {
EditPart part = (EditPart) siblings.get(index + 1);
if (part instanceof GroupEditPart
&& part.getChildren().size() > 0) {
EditPart child = (EditPart) part.getChildren().get(0);
navigateTo(child, event);
} else
navigateTo(part, event);
return true;
}
return false;
}
current = current.getParent();
}
return false;
}
private void expandStack() {
((IPaletteStackEditPart) getFocusEditPart().getParent()).openMenu();
}
private void collapseStack(KeyEvent event) {
((PinnablePaletteStackEditPart) getFocusEditPart().getParent())
.setExpanded(false);
navigateTo(getFocusEditPart().getParent(), event);
}
}