/******************************************************************************* * Copyright (c) 2000, 2010, 2012 IBM Corporation, Gerhardt Informatics Kft. 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 * Gerhardt Informatics Kft. - GEFGWT port *******************************************************************************/ package org.eclipse.gef.ui.parts; import java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Point; 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; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; /** * 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); } }