/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.diagram.ui.util; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.Cursors; import org.eclipse.draw2d.FigureUtilities; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.RectangleFigure; import org.eclipse.draw2d.Shape; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPartViewer; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.GraphicalViewer; import org.eclipse.gef.Request; import org.eclipse.gef.RequestConstants; import org.eclipse.gef.tools.AbstractTool; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.graphics.Color; /** * This tool implements the selection of multiple objects in rectangular area. * * @since 8.0 */ public class LassoSelectionTool extends AbstractTool { static final int TOGGLE_MODE = 1; static final int APPEND_MODE = 2; private int mode; private boolean fillValue = false; private int lineStyle = Graphics.LINE_DASHDOT; private Color lineColor = ColorConstants.blue; private int lineWidth = 5; //= 2; private Shape lassoRectangleFigure; private List allChildren = new ArrayList(); private List selectedEditParts; private Request targetRequest; private static final Request LASSO_REQUEST = new Request(RequestConstants.REQ_SELECTION); /** * Creates a new LassoSelectionTool. */ public LassoSelectionTool() { setDefaultCursor(Cursors.CROSS); setLineStyle(lineStyle); } private List calculateNewSelection() { List newSelections = new ArrayList(); List children = getAllChildren(); // Calculate new selections based on which children fall // inside the lasso selection rectangle. Do not select // children who are not visible for (int i = 0; i < children.size(); i++) { EditPart child = (EditPart) children.get(i); IFigure figure = ((GraphicalEditPart) child).getFigure(); Rectangle r = figure.getBounds().getCopy(); figure.translateToAbsolute(r); if( DiagramUiUtilities.isLassoableFigure(figure) && figure.isVisible()) { if (geLassoSelectionRectangle().contains(r.getTopLeft()) && geLassoSelectionRectangle().contains(r.getBottomRight()) ) { if (child.getTargetEditPart(LASSO_REQUEST) == child && DiagramUiUtilities.isLassoableEditPart(child) && !newSelections.contains(child) ) { newSelections.add(child); } } else if (geLassoSelectionRectangle().intersects(r) ) { if (child.getTargetEditPart(LASSO_REQUEST) == child && DiagramUiUtilities.isLassoableEditPart(child) && !newSelections.contains(child) ) { newSelections.add(child); } } } } return newSelections; } private Request createTargetRequest() { return LASSO_REQUEST; } /** * Erases feedback if necessary and puts the tool into the terminal state. */ @Override public void deactivate() { if (isInState(STATE_DRAG_IN_PROGRESS)) { eraseLassoFeedback(); eraseTargetFeedback(); } super.deactivate(); allChildren = new ArrayList(); setState(STATE_TERMINAL); } private void eraseLassoFeedback() { if (lassoRectangleFigure != null) { removeFeedback(lassoRectangleFigure); lassoRectangleFigure = null; } } private void eraseTargetFeedback() { if (selectedEditParts == null) return; ListIterator oldEditParts = selectedEditParts.listIterator(); while (oldEditParts.hasNext()) { EditPart editPart = (EditPart) oldEditParts.next(); editPart.eraseTargetFeedback(getTargetRequest()); } } /** * Returns a list including all of the children * of the edit part passed in. */ private List getAllChildren(EditPart editPart, List allChildren) { List children = editPart.getChildren(); for (int i = 0; i < children.size(); i++) { GraphicalEditPart child = (GraphicalEditPart) children.get(i); allChildren.add(child); getAllChildren(child, allChildren); } return allChildren; } /** * Return a vector including all of the children * of the root editpart */ private List getAllChildren() { if (allChildren.isEmpty()) allChildren = getAllChildren(getCurrentViewer().getRootEditPart(), new ArrayList()); return allChildren; } /** * Returns the name identifier of the command that the tool * is currently looking for. */ @Override protected String getCommandName() { return REQ_SELECTION; } /** * Returns the debug name for this tool. */ @Override protected String getDebugName() { return "Lasso Tool"; //$NON-NLS-1$ } private IFigure getLassoFeedbackFigure() { if (lassoRectangleFigure == null) { lassoRectangleFigure = new RectangleFigure(); FigureUtilities.makeGhostShape(lassoRectangleFigure); lassoRectangleFigure.setFill(fillValue); lassoRectangleFigure.setLineStyle(lineStyle); lassoRectangleFigure.setLineWidth(lineWidth); lassoRectangleFigure.setForegroundColor(lineColor); addFeedback(lassoRectangleFigure); } return lassoRectangleFigure; } private Rectangle geLassoSelectionRectangle() { return new Rectangle(getStartLocation(), getLocation()); } private int getSelectionMode() { return mode; } private Request getTargetRequest() { if (targetRequest == null) targetRequest = createTargetRequest(); return targetRequest; } /** * Sets the selection mode to <code>TOGGLE_MODE</code> or * <code>APPEND_MODE</code> depending on the keyboard input. */ @Override protected boolean handleButtonDown(int button) { if (!isGraphicalViewer()) return true; if (button != 1) { setState(STATE_INVALID); handleInvalidInput(); } if (stateTransition(STATE_INITIAL, STATE_DRAG_IN_PROGRESS)) { // jh Case 4514: Give this a default; otherwise old state may persist setSelectionMode(TOGGLE_MODE); if (getCurrentInput().isControlKeyDown()) setSelectionMode(TOGGLE_MODE); else if (getCurrentInput().isShiftKeyDown()) setSelectionMode(APPEND_MODE); } return true; } /** * Erases feedback and performs the selection. */ @Override protected boolean handleButtonUp(int button) { if (stateTransition(STATE_DRAG_IN_PROGRESS, STATE_TERMINAL)) { eraseTargetFeedback(); eraseLassoFeedback(); performLassoSelect(); } handleFinished(); return true; } /** * Calculates the selection and updates the feedback. */ @Override protected boolean handleDragInProgress() { if (isInState(STATE_DRAG | STATE_DRAG_IN_PROGRESS)) { showLassoFeedback(); eraseTargetFeedback(); selectedEditParts = calculateNewSelection(); showTargetFeedback(); } return true; } /** * This method is called when mouse or keyboard input is * invalid and erases the feedback. */ @Override protected boolean handleInvalidInput() { eraseTargetFeedback(); eraseLassoFeedback(); return true; } private boolean isGraphicalViewer() { return getCurrentViewer() instanceof GraphicalViewer; } private void performLassoSelect() { EditPartViewer viewer = getCurrentViewer(); List newSelections = calculateNewSelection(); // If in multi select mode, add the new selections to the already // selected group; otherwise, clear the selection and select the new group if (getSelectionMode() == APPEND_MODE) { for (int i = 0; i < newSelections.size(); i++) { EditPart editPart = (EditPart) newSelections.get(i); viewer.appendSelection(editPart); } } else { viewer.setSelection(new StructuredSelection(newSelections)); } } /** * Sets the EditPartViewer. Also sets the appropriate default cursor * based on the type of viewer. */ @Override public void setViewer(EditPartViewer viewer) { if (viewer == getCurrentViewer()) return; super.setViewer(viewer); if (viewer instanceof GraphicalViewer) setDefaultCursor(Cursors.CROSS); else setDefaultCursor(Cursors.NO); } private void setSelectionMode(int mode) { this.mode = mode; } private void showLassoFeedback() { Rectangle rect = geLassoSelectionRectangle().getCopy(); getLassoFeedbackFigure().translateToRelative(rect); getLassoFeedbackFigure().setBounds(rect); } private void showTargetFeedback() { for (int i = 0; i < selectedEditParts.size(); i++) { EditPart editPart = (EditPart) selectedEditParts.get(i); editPart.showTargetFeedback(getTargetRequest()); } } public void setLineWidth(int newWidth) { lineWidth = newWidth; } public void setLineStyle(int newStyle) { lineStyle = newStyle; } public void setLineColor(Color newColor ) { lineColor = newColor; } public void setFill(boolean shouldFill) { fillValue = shouldFill; } }