]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/pointertool/BoxSelectionMode.java
Performance and resource consumption optimization for G2D picking
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / diagram / participant / pointertool / BoxSelectionMode.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.diagram.participant.pointertool;
13
14 import java.awt.BasicStroke;
15 import java.awt.Color;
16 import java.awt.geom.Point2D;
17 import java.awt.geom.Rectangle2D;
18 import java.util.HashSet;
19 import java.util.Set;
20
21 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
22 import org.simantics.g2d.canvas.impl.DependencyReflection.Reference;
23 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;
24 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
25 import org.simantics.g2d.diagram.DiagramHints;
26 import org.simantics.g2d.diagram.handler.PickContext;
27 import org.simantics.g2d.diagram.handler.PickRequest;
28 import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;
29 import org.simantics.g2d.diagram.participant.Selection;
30 import org.simantics.g2d.element.IElement;
31 import org.simantics.g2d.participant.KeyUtil;
32 import org.simantics.g2d.participant.RenderingQualityInteractor;
33 import org.simantics.g2d.participant.TransformUtil;
34 import org.simantics.scenegraph.g2d.G2DParentNode;
35 import org.simantics.scenegraph.g2d.events.MouseEvent;
36 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
37 import org.simantics.scenegraph.g2d.events.command.CommandEvent;
38 import org.simantics.scenegraph.g2d.events.command.Commands;
39 import org.simantics.scenegraph.g2d.nodes.BoxSelectionNode;
40 import org.simantics.scenegraph.utils.Quality;
41
42 /**
43  * @author Toni Kalajainen
44  */
45 public class BoxSelectionMode extends AbstractMode {
46
47     @Reference  RenderingQualityInteractor quality;
48     @Dependency TransformUtil util;
49     @Dependency Selection selection;
50     @Dependency PickContext pickContext;
51     @Dependency KeyUtil keyUtil;
52
53     public final static BasicStroke STROKE         = new BasicStroke(1.0f);
54
55     public static final int         PAINT_PRIORITY = 30;
56
57     Point2D                         startingPoint;
58     Point2D                         currentPoint;
59     int                             mouseButton;
60     PickPolicy                      boxSelectMode;
61     BoxSelectionNode                node;
62
63     @SGInit
64     public void init(G2DParentNode parent) {
65         if (quality != null)
66             quality.setStaticQuality(Quality.LOW);
67
68         node = parent.getOrCreateNode("" + hashCode(), BoxSelectionNode.class);
69         node.setZIndex(PAINT_PRIORITY);
70         node.setStart(startingPoint);
71         node.setEnd(currentPoint);
72         node.setStroke(STROKE);
73         node.setScaleStroke(true);
74         node.setColor(getToolColor());
75         node.setMouseButton(mouseButton);
76         node.setSelectionListener(new BoxSelectionNode.SelectionListener() {
77             @Override
78             public void onSelect(Rectangle2D rect, int modifiers) {
79                 // Disposed?
80                 if (isRemoved())
81                     return;
82
83                 boolean toggle = (modifiers & MouseEvent.CTRL_MASK) != 0;
84                 boolean accumulate = (modifiers & MouseEvent.SHIFT_MASK) != 0;
85
86                 Set<IElement> boxSelection = new HashSet<IElement>();
87                 PickRequest request = new PickRequest(rect).context(getContext());
88                 request.pickPolicy = boxSelectMode;
89                 pickContext.pick(diagram, request, boxSelection);
90
91                 int selectionId = mouseId;
92                 if (toggle) {
93                     selection.toggle(selectionId, boxSelection);
94                 } else if (accumulate) {
95                     for (IElement elem : boxSelection)
96                         selection.add(selectionId, elem);
97                 } else {
98                     selection.setSelection(selectionId, boxSelection);
99                 }
100
101                 if (node != null) {
102                     node.remove();
103                     node = null;
104                 }
105
106                 setDirty();
107                 remove();
108             }
109         });
110
111     }
112
113     @SGCleanup
114     public void cleanup() {
115         if (quality != null)
116             quality.setStaticQuality(null);
117         if (node != null) {
118             node.remove();
119             node = null;
120         }
121     }
122
123     public BoxSelectionMode(Point2D startingPoint, Point2D currentPoint, final int mouseId, final int mouseButton, final PickPolicy boxSelectMode) {
124         super(mouseId);
125         this.startingPoint = startingPoint;
126         this.currentPoint = currentPoint;
127         this.mouseButton = mouseButton;
128         this.boxSelectMode = boxSelectMode;
129         //setHint(RenderingQualityInteractor.KEY_QUALITY_INTERACTOR_ENABLED, Boolean.FALSE);
130     }
131
132     public synchronized Color getToolColor() {
133         Color c = getHint(DiagramHints.KEY_SELECTION_FRAME_COLOR);
134         if (c != null)
135             return c;
136         return Color.BLACK;
137     }
138
139     /**
140      * Allows user to cancel box selection operations by invoking the CANCEL
141      * command (pressing ESC).
142      */
143     @EventHandler(priority = 100)
144     public boolean handleCancel(CommandEvent e) {
145         if (e.command.equals( Commands.CANCEL ) ) {
146             setDirty();
147             remove();
148         }
149         return false;
150     }
151
152 }