| /******************************************************************************* |
| * 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); |
| } |
| |
| } |