]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/BoxSelectionNode.java
Configurable connection crossing styles
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / nodes / BoxSelectionNode.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.scenegraph.g2d.nodes;
13
14 import java.awt.BasicStroke;
15 import java.awt.Color;
16 import java.awt.Graphics2D;
17 import java.awt.Stroke;
18 import java.awt.geom.Point2D;
19 import java.awt.geom.Rectangle2D;
20
21 import org.simantics.scenegraph.g2d.G2DNode;
22 import org.simantics.scenegraph.g2d.events.EventTypes;
23 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;
24 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
25 import org.simantics.scenegraph.utils.GeometryUtils;
26 import org.simantics.scenegraph.utils.NodeUtil;
27
28 /**
29  * @author Tuukka Lehtonen
30  */
31 public class BoxSelectionNode extends G2DNode {
32
33     private static final long serialVersionUID = 8508750881358776559L;
34
35     protected Stroke            stroke           = new BasicStroke(2);
36     protected Color             color            = Color.BLACK;
37     protected boolean           scaleStroke      = false;
38     protected int               mouseButton      = 0;
39
40     protected Point2D           start            = new Point2D.Double(0, 0);
41     protected Point2D           end              = new Point2D.Double(0, 0);
42
43     protected SelectionListener listener         = null;
44
45     public static interface SelectionListener {
46         public void onSelect(Rectangle2D rect, int modifiers);
47     }
48
49     @Override
50     public void init() {
51         super.init();
52         addEventHandler(this);
53     }
54
55     @Override
56     public void cleanup() {
57         removeEventHandler(this);
58         super.cleanup();
59     }
60
61     @SyncField("stroke")
62     public void setStroke(Stroke stroke) {
63         this.stroke = stroke;
64     }
65
66     @SyncField("color")
67     public void setColor(Color color) {
68         this.color = color;
69     }
70
71     @SyncField("scaleStroke")
72     public void setScaleStroke(boolean scaleStroke) {
73         this.scaleStroke = scaleStroke;
74     }
75
76     @SyncField("start")
77     public void setStart(Point2D start) {
78         this.start = start;
79     }
80
81     @SyncField("end")
82     public void setEnd(Point2D end) {
83         this.end = end;
84     }
85
86     @SyncField("mouseButton")
87     public void setMouseButton(int mouseButton) {
88         this.mouseButton = mouseButton;
89     }
90
91     @Override
92     public void render(Graphics2D g2d) {
93         Rectangle2D bounds = getBoundsInLocal();
94         if (bounds == null || bounds.isEmpty())
95             return;
96
97         if (color != null)
98             g2d.setColor(color);
99         if (stroke != null) {
100             if (scaleStroke && stroke instanceof BasicStroke) {
101                 BasicStroke bs = GeometryUtils.scaleStroke(stroke, (float) (1.0 / GeometryUtils.getScale(g2d.getTransform())));
102                 g2d.setStroke(bs);
103             } else {
104                 g2d.setStroke(stroke);
105             }
106         }
107
108         g2d.draw(bounds);
109     }
110
111     public void setSelectionListener(SelectionListener listener) {
112         this.listener = listener;
113     }
114
115     @ServerSide
116     private void onSelect(Rectangle2D selection, int modifiers) {
117         if (listener != null)
118             listener.onSelect(selection, modifiers);
119     }
120
121     @Override
122     public Rectangle2D getBoundsInLocal() {
123         // Empty bounds indicate no rendering.
124         if (start == null || end == null)
125             return new Rectangle2D.Double();
126
127         Rectangle2D rect = new Rectangle2D.Double(Math.min(start.getX(), end.getX()),
128                 Math.min(start.getY(), end.getY()),
129                 Math.max(start.getX(), end.getX())-Math.min(start.getX(), end.getX()),
130                 Math.max(start.getY(), end.getY())-Math.min(start.getY(), end.getY()));
131         return rect;
132     }
133
134     @Override
135     public int getEventMask() {
136         return EventTypes.MouseButtonReleasedMask | EventTypes.MouseDragBeginMask
137                 | EventTypes.MouseMovedMask;
138     }
139
140     @Override
141     protected boolean mouseButtonReleased(MouseButtonReleasedEvent e) {
142         if (e.button == mouseButton) {
143             onSelect(getBoundsInLocal(), e.stateMask);
144             start = null;
145             end = null;
146         }
147         return false;
148     }
149
150     @Override
151     protected boolean mouseMoved(MouseMovedEvent e) {
152         if (end != null) {
153             NodeUtil.worldToLocal(this, e.controlPosition, end);
154             repaint();
155         }
156         return false;
157     }
158
159 }