KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > taskblocks > graph > TaskLayouter


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.FontMetrics JavaDoc;
23 import java.awt.Graphics2D JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.List JavaDoc;
26
27 /**
28  * This class is used to count real positions of tasks on the component
29  *
30  * @author jakub
31  *
32  */

33 class TaskLayouter {
34
35     /**
36      * Recounts tasks and rows bounds
37      */

38     static void recountBounds(int _graphTop, int _rowHeight,
39             TaskGraphRepresentation _builder, TaskGraphComponent _graph, Graphics2D JavaDoc g2) {
40
41         int rowIndex = 0;
42         FontMetrics JavaDoc fm = g2.getFontMetrics();
43         int maxRowWidth = fm.stringWidth("Worker");
44         for (TaskRow row : _builder._rows) {
45             maxRowWidth = Math.max(maxRowWidth, fm.stringWidth(row._name));
46         }
47         _graph._headerWidth = maxRowWidth + 20;
48         _graph.recountBounds();
49
50         // count rows and tasks boundaries
51
int cummulatedRowAdd = _graph._scrollTop;
52         for (TaskRow row : _builder._rows) {
53             int rowTop = (int) (_graphTop + rowIndex * _rowHeight + cummulatedRowAdd);
54
55             // count connections paddings and modify cummulatedRowAdd and rowTop
56
// according to them.
57
int maxUpPadding = 0;
58             int maxDownPadding = 0;
59             List JavaDoc<Connection> processedConnections = new ArrayList JavaDoc<Connection>();
60             for (Task t : row._tasks) {
61                 for (int i = 0; i < t._outgoingConnections.length; i++) {
62                     Connection c = t._outgoingConnections[i];
63                     // recognize, if connection is going up or down
64
boolean goingDown = row._index <= c._toTask.getRow()._index;
65                     int connPadding = 1;
66
67                     // simple hack - if connection is in the same row, padding
68
// should be
69
// greater that 1, so the arrow will look nicer.
70
if (c._fromTask.getRow() == c._toTask.getRow()) {
71                         connPadding = 2;
72                     }
73                     // now check if the connection crosses something in the same
74
// direction.
75
// if yes, increase connPadding until nothings crosses.
76
// Note, that we must check only already processed
77
// connections.
78
boolean run = true;
79                     while (run) {
80                         run = false;
81                         for (Connection c2 : processedConnections) {
82                             boolean c2GoingDown = row._index <= c2._toTask
83                                     .getRow()._index;
84                             if (goingDown == c2GoingDown
85                                     && connPadding == c2._padding
86                                     && crosses(c, c2)) {
87                                 connPadding++;
88                                 run = true;
89                                 break; // breaks for loop and repeates again.
90
}
91                         }
92                     }
93                     c._padding = connPadding;
94                     processedConnections.add(c);
95                     if (goingDown) {
96                         maxDownPadding = Math.max(maxDownPadding, connPadding);
97                     } else {
98                         maxUpPadding = Math.max(maxUpPadding, connPadding);
99                     }
100                 }
101             }
102             rowTop += maxUpPadding * TaskGraphComponent.CONN_PADDING_FACTOR;
103             cummulatedRowAdd += (maxDownPadding + 1) * TaskGraphComponent.CONN_PADDING_FACTOR
104                     + maxUpPadding * TaskGraphComponent.CONN_PADDING_FACTOR;
105             row._topPosition = rowTop;
106             row._topPadding = maxUpPadding;
107             row._bottomPadding = maxDownPadding+1;
108
109             for (Task t : row._tasks) {
110
111                 double left = _graph.timeToX(t.getStartTime());
112                 double width = t.getRealDuration() * _graph._dayWidth;
113                 double top = rowTop + TaskGraphComponent.CONN_PADDING_FACTOR;
114                 double height = _rowHeight
115                         - TaskGraphComponent.CONN_PADDING_FACTOR;
116                 t._bounds.setBounds((int) left+2, (int) top, (int) width-4,
117                         (int) height);
118             }
119             rowIndex++;
120             
121         } // for all rows
122

123         for(Connection c: _builder._connections) {
124             recountConnectionBounds(c, _graph);
125         }
126
127         _builder.clearPaintDirtyFlag();
128         
129     }
130
131     /**
132      * Checks if the given connections crosses each other (without padding)
133      *
134      * @param c1
135      * @param c2
136      * @return
137      */

138     static boolean crosses(Connection c1, Connection c2) {
139         long c1Left = c1._fromTask.getFinishTime();
140         long c1Right = c1._toTask.getStartTime();
141         long c2Left = c2._fromTask.getFinishTime();
142         long c2Right = c2._toTask.getStartTime();
143
144         // c1.left inside c2
145
if (c1Left >= c2Left && c1Left <= c2Right) {
146             return true;
147         }
148         // c1.right inside c2
149
if (c1Right >= c2Left && c1Right <= c2Right) {
150             return true;
151         }
152
153         // c2.left inside c1
154
if (c2Left >= c1Left && c2Left <= c1Right) {
155             return true;
156         }
157         // c2.right inside c1
158
if (c2Right >= c1Left && c2Right <= c1Right) {
159             return true;
160         }
161
162         return false;
163     }
164     
165     static void recountConnectionBounds(Connection c, TaskGraphComponent _graph) {
166         long fromTime = c._fromTask.getFinishTime();
167         long toTime = c._toTask.getStartTime();
168         int x1 = _graph.timeToX(fromTime);
169         int x2 = _graph.timeToX(toTime);
170         int y1, y2;
171         boolean goingDown = c._fromTask.getRow()._index <= c._toTask.getRow()._index;
172         if(goingDown) {
173             y1 = c._fromTask.getRow()._topPosition + TaskGraphComponent.ROW_HEIGHT;
174         } else {
175             y1 = c._fromTask.getRow()._topPosition + TaskGraphComponent.CONN_PADDING_FACTOR;
176         }
177         boolean commingFromUp = c._fromTask.getRow()._index < c._toTask.getRow()._index;
178         if(commingFromUp) {
179             y2 = c._toTask.getRow()._topPosition + TaskGraphComponent.CONN_PADDING_FACTOR;
180         } else {
181             y2 = c._toTask.getRow()._topPosition + TaskGraphComponent.ROW_HEIGHT;
182         }
183
184         
185         int mediumY;
186         if(y2 >= y1) {
187             mediumY = y1 + c._padding*TaskGraphComponent.CONN_PADDING_FACTOR;
188         } else {
189             mediumY = y1 - c._padding*TaskGraphComponent.CONN_PADDING_FACTOR;
190         }
191         c._path.xpoints[0] = x1;
192         c._path.ypoints[0] = y1;
193         c._path.xpoints[1] = x1;
194         c._path.ypoints[1] = mediumY;
195         c._path.xpoints[2] = x2;
196         c._path.ypoints[2] = mediumY;
197         c._path.xpoints[3] = x2;
198         c._path.ypoints[3] = y2;
199         
200     }
201
202 }
203
Popular Tags