KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > taskblocks > graph > GraphMouseHandler


1 /*
2  * Copyright (C) Jakub Neubauer, 2007
3  *
4  * This file is part of TaskBlocks
5  *
6  * TaskBlocks is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * TaskBlocks is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */

19
20 package taskblocks.graph;
21
22 import java.awt.Cursor JavaDoc;
23 import java.awt.Point JavaDoc;
24 import java.awt.event.KeyEvent JavaDoc;
25 import java.awt.event.KeyListener JavaDoc;
26 import java.awt.event.MouseEvent JavaDoc;
27 import java.awt.event.MouseListener JavaDoc;
28 import java.awt.event.MouseMotionListener JavaDoc;
29 import java.awt.event.MouseWheelEvent JavaDoc;
30 import java.awt.event.MouseWheelListener JavaDoc;
31 import java.text.DateFormat JavaDoc;
32 import java.text.SimpleDateFormat JavaDoc;
33 import java.util.Date JavaDoc;
34 import java.util.HashSet JavaDoc;
35 import java.util.Set JavaDoc;
36
37 import javax.swing.JOptionPane JavaDoc;
38
39 import taskblocks.Pair;
40 import taskblocks.Utils;
41
42 public class GraphMouseHandler implements MouseListener JavaDoc, MouseMotionListener JavaDoc, MouseWheelListener JavaDoc, KeyListener JavaDoc {
43
44     /**
45      * drag mode
46      * 0 - nothing,
47      * 1 - dragging whole selected tasks,
48      * 2 - dragging task left boundary,
49      * 3 - dragging task right boundary
50      * 4 - dragging new connection
51      * 5 - dragging the whole canvas
52      */

53     int _dragMode;
54     
55     /** Used when dragging. Task on which the mouse was pressed*/
56     Task _pressedTask;
57     
58     /** Last mouse-pressed position */
59     int _pressX;
60     
61     /** Last mouse-pressed position */
62     int _pressY;
63     
64     /** Used when dragging - on this position will be shown the moved task shadow*/
65     long _cursorTime;
66     
67     /** Used when dragging */
68     TaskRow _cursorTaskRow;
69     
70     /** Used when dragging - task to which the new connection is to be created */
71     Task _destTask;
72     
73     /** Used when dragging - last mouse x */
74     private int _dragX;
75     
76     /** Used when dragging - last mouse y */
77     private int _dragY;
78     
79     /** Remembered firstDay when mouse was pressed and drag mode is 5 (dragging whole canvas) */
80     private long _pressFirstDay;
81     
82     /** The day on which the mouse was last pressed */
83     private long _pressDay;
84     
85     /** Graph component for which this handler works */
86     private TaskGraphComponent _graph;
87     
88     /** The set of currently selected tasks */
89     Set JavaDoc<Object JavaDoc> _selection = new HashSet JavaDoc<Object JavaDoc>();
90     
91     GraphMouseHandler(TaskGraphComponent graph) {
92         _graph = graph;
93     }
94     
95     public void mouseClicked(MouseEvent JavaDoc e) {
96         Point JavaDoc p = e.getPoint();
97         Object JavaDoc o = _graph.findObjectOnPo(p.x, p.y);
98         Task t = null;
99         
100         
101         GraphObject go = null;
102         if(o instanceof GraphObject) {
103             go = (GraphObject)o;
104         }
105         if(o instanceof Task) {
106             t = (Task)o;
107         } else if(o instanceof Pair) {
108             Pair pressedObj = (Pair)o;
109             t = (Task)pressedObj.fst;
110             go = (Task)pressedObj.fst;
111         }
112
113         boolean selectionChanged = false;
114         
115         if(e.getButton() == MouseEvent.BUTTON1
116                 && (
117                         (e.getModifiers() & MouseEvent.CTRL_MASK) != 0
118                         || (e.getModifiers() & MouseEvent.META_MASK) != 0
119                         || (e.getModifiers() & MouseEvent.SHIFT_MASK) != 0
120                     )
121         ) {
122             
123             // left mouse but. pressed with ctr or meta or shift => multi-selection
124

125             if(go != null) {
126                 go._selected = !go._selected;
127                 selectionChanged = true;
128                 if(go._selected) {
129                     _selection.add(go);
130                     _dragMode = 1; // moving whole task(s)
131
} else {
132                     _selection.remove(go);
133                 }
134             }
135         } else {
136             
137             if(go == null) {
138                 // outside task -> clear selection
139
if(_selection.size() > 0) {
140                     clearSelection();
141                     selectionChanged = true;
142                 }
143                 
144             } else {
145                 
146                 // if selection contains exactly t, do nothing
147
if(_selection.size() != 1 || !_selection.contains(go)) {
148                     clearSelection();
149                     _selection.add(go);
150                     go._selected = true;
151                     selectionChanged = true;
152                 }
153             }
154         }
155         
156         if(selectionChanged) {
157             _graph.repaint();
158         }
159         
160         
161         if(_graph._grActListener != null) {
162             _graph._grActListener.mouseClicked(t == null ? null : t._userObject, e);
163         }
164     }
165     
166     public void mouseDragged(MouseEvent JavaDoc e) {
167         Point JavaDoc p = e.getPoint();
168         _dragX = p.x;
169         _dragY = p.y;
170         switch(_dragMode) {
171             case 1: // dragging whole pressed task
172
if(_pressedTask != null) {
173                     
174                     // find the destination position.
175
// 1. find row
176
TaskRow myRow = _graph.findNearestRow(p.y);
177                     if(myRow != null) {
178                         // 2. find time
179
int x = p.x - (_pressX - _pressedTask._bounds.x);
180                         _cursorTime = _graph.xToTime(x);
181                         _cursorTaskRow = myRow;
182                         _graph.repaint();
183                     } else {
184                         // nothing found, let the cursor be the last one.
185
}
186                 }
187                 break;
188             case 2: // dragging left task boundary
189
if(_pressedTask != null) {
190                     long newStartDay = _graph.xToTime(p.x);
191                     long oldTaskStart = _pressedTask.getStartTime();
192                     if(oldTaskStart != newStartDay) {
193
194                         long t1 = Math.min(oldTaskStart, newStartDay);
195                         long t2 = Math.max(oldTaskStart, newStartDay);
196                         long workingDaysDiff = Utils.countWorkDuration(t1, t2);
197                         if(workingDaysDiff > 0) {
198                             _pressedTask.setStartTime(newStartDay);
199                             long newDuration = _pressedTask.getDuration();
200                             if(oldTaskStart > newStartDay) {
201                                 newDuration += workingDaysDiff;
202                             } else {
203                                 newDuration -= workingDaysDiff;
204                             }
205                             _pressedTask.setDuration(Math.max(1, newDuration));
206                             _graph.repaint();
207                         }
208                     }
209                 }
210                 break;
211             case 3: // dragging right mouse boundary
212
if(_pressedTask != null) {
213                     long newEndTime = _graph.xToTime(p.x);
214                     long oldEndTime = _pressedTask.getFinishTime();
215                     if(newEndTime != oldEndTime) {
216                         long t1 = Math.min(newEndTime, oldEndTime);
217                         long t2 = Math.max(newEndTime, oldEndTime);
218                         long workingDaysDiff = Utils.countWorkDuration(t1, t2);
219                         if(workingDaysDiff > 0) {
220                             long newDuration = _pressedTask.getDuration();
221                             if(newEndTime > oldEndTime) {
222                                 newDuration += workingDaysDiff;
223                             } else {
224                                 newDuration -= workingDaysDiff;
225                             }
226                             _pressedTask.setDuration(Math.max(1, newDuration));
227                             _graph.repaint();
228                         }
229                     }
230                 }
231                 break;
232             case 4: // new connection
233
if(_pressedTask != null) {
234                     Object JavaDoc o = _graph.findObjectOnPo(p.x, p.y);
235                     if(o instanceof Task) {
236                         _destTask = (Task)o;
237                     } else if(o instanceof Pair) {
238                         _destTask = (Task)((Pair)o).fst;
239                     } else {
240                         _destTask = null;
241                     }
242                 }
243                 _graph.repaint();
244                 break;
245             case 5:
246                 long tmpFirstDay = _graph._firstDay;
247                 _graph._firstDay = _pressFirstDay;
248                 long mouseDay = _graph.xToTime(p.x);
249                 _graph._firstDay = tmpFirstDay;
250                 
251                 long newFirstDay = _pressFirstDay - (mouseDay - _pressDay);
252                 if(newFirstDay != _graph._firstDay) {
253                     _graph._firstDay = newFirstDay;
254                     _graph.repaint();
255                     _graph._builder.setPaintDirty();
256                 }
257                 break;
258         }
259     }
260     
261     public void mouseEntered(MouseEvent JavaDoc arg0) {
262     }
263     
264     public void mouseExited(MouseEvent JavaDoc arg0) {
265         _graph.setCursor(Cursor.getDefaultCursor());
266     }
267     
268     public void mouseMoved(MouseEvent JavaDoc e) {
269         Point JavaDoc p = e.getPoint();
270         _dragX = p.x;
271         _dragY = p.y;
272         
273         Object JavaDoc o = _graph.findObjectOnPo(p.x, p.y);
274         _graph.changeCursor(o);
275         if(o instanceof Task || o instanceof Pair) {
276             Task t;
277             if(o instanceof Task) {
278                 t = (Task)o;
279             } else {
280                 t = (Task)((Pair)o).fst;
281             }
282             String JavaDoc taskName = _graph._model.getTaskName(t._userObject);
283             DateFormat JavaDoc df = new SimpleDateFormat JavaDoc("d.M.");
284             String JavaDoc start = df.format(new Date JavaDoc(t.getStartTime() * Utils.MILLISECONDS_PER_DAY));
285             String JavaDoc end = df.format(new Date JavaDoc(t.getFinishTime() * Utils.MILLISECONDS_PER_DAY));
286             String JavaDoc duration = String.valueOf(t.getDuration());
287             _graph.setToolTipText("<html><p style=\"padding:2 5 2 5;\"><b>" + taskName + "</b><br>Start: " + start + "&nbsp;&nbsp;&nbsp;End: " + end + "<br>Duration: " + duration + " days");
288         } else {
289             _graph.setToolTipText(null);
290         }
291     }
292     
293     public void mousePressed(MouseEvent JavaDoc e) {
294         Point JavaDoc p = e.getPoint();
295         Object JavaDoc o = _graph.findObjectOnPo(p.x, p.y);
296         _graph.requestFocus();
297         
298         _pressX = p.x;
299         _pressY = p.y;
300
301         if(e.getButton() == MouseEvent.BUTTON1 && o instanceof Pair) {
302             // presed on task left/right boundary
303
Pair pressedObj = (Pair)o;
304             Task t = (Task)pressedObj.fst;
305             Integer JavaDoc direction = (Integer JavaDoc)pressedObj.snd;
306             _pressedTask = t;
307             if(TaskGraphComponent.LEFT == direction) {
308                 _dragMode = 2;
309             } else if(TaskGraphComponent.RIGHT == direction) {
310                 _dragMode = 3;
311             }
312             return;
313         }
314         
315         GraphObject go = null;
316         if(o instanceof GraphObject) {
317             go = (GraphObject)o;
318         }
319         
320         if(go instanceof Task) {
321             _pressedTask = (Task)go;
322         } else {
323             _pressedTask = null;
324         }
325         
326         if(e.getButton() != MouseEvent.BUTTON1) {
327             _pressedTask = null;
328         }
329         
330         if(_pressedTask != null && (e.getModifiers() & MouseEvent.SHIFT_MASK) != 0) {
331             
332             // mouse pressed with shift => start defining new connection
333
_dragMode = 4; // draggin new connection
334
} else {
335             
336             if(go == null || e.getButton() == MouseEvent.BUTTON3) {
337                 // outside task/connection or with right button -> drag the canvas
338

339                 if(p.x > _graph._graphLeft) {
340                     _pressFirstDay = _graph._firstDay;
341                     _pressDay = _graph.xToTime(p.x);
342                     _dragMode = 5;
343                 }
344                 return;
345                 
346             } else {
347                 
348                 // if selection contains exactly t, do nothing
349
_graph.repaint();
350                 _dragMode = 1; // moving whole tasks
351
}
352         }
353     }
354     
355     public void mouseReleased(MouseEvent JavaDoc e) {
356         
357         if(_cursorTaskRow != null && _cursorTime >= 0 && _pressedTask != null) {
358             _pressedTask.setStartTime(_cursorTime);
359             if(_cursorTaskRow != _pressedTask.getRow()) {
360                 // change man of the task
361
_graph._builder.changeTaskRow(_pressedTask, _cursorTaskRow);
362             }
363             _graph._builder.recountStartingTimes();
364         }
365         
366         if(_dragMode == 2 || _dragMode == 3) {
367             if(_pressedTask != null) {
368                 _graph._builder.recountStartingTimes();
369                 _graph.repaint();
370             }
371         }
372         
373         // if creating new connection
374
if(_dragMode == 4) {
375             if(_pressedTask != null && _destTask != null && _pressedTask != _destTask) {
376                 try {
377                     _graph._builder.createConnection(_pressedTask, _destTask);
378                 } catch(Exception JavaDoc e1) {
379                     JOptionPane.showMessageDialog(_graph, "<html><b>Can't set dependency</b><br><br>" + e1.getMessage());
380                 }
381                 _graph._builder.recountStartingTimes();
382                 _graph.repaint();
383             }
384         }
385         
386         _graph.changeCursor(e.getPoint());
387         _dragMode = 0;
388         _cursorTaskRow = null;
389         _cursorTime = -1;
390         _destTask = null;
391         _pressedTask = null;
392         _graph.repaint();
393     }
394
395     public void mouseWheelMoved(MouseWheelEvent JavaDoc e) {
396         int rot = e.getWheelRotation();
397         if(rot < 0) {
398             for(int i = 0; i < -rot; i++) {
399                 _graph.scaleUp();
400             }
401         } else if(rot > 0) {
402             for(int i = 0; i < rot; i++) {
403                 _graph.scaleDown();
404             }
405         }
406     }
407     int getLastMouseX() {
408         return _dragX;
409     }
410     int getLastMouseY() {
411         return _dragY;
412     }
413
414     void clearSelection() {
415         for(Object JavaDoc o: _selection) {
416             if(o instanceof GraphObject) {
417                 ((GraphObject)o)._selected = false;
418             }
419         }
420         _selection.clear();
421     }
422
423     public void keyPressed(KeyEvent JavaDoc e) {
424         /*if(e.getKeyCode() == KeyEvent.VK_DELETE || e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
425             deleteSelection();
426         } else */
if(e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) {
427             _graph._verticalScroll.setValue(_graph._verticalScroll.getValue() + _graph._graphHeight/2);
428         } else if(e.getKeyCode() == KeyEvent.VK_PAGE_UP) {
429             _graph._verticalScroll.setValue(_graph._verticalScroll.getValue() - _graph._graphHeight/2);
430         } else if(e.getKeyCode() == KeyEvent.VK_UP) {
431             _graph._verticalScroll.setValue(_graph._verticalScroll.getValue() - 10);
432         } else if(e.getKeyCode() == KeyEvent.VK_DOWN) {
433             _graph._verticalScroll.setValue(_graph._verticalScroll.getValue() + 10);
434         }
435     }
436
437     public void keyReleased(KeyEvent JavaDoc e) {
438     }
439
440     public void keyTyped(KeyEvent JavaDoc e) {
441     }
442
443     void deleteSelection() {
444         boolean changed = false;
445         for(Object JavaDoc o: _selection) {
446             if(o instanceof Connection) {
447                 _graph._builder.removeConnection((Connection)o);
448                 changed = true;
449             }
450         }
451         for(Object JavaDoc o: _selection) {
452             if(o instanceof Task) {
453                 _graph._builder.removeTask((Task)o);
454                 changed = true;
455             }
456         }
457         for(Object JavaDoc o: _selection) {
458             if(o instanceof TaskRow) {
459                 _graph._builder.removeRow((TaskRow)o);
460                 changed = true;
461             }
462         }
463         if(changed) {
464             _graph.repaint();
465         }
466     }
467 }
468
Popular Tags