KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgroups > demos > Draw


1 // $Id: Draw.java,v 1.10 2005/01/28 14:18:32 belaban Exp $
2

3
4 package org.jgroups.demos;
5
6
7 import org.jgroups.*;
8 import org.jgroups.debug.Debugger;
9 import org.jgroups.util.Util;
10
11 import javax.swing.*;
12 import java.awt.*;
13 import java.awt.event.*;
14 import java.io.ByteArrayOutputStream JavaDoc;
15 import java.io.ObjectOutputStream JavaDoc;
16 import java.util.Random JavaDoc;
17
18
19
20
21 /**
22  * Shared whiteboard, each new instance joins the same group. Each instance chooses a random color,
23  * mouse moves are broadcast to all group members, which then apply them to their canvas<p>
24  * @author Bela Ban, Oct 17 2001
25  */

26 public class Draw implements ActionListener, ChannelListener {
27     private final ByteArrayOutputStream JavaDoc out=new ByteArrayOutputStream JavaDoc();
28     private final String JavaDoc groupname="DrawGroupDemo";
29     private JChannel channel=null;
30     private int member_size=1;
31     Debugger debugger=null;
32     final boolean first=true;
33     final boolean cummulative=true;
34     private JFrame mainFrame=null;
35     private JPanel sub_panel=null;
36     private DrawPanel panel=null;
37     private JButton clear_button, leave_button;
38     private final Random JavaDoc random=new Random JavaDoc(System.currentTimeMillis());
39     private final Font default_font=new Font("Helvetica",Font.PLAIN,12);
40     private final Color draw_color=selectColor();
41     private final Color background_color=Color.white;
42     boolean no_channel=false;
43
44
45
46
47
48     public Draw(String JavaDoc props, boolean debug, boolean cummulative, boolean no_channel) throws Exception JavaDoc {
49         this.no_channel=no_channel;
50         if(no_channel)
51             return;
52
53         channel=new JChannel(props);
54         if(debug) {
55             debugger=new Debugger(channel, cummulative);
56             debugger.start();
57         }
58         channel.setOpt(Channel.AUTO_RECONNECT, Boolean.TRUE);
59         channel.setChannelListener(this);
60     }
61
62
63
64
65
66
67    public static void main(String JavaDoc[] args) {
68        Draw draw=null;
69        String JavaDoc props=null;
70        boolean debug=false;
71        boolean cummulative=false;
72        boolean no_channel=false;
73
74         for(int i=0; i < args.length; i++) {
75             if("-help".equals(args[i])) {
76                 help();
77                 return;
78             }
79             if("-debug".equals(args[i])) {
80                 debug=true;
81                 continue;
82             }
83             if("-cummulative".equals(args[i])) {
84                 cummulative=true;
85                 continue;
86             }
87             if("-props".equals(args[i])) {
88                 props=args[++i];
89                 continue;
90             }
91             if("-no_channel".equals(args[i])) {
92                 no_channel=true;
93                 continue;
94             }
95             help();
96             return;
97         }
98
99         if(props == null) {
100             props="UDP(mcast_addr=228.8.8.8;mcast_port=45566;ip_ttl=32;" +
101                     "mcast_send_buf_size=64000;mcast_recv_buf_size=64000):" +
102                     //"PIGGYBACK(max_wait_time=100;max_size=32000):" +
103
"PING(timeout=2000;num_initial_members=3):" +
104                     "MERGE2(min_interval=5000;max_interval=10000):" +
105                     "FD_SOCK:" +
106                     "VERIFY_SUSPECT(timeout=1500):" +
107                     "pbcast.NAKACK(max_xmit_size=8096;gc_lag=50;retransmit_timeout=600,1200,2400,4800):" +
108                     "UNICAST(timeout=600,1200,2400,4800):" +
109                     "pbcast.STABLE(desired_avg_gossip=20000):" +
110                     "FRAG(frag_size=8096;down_thread=false;up_thread=false):" +
111                     // "CAUSAL:" +
112
"pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;" +
113                     "shun=false;print_local_addr=true)";
114         }
115
116
117         try {
118             draw=new Draw(props, debug, cummulative, no_channel);
119             draw.go();
120         }
121         catch(Throwable JavaDoc e) {
122             e.printStackTrace();
123             System.exit(0);
124         }
125     }
126
127
128     static void help() {
129         System.out.println("\nDraw [-help] [-debug] [-cummulative] [-no_channel] [-props <protocol stack definition>]");
130         System.out.println("-debug: brings up a visual debugger");
131         System.out.println("-no_channel: doesn't use JGroups at all, any drawing will be relected on the " +
132                            "whiteboard directly");
133         System.out.println("-props: argument can be an old-style protocol stack specification, or it can be " +
134                            "a URL. In the latter case, the protocol specification will be read from the URL\n");
135     }
136
137
138     private Color selectColor() {
139         int red=(Math.abs(random.nextInt()) % 255);
140         int green=(Math.abs(random.nextInt()) % 255);
141         int blue=(Math.abs(random.nextInt()) % 255);
142         return new Color(red, green, blue);
143     }
144
145
146
147     public void go() throws Exception JavaDoc {
148         if(!no_channel) {
149             channel.connect(groupname);
150         }
151         mainFrame=new JFrame();
152         mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
153         panel=new DrawPanel();
154         panel.setBackground(background_color);
155         sub_panel=new JPanel();
156         mainFrame.getContentPane().add("Center", panel);
157         clear_button=new JButton("Clear");
158         clear_button.setFont(default_font);
159         clear_button.addActionListener(this);
160         leave_button=new JButton("Leave & Exit");
161         leave_button.setFont(default_font);
162         leave_button.addActionListener(this);
163         sub_panel.add("South", clear_button);
164         sub_panel.add("South", leave_button);
165         mainFrame.getContentPane().add("South", sub_panel);
166         mainFrame.setBackground(background_color);
167         clear_button.setForeground(Color.blue);
168         leave_button.setForeground(Color.blue);
169         setTitle();
170         mainFrame.pack();
171         mainFrame.setLocation(15, 25);
172         mainFrame.setBounds(new Rectangle(250, 250));
173         mainFrame.setVisible(true);
174         if(!no_channel)
175             mainLoop();
176     }
177
178
179
180
181     void setTitle(String JavaDoc title) {
182         String JavaDoc tmp="";
183         if(no_channel) {
184             mainFrame.setTitle(" Draw Demo ");
185             return;
186         }
187         if(title != null) {
188             mainFrame.setTitle(title);
189         }
190         else {
191             if(channel.getLocalAddress() != null)
192                 tmp+=channel.getLocalAddress();
193             tmp+=" (" + member_size + ")";
194             mainFrame.setTitle(tmp);
195         }
196     }
197
198     void setTitle() {
199         setTitle(null);
200     }
201
202
203
204
205     public void mainLoop() {
206         Object JavaDoc tmp;
207         Message msg=null;
208         DrawCommand comm;
209         boolean fl=true;
210
211         while(fl) {
212             try {
213                 tmp=channel.receive(0);
214                 if(tmp == null) continue;
215
216                 if(tmp instanceof View) {
217                     View v=(View)tmp;
218                     if(v instanceof MergeView)
219                         System.out.println("** MergeView=" + v);
220                     else
221                         System.out.println("** View=" + v);
222                     member_size=v.size();
223                     if(mainFrame != null)
224                         setTitle();
225                     continue;
226                 }
227
228                 if(tmp instanceof ExitEvent) {
229                     System.out.println("-- Draw.main(): received EXIT, waiting for ChannelReconnected callback");
230                     setTitle(" Draw Demo - shunned ");
231                     break;
232                 }
233
234                 if(!(tmp instanceof Message))
235                     continue;
236
237                 msg=(Message)tmp;
238                 comm=null;
239
240                 Object JavaDoc obj=msg.getObject();
241                 if(obj instanceof DrawCommand)
242                     comm=(DrawCommand)obj;
243                 else if(obj instanceof Message) {
244                     System.out.println("*** Draw.run(): message is " + Util.printMessage((Message)obj));
245                     Util.dumpStack(false);
246                     continue;
247                 }
248                 else {
249                     if(obj != null)
250                         System.out.println("*** Draw.run(): obj is " + obj.getClass() +
251                                            ", hdrs are" + msg.printObjectHeaders());
252                     else
253                         System.out.println("*** Draw.run(): hdrs are " + msg.printObjectHeaders());
254                     Util.dumpStack(false);
255                     continue;
256                 }
257
258                 switch(comm.mode) {
259                 case DrawCommand.DRAW:
260                     if(panel != null)
261                         panel.drawPoint(comm);
262                     break;
263                 case DrawCommand.CLEAR:
264                     clearPanel();
265                     continue;
266                 default:
267                     System.err.println("***** Draw.run(): received invalid draw command " + comm.mode);
268                     break;
269                 }
270
271             }
272             catch(ChannelNotConnectedException not) {
273                 System.err.println("Draw: " + not);
274                 break;
275             }
276             catch(ChannelClosedException closed) {
277                 break;
278             }
279             catch(Exception JavaDoc e) {
280                 System.err.println(e);
281                 continue;
282             }
283         }
284     }
285
286
287
288
289
290     /* --------------- Callbacks --------------- */
291
292
293
294     public void clearPanel() {
295         if(panel != null)
296             panel.clear();
297     }
298
299     public void sendClearPanelMsg() {
300         int tmp[]=new int[1]; tmp[0]=0;
301         DrawCommand comm=new DrawCommand(DrawCommand.CLEAR);
302         ObjectOutputStream JavaDoc os;
303
304         try {
305             out.reset();
306             os=new ObjectOutputStream JavaDoc(out);
307             os.writeObject(comm);
308             os.flush();
309             channel.send(new Message(null, null, out.toByteArray()));
310         }
311         catch(Exception JavaDoc ex) {
312             System.err.println(ex);
313         }
314     }
315
316
317     public void actionPerformed(ActionEvent e) {
318         String JavaDoc command=e.getActionCommand();
319         if("Clear".equals(command)) {
320             if(no_channel) {
321                 clearPanel();
322                 return;
323             }
324             sendClearPanelMsg();
325         }
326         else if("Leave & Exit".equals(command)) {
327             if(!no_channel) {
328                 try {
329                     channel.close();
330                 }
331                 catch(Exception JavaDoc ex) {
332                     System.err.println(ex);
333                 }
334             }
335             mainFrame.setVisible(false);
336             mainFrame.dispose();
337             System.exit(0);
338         }
339         else
340             System.out.println("Unknown action");
341     }
342
343
344     /* ------------------------------ ChannelListener interface -------------------------- */
345
346     public void channelConnected(Channel channel) {
347
348     }
349
350     public void channelDisconnected(Channel channel) {
351
352     }
353
354     public void channelClosed(Channel channel) {
355
356     }
357
358     public void channelShunned() {
359
360     }
361
362     public void channelReconnected(Address addr) {
363         setTitle();
364         new Thread JavaDoc() {
365             public void run() {
366                 mainLoop();
367             }
368         }.start();
369     }
370
371
372     /* --------------------------- End of ChannelListener interface ---------------------- */
373
374
375
376     private class DrawPanel extends JPanel implements MouseMotionListener {
377         final Dimension preferred_size=new Dimension(235, 170);
378         Image img=null; // for drawing pixels
379
Dimension d, imgsize;
380         Graphics gr=null;
381
382
383         public DrawPanel() {
384             createOffscreenImage();
385             addMouseMotionListener(this);
386             addComponentListener(new ComponentAdapter() {
387                 public void componentResized(ComponentEvent e) {
388                     if(getWidth() <= 0 || getHeight() <= 0) return;
389                     createOffscreenImage();
390                 }
391             });
392         }
393
394
395
396         void createOffscreenImage() {
397             d=getSize();
398             if(img == null || imgsize == null || imgsize.width != d.width || imgsize.height != d.height) {
399                 img=createImage(d.width, d.height);
400                 if(img != null)
401                     gr=img.getGraphics();
402                 imgsize=d;
403             }
404         }
405
406
407         /* ---------------------- MouseMotionListener interface------------------------- */
408
409         public void mouseMoved(MouseEvent e) {}
410
411         public void mouseDragged(MouseEvent e) {
412             ObjectOutputStream JavaDoc os;
413             int x=e.getX(), y=e.getY();
414             DrawCommand comm=new DrawCommand(DrawCommand.DRAW, x, y,
415                                                      draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue());
416
417             if(no_channel) {
418                 drawPoint(comm);
419                 return;
420             }
421
422             try {
423                 out.reset();
424                 os=new ObjectOutputStream JavaDoc(out);
425                 os.writeObject(comm);
426                 os.flush();
427                 channel.send(new Message(null, null, out.toByteArray()));
428                 Thread.yield(); // gives the repainter some breath
429
}
430             catch(Exception JavaDoc ex) {
431                 System.err.println(ex);
432             }
433         }
434
435         /* ------------------- End of MouseMotionListener interface --------------------- */
436
437
438         /**
439          * Adds pixel to queue and calls repaint() whenever we have MAX_ITEMS pixels in the queue
440          * or when MAX_TIME msecs have elapsed (whichever comes first). The advantage compared to just calling
441          * repaint() after adding a pixel to the queue is that repaint() can most often draw multiple points
442          * at the same time.
443          */

444         public void drawPoint(DrawCommand c) {
445             if(c == null || gr == null) return;
446             gr.setColor(new Color(c.r, c.g, c.b));
447             gr.fillOval(c.x, c.y, 10, 10);
448             repaint();
449         }
450
451
452
453         public void clear() {
454             if(gr == null) return;
455             gr.clearRect(0, 0, getSize().width, getSize().height);
456             repaint();
457         }
458
459
460         public Dimension getPreferredSize() {
461             return preferred_size;
462         }
463
464
465         public void paintComponent(Graphics g) {
466             super.paintComponent(g);
467             if(img != null) {
468                 g.drawImage(img, 0, 0, null);
469             }
470         }
471
472     }
473
474
475
476
477
478 }
479
480
Popular Tags