Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 214038 Details for
Bug 186470
[Tool] Targeting Tool selects parts at random during drag selection
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
improved performance of marquee drag
MarqueeSelectionTool.java (text/plain), 30.50 KB, created by
Arieh Bibliowicz
on 2012-04-16 07:12:59 EDT
(
hide
)
Description:
improved performance of marquee drag
Filename:
MIME Type:
Creator:
Arieh Bibliowicz
Created:
2012-04-16 07:12:59 EDT
Size:
30.50 KB
patch
obsolete
>package org.eclipse.gef.tools; > >/******************************************************************************* > * 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 > *******************************************************************************/ > >import java.util.ArrayList; >import java.util.Collection; >import java.util.HashSet; >import java.util.Iterator; >import java.util.LinkedHashSet; >import java.util.List; >import java.util.Set; > >import org.eclipse.swt.SWT; >import org.eclipse.swt.events.KeyEvent; >import org.eclipse.swt.widgets.Display; > >import org.eclipse.jface.viewers.StructuredSelection; > >import org.eclipse.draw2d.ColorConstants; >import org.eclipse.draw2d.Connection; >import org.eclipse.draw2d.Figure; >import org.eclipse.draw2d.FigureUtilities; >import org.eclipse.draw2d.Graphics; >import org.eclipse.draw2d.IFigure; >import org.eclipse.draw2d.geometry.Rectangle; > >import org.eclipse.gef.ConnectionEditPart; >import org.eclipse.gef.EditPart; >import org.eclipse.gef.EditPartViewer; >import org.eclipse.gef.GraphicalEditPart; >import org.eclipse.gef.GraphicalViewer; >import org.eclipse.gef.KeyHandler; >import org.eclipse.gef.Request; >import org.eclipse.gef.RequestConstants; >import org.eclipse.gef.SharedCursors; >import org.eclipse.gef.util.EditPartUtilities; > >/** > * A Tool which selects multiple {@link EditPart}s inside a rectangular area of > * a Graphical Viewer. Selection behavior can be configured by selecting (via > * {@link #setMarqueeBehavior(int)}) one of six supported marquee behaviors, > * which are: > * > * <ul> > * <li>{@link #BEHAVIOR_NODES_CONTAINED}</li> > * <li>{@link #BEHAVIOR_NODES_TOUCHED}</li> > * <li>{@link #BEHAVIOR_CONNECTIONS_CONTAINED}</li> > * <li>{@link #BEHAVIOR_CONNECTIONS_TOUCHED}</li> > * <li>{@link #BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS}</li> > * <li>{@link #BEHAVIOR_NODES_TOUCHED_AND_RELATED_CONNECTIONS}</li> > * </ul> > * > * By default, only edit parts whose figure's are on the primary layer that are > * fully enclosed in the marquee selection rectangle will be considered ( > * {@link #BEHAVIOR_NODES_CONTAINED}). > * > * Besides different marquee behaviors, the tool supports different modes, which > * the user can influence by pressing modifier keys at the beginning of the drag > * operation. I.e. if the SHIFT key is pressed at the beginning of the drag, the > * enclosed items will be appended to the current viewer selection. If the MOD1 > * key is pressed at the beginning of the drag, the enclosed items will have > * their selection state inverted. > * > * @author ebordeau > * @author dlee > * @author rhudson > * @author delee > * @author msorens > * @author pshah > * @author anyssen > */ >public class MarqueeSelectionTool extends AbstractTool { > > class MarqueeRectangleFigure extends Figure { > > private static final int DELAY = 110; // animation delay in millisecond > private int offset = 0; > private boolean schedulePaint = true; > > /** > * @see org.eclipse.draw2d.Figure#paintFigure(org.eclipse.draw2d.Graphics) > */ > protected void paintFigure(Graphics graphics) { > Rectangle bounds = getBounds().getCopy(); > graphics.translate(getLocation()); > > graphics.setXORMode(true); > graphics.setForegroundColor(ColorConstants.white); > graphics.setBackgroundColor(ColorConstants.black); > graphics.setLineStyle(Graphics.LINE_DOT); > > int[] points = new int[6]; > > points[0] = 0 + offset; > points[1] = 0; > points[2] = bounds.width - 1; > points[3] = 0; > points[4] = bounds.width - 1; > points[5] = bounds.height - 1; > > graphics.drawPolyline(points); > > points[0] = 0; > points[1] = 0 + offset; > points[2] = 0; > points[3] = bounds.height - 1; > points[4] = bounds.width - 1; > points[5] = bounds.height - 1; > > graphics.drawPolyline(points); > > graphics.translate(getLocation().getNegated()); > > if (schedulePaint) { > Display.getCurrent().timerExec(DELAY, new Runnable() { > public void run() { > offset++; > if (offset > 5) > offset = 0; > > schedulePaint = true; > repaint(); > } > }); > } > > schedulePaint = false; > } > } > > /** > * This behavior selects connections that intersect the marquee rectangle. > * > * @since 3.7 > */ > public static final int BEHAVIOR_CONNECTIONS_CONTAINED = new Integer(6) > .intValue(); > > /** > * This behavior selects connections that intersect the marquee rectangle. > * > * @since 3.1 > */ > public static final int BEHAVIOR_CONNECTIONS_TOUCHED = new Integer(2) > .intValue(); > > /** > * This behavior selects nodes completely encompassed by the marquee > * rectangle. This is the default behavior for this tool. > * > * @since 3.1 > */ > public static final int BEHAVIOR_NODES_CONTAINED = new Integer(1) > .intValue(); > > /** > * This behavior selects nodes completely encompassed by the marquee > * rectangle, and all connections between those nodes. > * > * @since 3.7 > */ > public static final int BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS = new Integer( > 3).intValue(); > > /** > * This behavior selects nodes that intersect the marquee rectangle. > * > * @since 3.7 > */ > public static final int BEHAVIOR_NODES_TOUCHED = new Integer(4).intValue(); > > /** > * This behavior selects nodes that intersect the marquee rectangle. > * > * @since 3.7 > */ > public static final int BEHAVIOR_NODES_TOUCHED_AND_RELATED_CONNECTIONS = new Integer( > 5).intValue(); > > /** > * This behavior selects nodes completely encompassed by the marquee > * rectangle, and all connections between those nodes. > * > * @since 3.1 > * @deprecated use {@link #BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS} > * instead. > */ > public static final int BEHAVIOR_NODES_AND_CONNECTIONS = BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS; > > static final int DEFAULT_MODE = 0; > static final int TOGGLE_MODE = 1; > static final int APPEND_MODE = 2; > > private static final Request MARQUEE_REQUEST = new Request( > RequestConstants.REQ_SELECTION); > > /** > * The property to be used in > * {@link AbstractTool#setProperties(java.util.Map)} for > * {@link #setMarqueeBehavior(int)}. > */ > public static final Object PROPERTY_MARQUEE_BEHAVIOR = "marqueeBehavior"; //$NON-NLS-1$ > > /** > * Constant defining the default marquee selection behavior. > * > * @since 3.7 > */ > public static final int DEFAULT_MARQUEE_BEHAVIOR = BEHAVIOR_NODES_CONTAINED; > > private Set allChildren = new HashSet(); > private int marqueeBehavior = DEFAULT_MARQUEE_BEHAVIOR; > private Figure marqueeRectangleFigure; > private int mode; > > private Collection selectedEditParts; > > private Request targetRequest; > > /** > * Creates a new MarqueeSelectionTool of default type > * {@link #BEHAVIOR_NODES_CONTAINED}. > */ > public MarqueeSelectionTool() { > setDefaultCursor(SharedCursors.CROSS); > setUnloadWhenFinished(false); > } > > /** > * @see org.eclipse.gef.tools.AbstractTool#applyProperty(java.lang.Object, > * java.lang.Object) > */ > protected void applyProperty(Object key, Object value) { > if (PROPERTY_MARQUEE_BEHAVIOR.equals(key)) { > if (value instanceof Integer) > setMarqueeBehavior(((Integer) value).intValue()); > return; > } > super.applyProperty(key, value); > } > > /** > * Called from {@link #performMarqueeSelect()} to determine those > * {@link EditPart}s that are affected by the current marquee selection. In > * default and append mode, the edit parts returned here will become > * selected in the current viewer's new selection (which is calculated and > * set in {@link #performMarqueeSelect()}), while in toggle mode their > * selection state will be inverted. > * > * Calculation is delegated to > * {@link #calculatePrimaryMarqueeSelectedEditParts()} and > * {@link #calculateSecondaryMarqueeSelectedEditParts(Collection)} to > * compute the set of marquee selected edit parts in a two step-process, > * where all directly affected edit parts are determined first, and those > * indirectly affected (related connections in case of > * {@link #BEHAVIOR_NODES_TOUCHED_AND_RELATED_CONNECTIONS}, or > * {@link #BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS}) afterwards. > * > * Clients may overwrite to customize the calculation of marquee selected > * edit parts. > * > * @return A collection containing all edit parts that should be regarded as > * being included in the current marquee selection, i.e. which > * should get selected in default or append mode, and whose > * selection state should get inverted in toggle mode. > * @since 3.7 > */ > protected Collection calculateMarqueeSelectedEditParts() { > Collection marqueeSelectedEditParts = new HashSet(); > marqueeSelectedEditParts > .addAll(calculatePrimaryMarqueeSelectedEditParts()); > marqueeSelectedEditParts > .addAll(calculateSecondaryMarqueeSelectedEditParts(marqueeSelectedEditParts)); > return marqueeSelectedEditParts; > } > > /** > * Filter all edit parts using the current marquee rectangle. Filter is done > * iteratively. If an edit part is completely inside the marquee, it is > * added to the returned collection with all of its children (all levels). > * If it intersects the marquee, it is added and all of its children are > * then filtered in the next iteration. > * > * @return all edit parts that are inside or intersect the current marquee > * rectangle. > */ > private Collection filterEditPartsByMarqueeRectangle() { > List filteredEditParts = new ArrayList(); > List newEditPartsToProcess = new ArrayList(); > > List editPartsToProcess = getCurrentViewer().getRootEditPart() > .getChildren(); > Rectangle marqueeRectangle = getCurrentMarqueeSelectionRectangle(); > > while (editPartsToProcess.size() > 0) { > for (Iterator it = editPartsToProcess.iterator(); it.hasNext();) { > GraphicalEditPart currentEditPart = (GraphicalEditPart) it > .next(); > Rectangle currentEditPartbounds = currentEditPart.getFigure() > .getBounds().getCopy(); > currentEditPart.getFigure().translateToAbsolute( > currentEditPartbounds); > > if (marqueeRectangle.contains(currentEditPartbounds)) { > filteredEditParts.add(currentEditPart); > filteredEditParts.addAll(EditPartUtilities > .getAllChildren(currentEditPart)); > } else if (marqueeRectangle.intersects(currentEditPartbounds)) { > filteredEditParts.add(currentEditPart); > newEditPartsToProcess.addAll(currentEditPart.getChildren()); > } > } > editPartsToProcess = new ArrayList(newEditPartsToProcess); > newEditPartsToProcess.clear(); > } > return filteredEditParts; > } > > /** > * Responsible of calculating those edit parts that should be regarded as > * directly affected by the current marquee selection. By default, the > * method calculates which edit parts are potential candidates based on the > * current marquee behavior and delegates to > * {@link #isMarqueeSelectable(GraphicalEditPart)} and > * {@link #isPrimaryMarqueeSelectedEditPart(GraphicalEditPart)} to decide > * whether the candidate is to be included in the marquee selection. > * > * @return A {@link Collection} containing all {@link EditPart}s that should > * be regarded as being directly affected by the current marquee > * selection. > * @since 3.7 > */ > boolean toggle = true; > int count = 0; > double averageOld = 0; > double averageNew = 0; > > private Collection calculatePrimaryMarqueeSelectedEditParts() { > double start = System.currentTimeMillis(); > Collection editPartsToProcess = new HashSet(); > if (marqueeBehavior != BEHAVIOR_CONNECTIONS_CONTAINED > && marqueeBehavior != BEHAVIOR_CONNECTIONS_TOUCHED) { > if (toggle) { > editPartsToProcess.addAll(EditPartUtilities > .getAllChildren((GraphicalEditPart) getCurrentViewer() > .getRootEditPart())); > } else { > editPartsToProcess.addAll(filterEditPartsByMarqueeRectangle()); > } > } > > if (marqueeBehavior != BEHAVIOR_NODES_CONTAINED > && marqueeBehavior != BEHAVIOR_NODES_TOUCHED) { > // process connections > editPartsToProcess > .addAll(EditPartUtilities > .getAllNestedConnectionEditParts((GraphicalEditPart) getCurrentViewer() > .getRootEditPart())); > } > System.out.println((toggle ? "Old " : "New ") + "editPartsToProcess: " > + editPartsToProcess.size()); > > // process all edit parts and determine which are affected by the > // current marquee selection > Collection marqueeSelectedEditParts = new ArrayList(); > for (Iterator iterator = editPartsToProcess.iterator(); iterator > .hasNext();) { > GraphicalEditPart editPart = (GraphicalEditPart) iterator.next(); > if (isMarqueeSelectable(editPart) > && isPrimaryMarqueeSelectedEditPart(editPart)) { > marqueeSelectedEditParts.add(editPart); > } > } > > double end = System.currentTimeMillis(); > System.out.println((toggle ? "Old " : "New ") + "time: " > + (end - start)); > if (toggle) > averageOld = (averageOld * count + (end - start)) / (count + 1); > else > averageNew = (averageNew * count + (end - start)) / (count + 1); > count++; > System.out.println("Averages: old = " + averageOld + "; new = " > + averageNew); > > toggle = !toggle; > return marqueeSelectedEditParts; > } > > /** > * Responsible of calculating those edit parts that should be regarded as > * being indirectly affected by the marquee selection. By default, the > * method calculates which edit parts are potential candidates based on the > * current marquee behavior and delegates to > * {@link #isMarqueeSelectable(GraphicalEditPart)} and > * {@link #isSecondaryMarqueeSelectedEditPart(Collection, EditPart)} to > * decide whether the candidate is to be included in the marquee selection. > * > * @param directlyMarqueeSelectedEditParts > * A collection containing those {@link EditPart}s that were > * already identified as being directly affected by the marquee > * selection > * @return A {@link Collection} containing all {@link EditPart}s that are > * indirectly affected by the current marquee selection > * @since 3.7 > */ > private Collection calculateSecondaryMarqueeSelectedEditParts( > Collection directlyMarqueeSelectedEditParts) { > > Collection editPartsToProcess = new HashSet(); > for (Iterator iterator = directlyMarqueeSelectedEditParts.iterator(); iterator > .hasNext();) { > GraphicalEditPart marqueeSelectedEditPart = (GraphicalEditPart) iterator > .next(); > editPartsToProcess.addAll(marqueeSelectedEditPart > .getSourceConnections()); > editPartsToProcess.addAll(marqueeSelectedEditPart > .getTargetConnections()); > } > > // process all edit parts and decide, whether they are indirectly > // affected by marquee selection > Collection secondaryMarqueeSelectedEditParts = new HashSet(); > for (Iterator iterator = editPartsToProcess.iterator(); iterator > .hasNext();) { > GraphicalEditPart editPart = (GraphicalEditPart) iterator.next(); > if (isSecondaryMarqueeSelectedEditPart( > directlyMarqueeSelectedEditParts, editPart)) { > secondaryMarqueeSelectedEditParts.add(editPart); > } > } > return secondaryMarqueeSelectedEditParts; > } > > private Request createTargetRequest() { > return MARQUEE_REQUEST; > } > > /** > * Erases feedback if necessary and puts the tool into the terminal state. > */ > public void deactivate() { > if (isInState(STATE_DRAG_IN_PROGRESS)) { > eraseMarqueeFeedback(); > eraseTargetFeedback(); > } > super.deactivate(); > allChildren.clear(); > setState(STATE_TERMINAL); > } > > private void eraseMarqueeFeedback() { > if (marqueeRectangleFigure != null) { > removeFeedback(marqueeRectangleFigure); > marqueeRectangleFigure = null; > } > } > > private void eraseTargetFeedback() { > if (selectedEditParts == null) > return; > Iterator oldEditParts = selectedEditParts.iterator(); > while (oldEditParts.hasNext()) { > EditPart editPart = (EditPart) oldEditParts.next(); > editPart.eraseTargetFeedback(getTargetRequest()); > } > } > > /** > * @see org.eclipse.gef.tools.AbstractTool#getCommandName() > */ > protected String getCommandName() { > return REQ_SELECTION; > } > > /** > * Returns the current marquee selection rectangle. > * > * @return A {@link Rectangle} representing the current marquee selection. > * @since 3.7 > */ > protected Rectangle getCurrentMarqueeSelectionRectangle() { > return new Rectangle(getStartLocation(), getLocation()); > } > > /** > * Returns the current selection mode, i.e. default, append, or toggle > * > * @return on of {@link #DEFAULT_MODE}, {@link #APPEND_MODE}, or > * {@link #TOGGLE_MODE} > * @since 3.7 > */ > protected int getCurrentSelectionMode() { > return mode; > } > > /** > * @see org.eclipse.gef.tools.AbstractTool#getDebugName() > */ > protected String getDebugName() { > return "Marquee Tool: " + marqueeBehavior;//$NON-NLS-1$ > } > > private IFigure getMarqueeFeedbackFigure() { > if (marqueeRectangleFigure == null) { > marqueeRectangleFigure = new MarqueeRectangleFigure(); > addFeedback(marqueeRectangleFigure); > } > return marqueeRectangleFigure; > } > > private Request getTargetRequest() { > if (targetRequest == null) > targetRequest = createTargetRequest(); > return targetRequest; > } > > /** > * @see org.eclipse.gef.tools.AbstractTool#handleButtonDown(int) > */ > protected boolean handleButtonDown(int button) { > if (!isCurrentViewerGraphical()) > return true; > if (button != 1) { > setState(STATE_INVALID); > handleInvalidInput(); > } > if (stateTransition(STATE_INITIAL, STATE_DRAG_IN_PROGRESS)) { > if (getCurrentInput().isModKeyDown(SWT.MOD1)) > setSelectionMode(TOGGLE_MODE); > else if (getCurrentInput().isShiftKeyDown()) > setSelectionMode(APPEND_MODE); > else > setSelectionMode(DEFAULT_MODE); > } > return true; > } > > /** > * @see org.eclipse.gef.tools.AbstractTool#handleButtonUp(int) > */ > protected boolean handleButtonUp(int button) { > if (stateTransition(STATE_DRAG_IN_PROGRESS, STATE_TERMINAL)) { > eraseTargetFeedback(); > eraseMarqueeFeedback(); > performMarqueeSelect(); > } > handleFinished(); > return true; > } > > /** > * @see org.eclipse.gef.tools.AbstractTool#handleDragInProgress() > */ > protected boolean handleDragInProgress() { > if (isInState(STATE_DRAG | STATE_DRAG_IN_PROGRESS)) { > showMarqueeFeedback(); > eraseTargetFeedback(); > selectedEditParts = calculateMarqueeSelectedEditParts(); > showTargetFeedback(); > } > return true; > } > > /** > * @see org.eclipse.gef.tools.AbstractTool#handleFocusLost() > */ > protected boolean handleFocusLost() { > if (isInState(STATE_DRAG | STATE_DRAG_IN_PROGRESS)) { > handleFinished(); > return true; > } > return false; > } > > /** > * This method is called when mouse or keyboard input is invalid and erases > * the feedback. > * > * @return <code>true</code> > */ > protected boolean handleInvalidInput() { > eraseTargetFeedback(); > eraseMarqueeFeedback(); > return true; > } > > /** > * Handles high-level processing of a key down event. KeyEvents are > * forwarded to the current viewer's {@link KeyHandler}, via > * {@link KeyHandler#keyPressed(KeyEvent)}. > * > * @see AbstractTool#handleKeyDown(KeyEvent) > */ > protected boolean handleKeyDown(KeyEvent e) { > if (super.handleKeyDown(e)) > return true; > if (getCurrentViewer().getKeyHandler() != null) > return getCurrentViewer().getKeyHandler().keyPressed(e); > return false; > } > > /** > * Decides whether the given edit part may potentially be included in the > * current marquee selection. > * > * @param editPart > * the {@link EditPart} of interest > * @return <code>true</code> if the given edit part may be included into the > * marquee selection, <code>false</code> otherwise > * @since 3.7 > */ > protected boolean isMarqueeSelectable(GraphicalEditPart editPart) { > // IMPORTANT: MarqueeSelectionTool is not a TargetingTool, thus the > // pre-selection does not depend on hit-testing. Therefore, the visible > // state of the edit part's figure has to be taken into consideration as > // well. > return editPart.getTargetEditPart(MARQUEE_REQUEST) == editPart > && editPart.isSelectable() > && FigureUtilities.isNotFullyClipped(editPart.getFigure()); > } > > /** > * Determines which edit parts are directly affected by the current marquee > * selection. Calculation is performed by regarding the current marquee > * selection rectangle ( {@link #getCurrentMarqueeSelectionRectangle()}), > * taking into consideration the current marquee behavior (contained vs. > * touched) that was provided ( {@link #setMarqueeBehavior(int)} ). > * > * @param editPart > * the {@link EditPart} whose state is to be determined > * @return <code>true</code> if the {@link EditPart} should be regarded as > * being included in the current marquee selection, > * <code>false</code> otherwise. > * @since 3.7 > */ > private boolean isPrimaryMarqueeSelectedEditPart(GraphicalEditPart editPart) { > // figure bounds are used to determine if edit part is included in > // selection > IFigure figure = editPart.getFigure(); > Rectangle r = figure.getBounds().getCopy(); > figure.translateToAbsolute(r); > > boolean included = false; > Rectangle marqueeSelectionRectangle = getCurrentMarqueeSelectionRectangle(); > if (editPart instanceof ConnectionEditPart) { > if (marqueeBehavior == BEHAVIOR_CONNECTIONS_TOUCHED > || marqueeBehavior == BEHAVIOR_CONNECTIONS_CONTAINED) { > if (marqueeSelectionRectangle.intersects(r)) { > // children will contain ConnectionEditParts only in case > // behavior is BEHAVIOR_CONNECTIONS_TOUCHED or > // BEHAVIOR_CONNECTIONS_CONTAINED > Rectangle relMarqueeRect = Rectangle.SINGLETON; > figure.translateToRelative(relMarqueeRect > .setBounds(marqueeSelectionRectangle)); > if (marqueeBehavior == BEHAVIOR_CONNECTIONS_TOUCHED) { > included = ((Connection) figure).getPoints() > .intersects(relMarqueeRect); > } else if (marqueeBehavior == BEHAVIOR_CONNECTIONS_CONTAINED) { > included = relMarqueeRect > .contains(((Connection) figure).getPoints() > .getBounds()); > } > } > } > } else { > // otherwise children will only be 'node' edit parts > if (marqueeBehavior == BEHAVIOR_NODES_TOUCHED > || marqueeBehavior == BEHAVIOR_NODES_TOUCHED_AND_RELATED_CONNECTIONS) { > included = marqueeSelectionRectangle.intersects(r); > } else if (marqueeBehavior == BEHAVIOR_NODES_CONTAINED > || marqueeBehavior == BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS) { > included = marqueeSelectionRectangle.contains(r); > } > } > return included; > } > > /** > * Determines which edit parts are indirectly affected by the current > * marquee selection through those edit parts being directly affected. In > * case of {@link #BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS} or > * {@link #BEHAVIOR_NODES_TOUCHED_AND_RELATED_CONNECTIONS} marquee behavior, > * this method will be used to calculate the related connections after all > * respective nodes have been identified as primary selected edit parts. > * > * @param directlyMarqueeSelectedEditParts > * A collection of {@link EditPart}s which are regarded to be > * directly included in the current marquee selection. > * @param editPart > * the {@link EditPart} of concern > * @return <code>true</code> if the {@link EditPart} should be regarded as > * being included in the current marquee selection, > * <code>false</code> otherwise. > * @since 3.7 > */ > private boolean isSecondaryMarqueeSelectedEditPart( > Collection directlyMarqueeSelectedEditParts, EditPart editPart) { > boolean included = false; > if (editPart instanceof ConnectionEditPart > && (marqueeBehavior == BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS || marqueeBehavior == BEHAVIOR_NODES_TOUCHED_AND_RELATED_CONNECTIONS)) { > // connections are included, if related nodes are included > ConnectionEditPart connection = (ConnectionEditPart) editPart; > GraphicalEditPart source = (GraphicalEditPart) connection > .getSource(); > GraphicalEditPart target = (GraphicalEditPart) connection > .getTarget(); > boolean sourceIncludedInMarqueeSelection = directlyMarqueeSelectedEditParts > .contains(source); > boolean targetIncludedInMarqueeSelection = directlyMarqueeSelectedEditParts > .contains(target); > > if (mode == DEFAULT_MODE) { > // in default mode, select connection if source and > // target are included in marqee selection > included = sourceIncludedInMarqueeSelection > && targetIncludedInMarqueeSelection; > } else if (mode == APPEND_MODE) { > // in append mode, the current viewer selection is of interest > // as well, so select connection if not already selected and > // source and target are already selected or will get selected > included = connection.getSelected() == EditPart.SELECTED_NONE > && (getCurrentViewer().getSelectedEditParts().contains( > source) || sourceIncludedInMarqueeSelection) > && (getCurrentViewer().getSelectedEditParts().contains( > target) || targetIncludedInMarqueeSelection); > } else if (mode == TOGGLE_MODE) { > if (connection.getSelected() == EditPart.SELECTED_NONE) { > // connection is currently deselected, include it in the > // marquee selection, i.e. select it, if one of > // source or target will become selected in the new viewer > // selection > included = ((source.getSelected() == EditPart.SELECTED_NONE && sourceIncludedInMarqueeSelection) || (source > .getSelected() != EditPart.SELECTED_NONE && !sourceIncludedInMarqueeSelection)) > && ((target.getSelected() == EditPart.SELECTED_NONE && targetIncludedInMarqueeSelection) || (target > .getSelected() != EditPart.SELECTED_NONE && !targetIncludedInMarqueeSelection)); > } else { > // connection is currently selected, include it in marquee > // selection, i.e. deselect it, if one of source or target > // will become deselected in the new viewer selection > included = (source.getSelected() != EditPart.SELECTED_NONE && sourceIncludedInMarqueeSelection) > || (target.getSelected() != EditPart.SELECTED_NONE && targetIncludedInMarqueeSelection); > } > } > } > return included; > } > > /** > * MarqueeSelectionTool is only interested in GraphicalViewers, not > * TreeViewers. > * > * @see org.eclipse.gef.tools.AbstractTool#isViewerImportant(org.eclipse.gef.EditPartViewer) > */ > protected boolean isViewerImportant(EditPartViewer viewer) { > return isCurrentViewerGraphical(); > } > > private boolean isCurrentViewerGraphical() { > return getCurrentViewer() instanceof GraphicalViewer; > } > > /** > * Calculates and sets a new viewer selection based on the current marquee > * selection. > * > * By default, this method delegates to > * {@link #calculateMarqueeSelectedEditParts()} to obtain the set of edit > * parts, which should be regarded as being affected by the current marquee > * selection. It then calculates a new viewer selection based on the current > * selection state of all affected edit parts and the current selection mode > * of the tool ( {@link #getCurrentSelectionMode()}), as well as the current > * selection of the viewer (in case of APPEND mode), which is then passed to > * the current viewer. > * > * @since 3.7 > */ > protected void performMarqueeSelect() { > // determine which edit parts are affected by the current marquee > // selection > Collection marqueeSelectedEditParts = calculateMarqueeSelectedEditParts(); > > // calculate nodes/connections that are to be selected/deselected, > // dependent on the current mode of the tool > Collection editPartsToSelect = new LinkedHashSet(); > Collection editPartsToDeselect = new HashSet(); > for (Iterator iterator = marqueeSelectedEditParts.iterator(); iterator > .hasNext();) { > EditPart affectedEditPart = (EditPart) iterator.next(); > if (affectedEditPart.getSelected() == EditPart.SELECTED_NONE > || getCurrentSelectionMode() != TOGGLE_MODE) > editPartsToSelect.add(affectedEditPart); > else > editPartsToDeselect.add(affectedEditPart); > } > > // include the current viewer selection, if not in DEFAULT mode. > if (getCurrentSelectionMode() != DEFAULT_MODE) { > editPartsToSelect.addAll(getCurrentViewer().getSelectedEditParts()); > editPartsToSelect.removeAll(editPartsToDeselect); > } > > getCurrentViewer().setSelection( > new StructuredSelection(editPartsToSelect.toArray())); > } > > /** > * Sets the type of parts that this tool will select. This method should > * only be invoked once: when the tool is being initialized. > * > * @param type > * {@link #BEHAVIOR_CONNECTIONS_TOUCHED} or > * {@link #BEHAVIOR_CONNECTIONS_CONTAINED} > * {@link #BEHAVIOR_NODES_TOUCHED} or > * {@link #BEHAVIOR_NODES_CONTAINED} or > * {@link #BEHAVIOR_NODES_TOUCHED_AND_RELATED_CONNECTIONS} or > * {@link #BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS} > * @since 3.1 > */ > public void setMarqueeBehavior(int type) { > if (type != BEHAVIOR_CONNECTIONS_TOUCHED > && type != BEHAVIOR_CONNECTIONS_CONTAINED > && type != BEHAVIOR_NODES_TOUCHED > && type != BEHAVIOR_NODES_TOUCHED_AND_RELATED_CONNECTIONS > && type != BEHAVIOR_NODES_CONTAINED > && type != BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS) > throw new IllegalArgumentException( > "Invalid marquee behaviour specified."); //$NON-NLS-1$ > marqueeBehavior = type; > } > > private void setSelectionMode(int mode) { > this.mode = mode; > } > > /** > * @see org.eclipse.gef.Tool#setViewer(org.eclipse.gef.EditPartViewer) > */ > public void setViewer(EditPartViewer viewer) { > if (viewer == getCurrentViewer()) > return; > super.setViewer(viewer); > if (viewer instanceof GraphicalViewer) > setDefaultCursor(SharedCursors.CROSS); > else > setDefaultCursor(SharedCursors.NO); > } > > private void showMarqueeFeedback() { > Rectangle rect = getCurrentMarqueeSelectionRectangle().getCopy(); > IFigure marqueeFeedbackFigure = getMarqueeFeedbackFigure(); > marqueeFeedbackFigure.translateToRelative(rect); > marqueeFeedbackFigure.setBounds(rect); > marqueeFeedbackFigure.validate(); > } > > private void showTargetFeedback() { > for (Iterator itr = selectedEditParts.iterator(); itr.hasNext();) { > EditPart editPart = (EditPart) itr.next(); > editPart.showTargetFeedback(getTargetRequest()); > } > } > >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 186470
: 214038 |
214039