KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > tribe > demos > draw > WhiteBoard


1 /**
2  * Tribe: Group communication library.
3  * Copyright (C) 2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: tribe@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Bela Ban.
22  * Contributor(s): Emmanuel Cecchet.
23  */

24
25 package org.objectweb.tribe.demos.draw;
26
27 import java.awt.Color JavaDoc;
28 import java.awt.Dimension JavaDoc;
29 import java.awt.Font JavaDoc;
30 import java.awt.Graphics JavaDoc;
31 import java.awt.Image JavaDoc;
32 import java.awt.event.ActionEvent JavaDoc;
33 import java.awt.event.ActionListener JavaDoc;
34 import java.awt.event.ComponentAdapter JavaDoc;
35 import java.awt.event.ComponentEvent JavaDoc;
36 import java.awt.event.MouseEvent JavaDoc;
37 import java.awt.event.MouseMotionListener JavaDoc;
38 import java.net.InetAddress JavaDoc;
39 import java.util.Random JavaDoc;
40
41 import javax.swing.JButton JavaDoc;
42 import javax.swing.JFrame JavaDoc;
43 import javax.swing.JPanel JavaDoc;
44
45 import org.objectweb.tribe.channel.ReliableGroupChannelWithGms;
46 import org.objectweb.tribe.channel.tcp.TcpChannelPool;
47 import org.objectweb.tribe.common.GroupIdentifier;
48 import org.objectweb.tribe.common.IpAddress;
49 import org.objectweb.tribe.gms.GroupMembershipService;
50 import org.objectweb.tribe.gms.discovery.UdpDiscoveryService;
51
52 /**
53  * Shared whiteboard, each new instance joins the same group. Each instance
54  * chooses a random color, mouse moves are broadcast to all group members, which
55  * then apply them to their canvas
56  * <p>
57  *
58  * @author Bela Ban, Oct 17 2001
59  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
60  * @version 1.0
61  */

