1 package de.fzi.wim.guibase.graphview.controller;
2
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.HashSet;
6 import java.util.Iterator;
7 import java.awt.Point;
8 import java.awt.Stroke;
9 import java.awt.Rectangle;
10 import java.awt.BasicStroke;
11 import java.awt.Color;
12 import java.awt.Graphics2D;
13 import java.awt.geom.Point2D;
14 import java.awt.event.MouseEvent;
15
16 import de.fzi.wim.guibase.graphview.graph.*;
17 import de.fzi.wim.guibase.graphview.view.*;
18 import de.fzi.wim.guibase.graphview.selection.*;
19
20 /***
21 * A manipulator that provides the selection user interface.
22 */
23 public class SelectionManipulator extends AbstractManipulator {
24 /*** The name of this manipulator. */
25 public static final String NAME="SelectionManipulator";
26 /*** The dashed stroke. */
27 protected static final Stroke DASHED_STROKE=new BasicStroke(1.0f,BasicStroke.CAP_SQUARE,BasicStroke.JOIN_BEVEL,2.0f,new float[] { 15.0f,10.0f },0.0f);
28
29 /*** The node selection model.*/
30 protected NodeSelectionModel m_nodeSelectionModel;
31 /*** The graph position of the fixed point. */
32 protected Point2D m_selectionRectangleFixedGraph;
33 /*** The fixed point of the selection rectangle. */
34 protected Point m_selectionRectangleFixed;
35 /*** The moving point of the selection rectangle. */
36 protected Point m_selectionRectangleMoving;
37
38 /***
39 * Creates an instance of this class.
40 *
41 * @param nodeSelectionModel the model for node selection
42 */
43 public SelectionManipulator(NodeSelectionModel nodeSelectionModel) {
44 m_nodeSelectionModel=nodeSelectionModel;
45 m_nodeSelectionModel.addNodeSelectionListener(new NodeSelectionHandler());
46 m_selectionRectangleFixedGraph=new Point2D.Double();
47 }
48 protected boolean shouldSelectNode(Node node) {
49 return true;
50 }
51 public String getName() {
52 return NAME;
53 }
54 public NodeSelectionModel getNodeSelectionModel() {
55 return m_nodeSelectionModel;
56 }
57 public void paint(Graphics2D g) {
58 if (m_selectionRectangleFixed!=null) {
59 Color oldColor=g.getColor();
60 g.setColor(Color.gray);
61 Stroke oldStroke=g.getStroke();
62 g.setStroke(DASHED_STROKE);
63 int x=Math.min(m_selectionRectangleFixed.x,m_selectionRectangleMoving.x);
64 int y=Math.min(m_selectionRectangleFixed.y,m_selectionRectangleMoving.y);
65 int width=Math.abs(m_selectionRectangleFixed.x-m_selectionRectangleMoving.x);
66 int height=Math.abs(m_selectionRectangleFixed.y-m_selectionRectangleMoving.y);
67 g.drawRect(x,y,width,height);
68 g.setStroke(oldStroke);
69 g.setColor(oldColor);
70 }
71 }
72 public void mousePressed(MouseEvent e) {
73 if (m_graphPane.isEnabled() && (e.getModifiers() & MouseEvent.BUTTON1_MASK)!=0 && isStartSelectionEvent(e)) {
74 Node node=m_graphPane.getNodeAtPoint(e.getPoint());
75 if (node!=null) {
76 Collection rawSelection=Collections.singletonList(node);
77 changeSelection(rawSelection,e);
78 }
79 else {
80 Edge edge=m_graphPane.getNearestEdge(e.getPoint());
81 if (edge==null) {
82 updateLastMouseEventScreenPoint(e);
83 m_selectionRectangleFixed=e.getPoint();
84 m_graphPane.screenToGraphPoint(m_selectionRectangleFixed,m_selectionRectangleFixedGraph);
85 m_selectionRectangleMoving=m_selectionRectangleFixed;
86 e.consume();
87 }
88 }
89 }
90 }
91 public void mouseReleased(MouseEvent e) {
92 if (m_selectionRectangleFixed!=null && (e.getModifiers() & MouseEvent.BUTTON1_MASK)!=0) {
93 m_selectionRectangleMoving=e.getPoint();
94 int x=Math.min(m_selectionRectangleFixed.x,m_selectionRectangleMoving.x);
95 int y=Math.min(m_selectionRectangleFixed.y,m_selectionRectangleMoving.y);
96 int width=Math.abs(m_selectionRectangleFixed.x-m_selectionRectangleMoving.x);
97 int height=Math.abs(m_selectionRectangleFixed.y-m_selectionRectangleMoving.y);
98 Rectangle rectangle=new Rectangle(x,y,width,height);
99 Collection nodesInRectangle=m_graphPane.getNodesInRectangle(rectangle);
100 changeSelection(nodesInRectangle,e);
101 m_selectionRectangleFixed=null;
102 m_selectionRectangleMoving=null;
103 m_lastMouseEventScreenPoint=null;
104 m_graphPane.repaint();
105 e.consume();
106 }
107 }
108 public void mouseDragged(MouseEvent e) {
109 if (m_selectionRectangleFixed!=null) {
110 autoscroll(e);
111 updateLastMouseEventScreenPoint(e);
112 m_selectionRectangleMoving=e.getPoint();
113 m_graphPane.repaint();
114 e.consume();
115 }
116 }
117 public void notifyGraphPaneScrolled() {
118 if (m_selectionRectangleFixed!=null) {
119 m_graphPane.graphToScreenPoint(m_selectionRectangleFixedGraph,m_selectionRectangleFixed);
120 m_selectionRectangleMoving=getLastMouseEventPoint();
121 m_graphPane.repaint();
122 }
123 }
124 protected void changeSelection(Collection rawSelection,MouseEvent e) {
125 Collection newSelection=new HashSet();
126 Iterator iterator=rawSelection.iterator();
127 while (iterator.hasNext()) {
128 Node node=(Node)iterator.next();
129 if (shouldSelectNode(node))
130 newSelection.add(node);
131 }
132 if (!newSelection.isEmpty()) {
133 Collection existingSelection=m_nodeSelectionModel.getSelectedNodes();
134 if (isToggleSelectionEvent(e)) {
135 Collection addElements=new HashSet();
136 Collection removeElements=new HashSet();
137 iterator=newSelection.iterator();
138 while (iterator.hasNext()) {
139 Node node=(Node)iterator.next();
140 if (existingSelection.contains(node))
141 removeElements.add(node);
142 else
143 addElements.add(node);
144 }
145 if (!removeElements.isEmpty())
146 m_nodeSelectionModel.removeNodes(removeElements);
147 if (!addElements.isEmpty())
148 m_nodeSelectionModel.addNodes(addElements);
149 }
150 else {
151 if (!existingSelection.containsAll(newSelection) || existingSelection.size()!=newSelection.size()) {
152 m_nodeSelectionModel.clear();
153 m_nodeSelectionModel.addNodes(newSelection);
154 }
155 }
156 }
157 }
158 protected boolean isStartSelectionEvent(MouseEvent e) {
159 return (e.getModifiers() & MouseEvent.SHIFT_MASK)==0;
160 }
161 protected boolean isToggleSelectionEvent(MouseEvent e) {
162 return (e.getModifiers() & MouseEvent.CTRL_MASK)!=0;
163 }
164
165 /***
166 * The handles of the node selection events.
167 */
168 protected class NodeSelectionHandler implements NodeSelectionListener {
169 public void nodesAddedToSelection(NodeSelectionModel nodeSelectionModel,Collection nodes) {
170 m_graphPane.repaint();
171 }
172 public void nodesRemovedFromSelection(NodeSelectionModel nodeSelectionModel,Collection nodes) {
173 m_graphPane.repaint();
174 }
175 public void selectionCleared(NodeSelectionModel nodeSelectionModel) {
176 m_graphPane.repaint();
177 }
178 }
179 }