001: // $Id: GraphPanel.java,v 1.6 2006/02/16 08:22:25 belaban Exp $
002:
003: package org.jgroups.demos.wb;
004:
005: import org.apache.commons.logging.Log;
006: import org.apache.commons.logging.LogFactory;
007: import org.jgroups.Address;
008: import org.jgroups.blocks.GroupRequest;
009: import org.jgroups.blocks.MethodCall;
010: import org.jgroups.util.Util;
011:
012: import java.awt.*;
013: import java.awt.event.MouseEvent;
014: import java.awt.event.MouseListener;
015: import java.awt.event.MouseMotionListener;
016: import java.util.Vector;
017:
018: public class GraphPanel extends Panel implements MouseListener,
019: MouseMotionListener {
020: final Whiteboard wb;
021: final Vector nodes = new Vector();
022: final Vector copy = new Vector();
023: String myname = null;
024: public Object my_addr = null;
025: Node pick;
026: boolean pickfixed;
027: Image offscreen;
028: Dimension offscreensize;
029: Graphics offgraphics;
030: static final Color fixedColor = Color.red;
031: static final Color selectColor = Color.pink;
032: final Color nodeColor = new Color(250, 220, 100);
033: final Font default_font = new Font("Helvetica", Font.PLAIN, 12);
034: Log log = LogFactory.getLog(getClass());
035:
036: private Frame findParent() {
037: Component retval = getParent();
038:
039: while (retval != null) {
040: if (retval instanceof Frame)
041: return (Frame) retval;
042: retval = retval.getParent();
043: }
044: return null;
045: }
046:
047: Node findNodeAtPoint(Point p) {
048: int x = p.x, y = p.y;
049: Node n;
050:
051: synchronized (nodes) {
052: if (nodes.size() < 1)
053: return null;
054: for (int i = nodes.size() - 1; i >= 0; i--) {
055: n = (Node) nodes.elementAt(i);
056: if (x >= n.xloc && x <= (n.xloc + n.width)
057: && y >= n.yloc && y <= (n.yloc + n.height))
058: return n;
059: }
060: }
061: return null;
062: }
063:
064: public GraphPanel(Whiteboard wb) {
065: this .wb = wb;
066: addMouseListener(this );
067: addMouseMotionListener(this );
068: }
069:
070: public void addNode(String lbl, Address addr, int xloc, int yloc) {
071: Node n = new Node();
072: n.x = xloc;
073: n.y = yloc;
074: n.lbl = lbl;
075: n.addr = addr;
076: nodes.addElement(n);
077: repaint();
078: }
079:
080: public void removeNode(Object addr) {
081: Node n;
082: Object a;
083:
084: if (addr == null) {
085: log
086: .error("removeNode(): address of node to be removed is null !");
087: return;
088: }
089:
090: synchronized (nodes) {
091: for (int i = 0; i < nodes.size(); i++) {
092: n = (Node) nodes.elementAt(i);
093: a = n.addr;
094: if (a == null)
095: continue;
096: if (addr.equals(a)) {
097: nodes.removeElement(n);
098: System.out.println("Removed node " + n);
099: break;
100: }
101: }
102: repaint();
103: }
104: }
105:
106: // Removes nodes that are not in the view
107: public void adjustNodes(Vector v) {
108: Node n;
109: boolean removed = false;
110:
111: synchronized (nodes) {
112: for (int i = 0; i < nodes.size(); i++) {
113: n = (Node) nodes.elementAt(i);
114: if (!v.contains(n.addr)) {
115: System.out.println("adjustNodes(): node " + n
116: + " was removed");
117: nodes.removeElement(n);
118: removed = true;
119: }
120: }
121: if (removed)
122: repaint();
123: }
124: }
125:
126: public void paintNode(Graphics g, Node n, FontMetrics fm) {
127: String addr = n.addr != null ? n.addr.toString() : null;
128: int x = (int) n.x;
129: int y = (int) n.y;
130: g.setColor((n == pick) ? selectColor : (n.fixed ? fixedColor
131: : nodeColor));
132: int w = fm.stringWidth(n.lbl) + 10;
133:
134: if (addr != null)
135: w = Math.max(w, fm.stringWidth(addr) + 10);
136:
137: if (addr == null)
138: addr = "<no address>";
139:
140: int h = (fm.getHeight() + 4) * 2;
141: n.width = w;
142: n.height = h;
143: n.xloc = x - w / 2;
144: n.yloc = y - h / 2;
145: g.fillRect(x - w / 2, y - h / 2, w, h);
146: g.setColor(Color.black);
147: g.drawRect(x - w / 2, y - h / 2, w - 1, h - 1);
148: g.drawString(n.lbl, x - (w - 10) / 2, (y - (h - 4) / 2)
149: + fm.getAscent());
150: g.drawString(addr, x - (w - 10) / 2, (y - (h - 4) / 2) + 2
151: * fm.getAscent() + 4);
152: }
153:
154: public synchronized void update(Graphics g) {
155: Dimension d = getSize();
156: if ((offscreen == null) || (d.width != offscreensize.width)
157: || (d.height != offscreensize.height)) {
158: offscreen = createImage(d.width, d.height);
159: offscreensize = d;
160: offgraphics = offscreen.getGraphics();
161: offgraphics.setFont(default_font);
162: }
163:
164: offgraphics.setColor(getBackground());
165: offgraphics.fillRect(0, 0, d.width, d.height);
166:
167: FontMetrics fm = offgraphics.getFontMetrics();
168: for (int i = 0; i < nodes.size(); i++) {
169: paintNode(offgraphics, (Node) nodes.elementAt(i), fm);
170: }
171:
172: g.drawImage(offscreen, 0, 0, null);
173: }
174:
175: public void mouseDragged(MouseEvent e) {
176: Point p = e.getPoint();
177: int mod = e.getModifiers();
178:
179: if (pick == null)
180: return;
181:
182: pick.x = p.x;
183: pick.y = p.y;
184: repaint();
185: }
186:
187: public void mousePressed(MouseEvent e) {
188: Point p = e.getPoint();
189: double bestdist = Double.MAX_VALUE, dist;
190: int mod = e.getModifiers();
191: Node n;
192: String msg;
193:
194: if ((mod & MouseEvent.BUTTON3_MASK) != 0) {
195: System.out.println("\nright button at " + p);
196: n = findNodeAtPoint(p);
197: if (n != null) {
198: System.out.println("Found node at " + p + ": " + n);
199: SendDialog dlg = new SendDialog(findParent(), n,
200: myname, wb.disp);
201: repaint();
202: }
203: e.consume();
204: return;
205: }
206:
207: for (int i = 0; i < nodes.size(); i++) {
208: n = (Node) nodes.elementAt(i);
209: dist = (n.x - p.x) * (n.x - p.x) + (n.y - p.y)
210: * (n.y - p.y);
211: if (dist < bestdist) {
212: pick = n;
213: bestdist = dist;
214: }
215: }
216: pickfixed = pick.fixed;
217: pick.fixed = true;
218: pick.x = p.x;
219: pick.y = p.y;
220: repaint();
221: }
222:
223: public void mouseReleased(MouseEvent e) {
224: Point p = e.getPoint();
225: int mod = e.getModifiers();
226:
227: if (pick == null)
228: return;
229:
230: pick.x = p.x;
231: pick.y = p.y;
232: pick.fixed = pickfixed;
233:
234: try {
235: MethodCall call = new MethodCall("moveNode",
236: new Object[] { pick }, new String[] { Node.class
237: .getName() });
238: wb.disp.callRemoteMethods(null, call, GroupRequest.GET_ALL,
239: 0);
240: } catch (Exception ex) {
241: log.error(ex);
242: }
243:
244: pick = null;
245: }
246:
247: public void mouseEntered(MouseEvent e) {
248: }
249:
250: public void mouseExited(MouseEvent e) {
251: }
252:
253: public void mouseMoved(MouseEvent e) {
254: }
255:
256: public void mouseClicked(MouseEvent e) {
257: }
258:
259: public void start(String name) {
260: myname = name;
261: int xloc = (int) (10 + 250 * Math.random());
262: int yloc = (int) (10 + 250 * Math.random());
263:
264: try {
265: MethodCall call = new MethodCall("addNode",
266: new Object[] { name, my_addr, new Integer(xloc),
267: new Integer(yloc) }, new String[] {
268: String.class.getName(),
269: Address.class.getName(),
270: int.class.getName(), int.class.getName() });
271: wb.disp.callRemoteMethods(null, call, GroupRequest.GET_ALL,
272: 0);
273: } catch (Exception e) {
274: log.error(e);
275: }
276: repaint();
277: }
278:
279: public void stop() {
280: nodes.removeAllElements();
281: }
282:
283: public void saveState() {
284: copy.removeAllElements();
285: synchronized (nodes) {
286: for (int i = 0; i < nodes.size(); i++)
287: copy.addElement(nodes.elementAt(i));
288: }
289: }
290:
291: public byte[] getState() { // return the copy previously saved by saveState()
292: try {
293: return Util.objectToByteBuffer(copy);
294: } catch (Throwable ex) {
295: ex.printStackTrace();
296: return null;
297: }
298: }
299:
300: public void setState(byte[] data) {
301: Vector n;
302: Object new_state;
303:
304: try {
305: new_state = Util.objectFromByteBuffer(data);
306: } catch (Exception ex) {
307: ex.printStackTrace();
308: return;
309: }
310:
311: synchronized (nodes) {
312: nodes.removeAllElements();
313: if (new_state != null) {
314: n = (Vector) new_state;
315: for (int i = 0; i < n.size(); i++)
316: nodes.addElement(n.elementAt(i));
317: repaint();
318: }
319: }
320: }
321:
322: public void moveNode(Node n) {
323: Node tmp;
324: boolean changed = false;
325:
326: synchronized (nodes) {
327: for (int i = 0; i < nodes.size(); i++) {
328: tmp = (Node) nodes.elementAt(i);
329: if (n.addr.equals(tmp.addr)) {
330: tmp.x = n.x;
331: tmp.y = n.y;
332: changed = true;
333: break;
334: }
335: }
336: if (changed)
337: repaint();
338: }
339: }
340:
341: }
|