Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
SelectionTool.java
1 
16 package net.squiz.matrix.ui;
17 
18 import javax.swing.*;
19 import java.awt.*;
20 import java.awt.event.*;
21 import javax.swing.tree.*;
22 import javax.swing.table.*;
23 import java.util.*;
24 import javax.swing.plaf.*;
25 import net.squiz.matrix.inspector.*;
26 
30 public class SelectionTool extends MouseAdapter implements MouseMotionListener {
31 
32  private Component comp;
33  private SelectionHandler selHandler;
34 
36  private Point initDragPoint = null;
38  private int mouseX;
40  private int mouseY;
42  private Rectangle selectionBounds = new Rectangle(0, 0, 0, 0);
44  private java.util.List currSelection = new ArrayList();
45 
46  /* TRUE if we are dragging the selection tool */
47  private boolean dragging = false;
48  /* a list of nodes to be removed from the selection */
49  private java.util.List removeSelections = new ArrayList();
50  /* a list of nodes to be added to the selection */
51  private java.util.List addSelections = new ArrayList();
52 
53  public SelectionTool(JTree comp) {
54  this.comp = comp;
55  selHandler = new TreeSelection(comp);
56  }
57 
58  public SelectionTool(JTable comp) {
59  this.comp = comp;
60  selHandler = new TableSelection(comp);
61  }
62 
63  public SelectionTool(SelectionHandler handler, Component comp) {
64  selHandler = handler;
65  this.comp = comp;
66  }
67 
68  public Point getInitialDragPoint() {
69  return initDragPoint;
70  }
71 
76  public boolean isDragging() {
77  return dragging;
78  }
79 
84  public void mouseMoved(MouseEvent evt) {}
85 
90  public void mouseReleased(MouseEvent evt) {
91  dragging = false;
92  initDragPoint = null;
93  currSelection.clear();
94  removeSelections.clear();
95  addSelections.clear();
96  comp.repaint();
97  }
98 
103  public void mouseDragged(MouseEvent evt) {
104  mouseX = evt.getX();
105  mouseY = evt.getY();
106 
107  if (initDragPoint == null) {
108  if (!selHandler.canSelect(evt.getPoint()))
109  return;
110 
111  initDragPoint = evt.getPoint();
112  dragging = true;
113  // remove any nodes that are currently selected
114  selHandler.clearSelection();
115  }
116  selHandler.updateSelection(evt.getPoint());
117  comp.repaint();
118  }
119 
126  public void paintSelectionTool(Graphics2D g2d) {
127 
128  if (initDragPoint == null)
129  return;
130 
131  int x = 0, y = 0, width = 0, height = 0;
132 
133  // this is the best way to visualise this:
134  // the slashes point up to the way the rectangle should be drawn
135  // where the x and y co-ordinates are the first slashes origin
136  // in each quadrant
137 
138  /* width --> | width --> |
139  ----------------------------- -
140  | / | / | ^
141  | / | / | | height
142  | / x,y | / x,y |
143  |---------------------------| * initDragPoint.y
144  | / | / |
145  | / | / | ^
146  | / x,y | / x,y | | height
147  |---------------------------|
148  * initDragPoint.x
149  */
150 
151  if (initDragPoint.x < mouseX) {
152  x = initDragPoint.x;
153  width = mouseX - initDragPoint.x;
154  } else {
155  x = mouseX;
156  width = initDragPoint.x -mouseX;
157  }
158 
159  if (initDragPoint.y > mouseY) {
160  y = mouseY;
161  height = initDragPoint.y - mouseY;
162  } else {
163  y = initDragPoint.y;
164  height = mouseY - initDragPoint.y;
165  }
166  drawSelectionImage(g2d, x, y, width, height);
167  selectionBounds.setBounds(x, y, width, height);
168  }
169 
178  protected void drawSelectionImage(
179  Graphics2D g2d,
180  int x,
181  int y,
182  int width,
183  int height) {
184  g2d.setColor(UIManager.getColor("SelectionTool.background"));
185  g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
186  g2d.fillRect(x, y, width, height);
187  g2d.setColor(UIManager.getColor("SelectionTool.bordercolor"));
188  g2d.drawRect(x, y, width - 1, height - 1);
189  }
190 
191  class TreeSelection implements SelectionHandler {
192 
193  private JTree tree;
194 
195  public TreeSelection(JTree tree) {
196  this.tree = tree;
197  }
198 
204  private TreePath[] pathsToArray(java.util.List paths) {
205  return (TreePath[]) paths.toArray(new TreePath[paths.size()]);
206  }
207 
208  public boolean canSelect(Point point) {
209  // check to see if the point if within the bounds of a node.
210  // if it is, we don't want to start a selection operation, because
211  // we want to let the operation cascade down to the drag and drop
212  // methods
213  if (tree.getPathForLocation(point.x, point.y) != null)
214  return false;
215  return true;
216  }
217 
218  public void clearSelection() {
219  tree.clearSelection();
220  }
221 
222  public void updateSelection(Point point) {
223  TreePath mousePath = tree.getClosestPathForLocation(
224  initDragPoint.x, initDragPoint.y);
225  TreePath initPath = tree.getClosestPathForLocation(point.x, point.y);
226 
227  // get the rows between the initial drag point and the current mouse
228  // point a check each of the tree path's bounds to see if it
229  // intersects the rectangle drawing tool
230 
231  TreePath[] rows = getPathBetweenRows(
232  tree.getRowForPath(mousePath), tree.getRowForPath(initPath));
233 
234  currSelection.clear();
235 
236  for (int i = 0; i < rows.length; i++) {
237  if (rows[i] == null)
238  continue;
239 
240  if (selectionBounds.intersects(tree.getPathBounds(rows[i]))) {
241  currSelection.add(rows[i]);
242  }
243  }
244  if (currSelection != null && !currSelection.isEmpty())
245  intersectSelection(currSelection);
246  // see the paintComponent method of this class to see how
247  // the selection tool is drawn
248  }
249 
250  private TreePath[] getPathBetweenRows(int index0, int index1) {
251  int newMinIndex, newMaxIndex;
252  TreeUI ui = tree.getUI();
253 
254  newMinIndex = Math.min(index0, index1);
255  newMaxIndex = Math.max(index0, index1);
256 
257  if(tree != null) {
258  TreePath[] selection = new TreePath[newMaxIndex - newMinIndex + 1];
259 
260  for (int counter = newMinIndex; counter <= newMaxIndex; counter++) {
261  selection[counter - newMinIndex] = ui.getPathForRow(tree, counter);
262  }
263 
264  return selection;
265  }
266 
267  return null;
268  }
269 
278  protected void intersectSelection(java.util.List selPaths) {
279  TreePath[] currSelPaths = tree.getSelectionPaths();
280 
281  // if there are currently no paths selected, then just selected
282  // the specified selection paths
283  if (currSelPaths == null) {
284  tree.addSelectionPaths(pathsToArray(selPaths));
285  return;
286  }
287 
288  addSelections.clear();
289  removeSelections.clear();
290  boolean found = false;
291  TreePath[] selPathsArr = pathsToArray(selPaths);
292 
293  for (int i = 0; i < selPathsArr.length; i++) {
294  found = false;
295  for (int j = 0; j < currSelPaths.length; j++) {
296  // check to see if new selection path is allready selection
297  if (selPathsArr[i] == currSelPaths[j]) {
298  found = true;
299  break;
300  }
301  }
302  if (!found)
303  addSelections.add(selPathsArr[i]);
304  }
305  for (int i = 0; i < currSelPaths.length; i++) {
306  found = false;
307  for (int j = 0; j < selPathsArr.length; j++) {
308  // check to see if old selection
309  // is not in the new selection
310  if (currSelPaths[i] == selPathsArr[j]) {
311  found = true;
312  break;
313  }
314  }
315  if (!found)
316  removeSelections.add(currSelPaths[i]);
317  }
318  // add any new selections that are not currently selected
319  if (!addSelections.isEmpty())
320  tree.addSelectionPaths(pathsToArray(addSelections));
321  // remove any new selections that are current selected
322  if (!removeSelections.isEmpty())
323  tree.removeSelectionPaths(pathsToArray(removeSelections));
324  }
325  }
326 
327  class TableSelection implements SelectionHandler {
328 
329  private JTable table;
330 
331  public TableSelection(JTable table) {
332  this.table = table;
333  }
334 
335  public boolean canSelect(Point point) {
336  if ( (table.rowAtPoint(point) == -1 ) || (table.columnAtPoint(point) == -1) )
337  return true;
338  if (table.getValueAt( table.rowAtPoint(point), table.columnAtPoint(point) ) == null)
339  return true;
340 
341  // MM: need to move mouseInsideCellComponent into this
342  // inner class
343  InspectorGadget tempTable = (InspectorGadget) table;
344  if (!tempTable.mouseInsideCellComponent(point))
345  return true;
346  return false;
347  }
348 
349  public void updateSelection(Point point) {
350  int currentRow = table.rowAtPoint(point);
351  int currentColumn = table.columnAtPoint(point);
352  int startRow = table.rowAtPoint(initDragPoint);
353  int startColumn = table.columnAtPoint(initDragPoint);
354 
355  if (startRow == -1)
356  startRow = table.getRowCount() - 1;
357 
358  table.changeSelection(currentRow,currentColumn,false,false);
359  table.changeSelection(startRow,startColumn,false,true);
360  }
361 
362  public void clearSelection() {
363  table.clearSelection();
364  }
365  }
366 }