62 public class WhiteBoard implements ActionListener JavaDoc
63 {
64   private static final String JavaDoc GROUP_NAME = "tribe.whiteboard";
65   private ReliableGroupChannelWithGms channel = null;
66   private int memberSize = 1;
67   boolean first = true,
68       cummulative = true;
69   private JFrame JavaDoc mainFrame = null;
70   private JPanel JavaDoc subPanel = null;
71   private DrawPanel panel = null;
72   private JButton JavaDoc clearButton;
73   private JButton JavaDoc leaveButton;
74   private Random JavaDoc random = new Random JavaDoc(System
75                                                           .currentTimeMillis());
76   private final Font JavaDoc defaultFont = new Font JavaDoc("Helvetica",
77                                                           Font.PLAIN, 12);
78   private Color JavaDoc drawColor = selectColor();
79   private Color JavaDoc backgroundColor = Color.white;
80
81   /**
82    * Creates a new <code>WhiteBoard</code> object
83    *
84    * @throws Exception if an error occurs
85    */

86   public WhiteBoard() throws Exception JavaDoc
87   {
88     final InetAddress JavaDoc MULTICAST_ADDRESS = InetAddress.getByName("224.7.65.23");
89     final int MULTICAST_PORT = 2288;
90     final IpAddress MULTICAST_IP = new IpAddress(MULTICAST_ADDRESS,
91         MULTICAST_PORT);
92     final InetAddress JavaDoc REPLY_ADDRESS = InetAddress.getLocalHost();
93     final int REPLY_PORT = 0;
94     final IpAddress REPLY_IP = new IpAddress(REPLY_ADDRESS, REPLY_PORT);
95
96     UdpDiscoveryService discovery = new UdpDiscoveryService(MULTICAST_IP,
97         REPLY_IP);
98     GroupMembershipService gms = new GroupMembershipService(REPLY_IP,
99         TcpChannelPool.getChannelPool(), discovery);
100
101     channel = new ReliableGroupChannelWithGms(gms);
102     // channel.setChannelListener(this);
103
}
104
105   /**
106    * Starts the WhiteBoard application. No parameter are required.
107    *
108    * @param args not used
109    */

110   public static void main(String JavaDoc[] args)
111   {
112     WhiteBoard whiteBoard = null;
113
114     try
115     {
116       whiteBoard = new WhiteBoard();
117       whiteBoard.go();
118     }
119     catch (Throwable JavaDoc e)
120     {
121       e.printStackTrace();
122       System.exit(0);
123     }
124   }
125
126   /**
127    * Randomly chooses a color.
128    *
129    * @return a new Color
130    */

131   private Color JavaDoc selectColor()
132   {
133     int red = (Math.abs(random.nextInt()) % 255);
134     int green = (Math.abs(random.nextInt()) % 255);
135     int blue = (Math.abs(random.nextInt()) % 255);
136     return new Color JavaDoc(red, green, blue);
137   }
138
139   /**
140    * Join the group, create the frame and listen for events.
141    *
142    * @throws Exception if an error occurs
143    */

144   public void go() throws Exception JavaDoc
145   {
146     channel.join(new GroupIdentifier(GROUP_NAME));
147
148     mainFrame = new JFrame JavaDoc();
149     mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
150     panel = new DrawPanel();
151     panel.setBackground(backgroundColor);
152     subPanel = new JPanel JavaDoc();
153     mainFrame.getContentPane().add("Center", panel);
154     clearButton = new JButton JavaDoc("Clear");
155     clearButton.setFont(defaultFont);
156     clearButton.addActionListener(this);
157     leaveButton = new JButton JavaDoc("Leave & Exit");
158     leaveButton.setFont(defaultFont);
159     leaveButton.addActionListener(this);
160     subPanel.add("South", clearButton);
161     subPanel.add("South", leaveButton);
162     mainFrame.getContentPane().add("South", subPanel);
163     mainFrame.setBackground(backgroundColor);
164     clearButton.setForeground(Color.blue);
165     leaveButton.setForeground(Color.blue);
166     setTitle();
167     mainFrame.pack();
168     mainFrame.setLocation(15, 25);
169     mainFrame.setVisible(true);
170     mainLoop();
171   }
172
173   /**
174    * Set the windows title.
175    *
176    * @param title title to set.
177    */

178   void setTitle(String JavaDoc title)
179   {
180     String JavaDoc tmp = "";
181     if (title != null)
182     {
183       mainFrame.setTitle(title);
184     }
185     else
186     {
187       // if (channel.getLocalAddress() != null)
188
// tmp += channel.getLocalAddress();
189
tmp += " (" + memberSize + ") mbrs";
190       mainFrame.setTitle(tmp);
191     }
192   }
193
194   /**
195    * Set the windows title
196    */

197   void setTitle()
198   {
199     setTitle(null);
200   }
201
202   /**
203    * Main loop handling incoming messages.
204    */

205   public void mainLoop()
206   {
207     Object JavaDoc msg = null;
208     WhiteBoardCommand comm;
209     boolean fl = true;
210
211     while (fl)
212     {
213       try
214       {
215         msg = channel.receive();
216
217         // if (tmp instanceof View)
218
// {
219
// View v = (View) tmp;
220
// System.out.println("** View=" + v);
221
// memberSize = v.size();
222
// if (mainFrame != null)
223
// setTitle();
224
// continue;
225
// }
226

227         comm = null;
228
229         if (msg instanceof WhiteBoardCommand)
230           comm = (WhiteBoardCommand) msg;
231         else
232         {
233           if (msg != null)
234             System.out.println("*** Draw.run(): msg is " + msg.getClass());
235           else
236             System.out.println("*** Draw.run(): msg is null");
237           continue;
238         }
239
240         switch (comm.mode)
241         {
242           case WhiteBoardCommand.DRAW :
243             if (panel != null)
244               panel.drawPoint(comm);
245             break;
246           case WhiteBoardCommand.CLEAR :
247             clearPanel();
248             continue;
249           default :
250             System.err
251                 .println("***** Draw.run(): received invalid draw command "
252                     + comm.mode);
253             break;
254         }
255
256       }
257       catch (Exception JavaDoc e)
258       {
259         System.err.println(e);
260         continue;
261       }
262     }
263   }
264
265   /* --------------- Callbacks --------------- */
266
267   /**
268    * Clear the panel
269    */

270   public void clearPanel()
271   {
272     if (panel != null)
273       panel.clear();
274   }
275
276   /**
277    * Send the clear panel order to other members.
278    */

279   public void sendClearPanelMsg()
280   {
281     WhiteBoardCommand comm = new WhiteBoardCommand();
282
283     try
284     {
285       channel.send(comm);
286     }
287     catch (Exception JavaDoc ex)
288     {
289       System.err.println(ex);
290     }
291   }
292
293   /**
294    * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
295    */

296   public void actionPerformed(ActionEvent JavaDoc e)
297   {
298     String JavaDoc command = e.getActionCommand();
299     if (command.equals("Clear"))
300       sendClearPanelMsg();
301     else if (command.equals("Leave & Exit"))
302     {
303       try
304       {
305         channel.close();
306       }
307       catch (Exception JavaDoc ex)
308       {
309         System.err.println(ex);
310       }
311       mainFrame.setVisible(false);
312       mainFrame.dispose();
313       System.exit(0);
314     }
315     else
316       System.out.println("Unknown action");
317   }
318
319   /**
320    * This class defines a DrawPanel used for handling mouse events and display.
321    *
322    * @author Bela Ban
323    * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
324    * @version 1.0
325    */

326   private class DrawPanel extends JPanel JavaDoc implements MouseMotionListener JavaDoc
327   {
328     Dimension JavaDoc preferred_size = new Dimension JavaDoc(235, 170);
329     Image JavaDoc img = null; // for drawing pixels
330
Dimension JavaDoc d, imgsize;
331     Graphics JavaDoc gr = null;
332
333     /**
334      * Creates a new <code>DrawPanel</code> object
335      */

336     public DrawPanel()
337     {
338       createOffscreenImage();
339       addMouseMotionListener(this);
340       addComponentListener(new ComponentAdapter JavaDoc()
341       {
342         public void componentResized(ComponentEvent JavaDoc e)
343         {
344           if (getWidth() <= 0 || getHeight() <= 0)
345             return;
346           createOffscreenImage();
347         }
348       });
349     }
350
351     /**
352      * Create an off screen image.
353      */

354     void createOffscreenImage()
355     {
356       d = getSize();
357       if (img == null || imgsize == null || imgsize.width != d.width
358           || imgsize.height != d.height)
359       {
360         img = createImage(d.width, d.height);
361         if (img != null)
362           gr = img.getGraphics();
363         imgsize = d;
364       }
365     }
366
367     //
368
// -------------- MouseMotionListener interface ---------------
369
//
370

371     /**
372      * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
373      */

374     public void mouseDragged(MouseEvent JavaDoc e)
375     {
376       int x = e.getX(), y = e.getY();
377       WhiteBoardCommand comm = new WhiteBoardCommand(x, y, drawColor.getRed(),
378           drawColor.getGreen(), drawColor.getBlue());
379
380       try
381       {
382         channel.send(comm);
383         Thread.yield(); // gives the repainter some breath
384
}
385       catch (Exception JavaDoc ex)
386       {
387         System.err.println(ex);
388       }
389     }
390
391     /**
392      * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
393      */

394     public void mouseMoved(MouseEvent JavaDoc e)
395     {
396     }
397
398     //
399
// -------------- End of MouseMotionListener interface --------------
400
//
401

402     /**
403      * Adds pixel to queue and calls repaint() whenever we have MAX_ITEMS pixels
404      * in the queue or when MAX_TIME msecs have elapsed (whichever comes first).
405      * The advantage compared to just calling repaint() after adding a pixel to
406      * the queue is that repaint() can most often draw multiple points at the
407      * same time.
408      */

409     public void drawPoint(WhiteBoardCommand c)
410     {
411       if (c == null || gr == null)
412         return;
413       gr.setColor(new Color JavaDoc(c.r, c.g, c.b));
414       gr.fillOval(c.x, c.y, 10, 10);
415       repaint();
416     }
417
418     /**
419      * Clear the frame content
420      */

421     public void clear()
422     {
423       if (gr == null)
424         return;
425       gr.clearRect(0, 0, getSize().width, getSize().height);
426       repaint();
427     }
428
429     /**
430      * @see java.awt.Component#getPreferredSize()
431      */

432     public Dimension JavaDoc getPreferredSize()
433     {
434       return preferred_size;
435     }
436
437     /**
438      * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
439      */

440     public void paintComponent(Graphics JavaDoc g)
441     {
442       super.paintComponent(g);
443       if (img != null)
444       {
445         g.drawImage(img, 0, 0, null);
446       }
447     }
448
449   }
450
451 }
452
453
Popular Tags