KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > hero > client > grapheditor > Touch


1 package hero.client.grapheditor;
2
3 import java.awt.Rectangle JavaDoc;
4 import java.awt.geom.Point2D JavaDoc;
5 import java.util.Hashtable JavaDoc;
6
7 import com.jgraph.graph.CellView;
8 import com.jgraph.graph.Edge;
9 import com.jgraph.graph.GraphConstants;
10
11
12 public class Touch implements Runnable JavaDoc {
13
14     private WFGraph graph;
15     private Hashtable JavaDoc deltas = new Hashtable JavaDoc();
16     private Hashtable JavaDoc positions = new Hashtable JavaDoc();
17     private Thread JavaDoc relaxer;
18     private boolean allowedToRun = false;
19     private boolean repaintNeeded = false;
20     private double damper=1.0; // A low damper value causes the graph to move slowly
21
private double maxMotion=0; // Keep an eye on the fastest moving node to see if the graph is stabilizing
22
private double lastMaxMotion=0;
23     private double motionRatio = 0; // It's sort of a ratio, equal to lastMaxMotion/maxMotion-1
24
private boolean damping = true; // When damping is true, the damper value decreases
25

26     private double rigidity = 1; // Rigidity has the same effect as the damper, except that it's a constant
27
// a low rigidity value causes things to go slowly.
28
// a value that's too high will cause oscillation
29
private double newRigidity = 1;
30
31   // ............
32

33   /** Constructor with a supplied TGPanel <tt>tgp</tt>.
34     */

35     public Touch(WFGraph graph) {
36         this.graph = graph;
37         relaxer = null;
38     }
39
40     void setRigidity(double r) {
41         newRigidity = r; //update rigidity at the end of the relax() thread
42
}
43
44     //relaxEdges is more like tense edges up. All edges pull nodes closer together;
45
private synchronized void relaxEdges() {
46     try{
47         Object JavaDoc[] edges = graph.getEdges(graph.getAll());
48         //System.out.println("edges="+edges.length);
49
for (int i = 0; i < edges.length; i++) {
50         CellView from = graph.getSourceView(edges[i]);
51         CellView to = graph.getTargetView(edges[i]);
52         CellView fromV = graph.getView().getMapping(((Edge) edges[i]).getSource(), false);
53         CellView toV = graph.getView().getMapping(((Edge) edges[i]).getTarget(), false);
54         
55         
56         if (from != null && to != null) {
57             Rectangle JavaDoc bf = fromV.getBounds();// GraphConstants.getBounds(fromV.getAttributes());
58
Rectangle JavaDoc bt = toV.getBounds();//GraphConstants.getBounds(toV.getAttributes());
59
//Point2D.Double bf = getPosition(from);
60
//Point2D.Double bt = getPosition(to);
61
double vx = bt.x - bf.x;
62             double vy = bt.y - bf.y;
63             double len = Math.sqrt(vx * vx + vy * vy);
64             double dx=vx*rigidity; //rigidity makes edges tighter
65
double dy=vy*rigidity;
66             double length = getLength(edges[i])*100;
67             dx /=length;
68             dy /=length;
69             moveView(to, -dx*len, -dy*len);
70             moveView(from, dx*len, dy*len);
71             
72         }
73         }
74     }catch(Exception JavaDoc e){run();}
75     }
76
77     public double getLength(Object JavaDoc edge) {
78       CellView view = graph.getView().getMapping(edge, false);
79       return GPGraphTools.getLength(view);
80     }
81
82     private synchronized void avoidLabels() {
83       Object JavaDoc[] vertices = graph.getVertices(graph.getAll());
84       for (int i = 0; i < vertices.length; i++) {
85     for (int j = i+1; j < vertices.length; j++) {
86       CellView from = graph.getView().getMapping(vertices[i], false);
87       CellView to = graph.getView().getMapping(vertices[j], false);
88       if (from != null && to != null) {
89         Point2D.Double JavaDoc bf = getPosition(from);
90         Point2D.Double JavaDoc bt = getPosition(to);
91
92         double dx=0;
93         double dy=0;
94         double vx = bf.x - bt.x;
95         double vy = bf.y - bt.y;
96         double len = vx * vx + vy * vy; //so it's length squared
97
if (len == 0) {
98         dx = Math.random();
99         dy = Math.random();
100         } else if (len <200*200) {
101         dx = vx / len;
102         dy = vy / len;
103         }
104         int repSum =400; // 200; // n1.repulsion * n2.repulsion/100
105
moveView(from, dx*repSum, dy*repSum);
106         moveView(to, -dx*repSum, -dy*repSum);
107       }
108     }
109       }
110     }
111
112     public void startDamper() {
113         damping = true;
114     }
115
116     public void stopDamper() {
117         damping = false;
118         damper = 1.0; //A value of 1.0 means no damping
119
}
120
121     public void resetDamper() { //reset the damper, but don't keep damping.
122
damping = true;
123         damper = 1.0;
124     }
125
126     public void setDamper(double newValue) {
127       damper = newValue;
128     }
129
130     public void damp() {
131         if (damping) {
132             if(motionRatio<=0.001) { //This is important. Only damp when the graph starts to move faster
133
//When there is noise, you damp roughly half the time. (Which is a lot)
134
//
135
//If things are slowing down, then you can let them do so on their own,
136
//without damping.
137

138                 //If max motion<0.2, damp away
139
//If by the time the damper has ticked down to 0.9, maxMotion is still>1, damp away
140
//We never want the damper to be negative though
141
if ((maxMotion<0.2 || (maxMotion>1 && damper<0.9)) && damper > 0.01) damper -= 0.01;
142                 //If we've slowed down significanly, damp more aggresively (then the line two below)
143
else if (maxMotion<0.4 && damper > 0.003) damper -= 0.003;
144                 //If max motion is pretty high, and we just started damping, then only damp slightly
145
else if(damper>0.0001) damper -=0.0001;
146             }
147         }
148         if(maxMotion<0.001 && damping)
149             damper=0;
150     //System.out.println("damper="+damper);
151
}
152
153
154     private synchronized void moveNodes() {
155     lastMaxMotion = maxMotion;
156     double maxMotionA=0;
157     Object JavaDoc[] vertices = graph.getVertices(graph.getAll());
158     for (int i = 0; i < vertices.length; i++) {
159       CellView view = graph.getView().getMapping(vertices[i], false);
160       if (view != null) {
161         Rectangle JavaDoc bounds = GraphConstants.getBounds(view.getAttributes());
162         Point2D.Double JavaDoc delta = getDelta(view);
163         Point2D.Double JavaDoc position = getPosition(view);
164         //deltas.remove(view);
165
double dx = delta.getX();
166         double dy = delta.getY();
167         dx*=damper;
168         dy*=damper;
169         delta.setLocation(dx/2, dy/2);
170         double distMoved = Math.sqrt(dx*dx+dy*dy);
171         if (GraphConstants.isMoveable(view.getAttributes()) &&
172         !graph.isCellSelected(vertices[i]) && (dx != 0 || dy != 0))
173         {
174           //System.out.println("dx: " + dx + " dy: "+dy);
175
position.x +=Math.max(-5, Math.min(5, dx));
176           position.y +=Math.max(-5, Math.min(5, dy));
177           bounds.x = Math.max(0, (int) position.x-bounds.width/2);
178           bounds.y = Math.max(0, (int) position.y-bounds.height/2);
179           repaintNeeded = true;
180          }
181          maxMotionA=Math.max(distMoved,maxMotionA);
182               
183       }
184         };
185     maxMotion=maxMotionA;
186     if (maxMotion>0) motionRatio = lastMaxMotion/maxMotion-1;
187     else motionRatio = 0;
188     damp();
189     }
190
191     private synchronized void relax() {
192         for (int i=0;i<10;i++) {
193           relaxEdges();
194           avoidLabels();
195           moveNodes();
196         }
197         if(rigidity!=newRigidity)
198       rigidity= newRigidity; //update rigidity
199
if (repaintNeeded) {
200           graph.repaint();
201       repaintNeeded = false;
202     }
203     }
204
205     public void run() {
206         Thread JavaDoc me = Thread.currentThread();
207         while (relaxer == me && allowedToRun) {
208             relax();
209             //System.out.println("D "+damper);
210
try {
211                 Thread.sleep(20);
212             } catch (InterruptedException JavaDoc e) {
213                 break;
214             }
215         }
216     }
217
218     public void start() {
219       relaxer = new Thread JavaDoc(this);
220       allowedToRun = true;
221       relaxer.start();
222     }
223
224     public boolean isRunning() {
225       if (relaxer != null)
226     return relaxer.isAlive();
227       return false;
228     }
229
230     public void stop() {
231       allowedToRun = false;
232       relaxer = null;
233     }
234
235     public Point2D.Double JavaDoc getPosition(CellView view) {
236       Point2D.Double JavaDoc p1 = (Point2D.Double JavaDoc) positions.get(view);
237       
238       Rectangle JavaDoc rect = GraphConstants.getBounds(view.getAttributes());
239       Point2D.Double JavaDoc p2 = new Point2D.Double JavaDoc(rect.x+rect.width/2, rect.y+rect.height/2);
240       
241       if(p1!=null) {
242         if(Math.abs(p1.x-p2.x)>5 || Math.abs(p1.y-p2.y)>5) {
243             //System.out.println("p1.x " +p1.x +" p2.x " +p2.x);
244
p1.setLocation(p2.x,p2.y);
245         }
246         return p1;
247       }
248       else {
249            positions.put(view, p2);
250            return p2;
251       }
252     }
253
254     public Point2D.Double JavaDoc getDelta(CellView view) {
255       Point2D.Double JavaDoc p = (Point2D.Double JavaDoc) deltas.get(view);
256       if (p == null) {
257            p = new Point2D.Double JavaDoc(0,0);
258            deltas.put(view, p);
259       }
260       return p;
261     }
262
263     public void moveView(CellView view, double dx, double dy) {
264       //System.out.println("set Delta for "+view+" to "+dx+", "+dy);
265
Point2D.Double JavaDoc p = getDelta(view);
266       p.setLocation(p.getX()+dx, p.getY()+dy);
267     }
268
269 }
270
Popular Tags