001: // $Id: Draw2Channels.java,v 1.10 2006/10/09 11:35:19 belaban Exp $
002:
003: package org.jgroups.demos;
004:
005: import org.jgroups.*;
006: import org.jgroups.Event;
007: import org.jgroups.util.Util;
008:
009: import javax.swing.*;
010: import java.awt.*;
011: import java.awt.event.*;
012: import java.util.Random;
013:
014: /**
015: * Same as Draw but using 2 channels: one for view changes (control channel) and the other one for drawing
016: * (data channel). Ported to use Swing Nov 1 2001, not tested.
017: * @author Bela Ban, Nov 1 2001
018: */
019: public class Draw2Channels implements ActionListener {
020: private final String control_groupname = "Draw2ChannelsGroup-Control";
021: private final String data_groupname = "Draw2ChannelsGroup-Data";
022: private Channel control_channel = null;
023: private Channel data_channel = null;
024: String control_props = null, data_props = null;
025: private Receiver control_receiver = null;
026: private Receiver data_receiver = null;
027: private int member_size = 1;
028: final boolean first = true;
029: final boolean cummulative = true;
030: private JFrame mainFrame = null;
031: private JPanel sub_panel = null;
032: private DrawPanel panel = null;
033: private JButton clear_button, leave_button;
034: private final Random random = new Random(System.currentTimeMillis());
035: private final Font default_font = new Font("Helvetica", Font.PLAIN,
036: 12);
037: private final Color draw_color = selectColor();
038: private final Color background_color = Color.white;
039: boolean no_channel = false;
040:
041: public Draw2Channels(String control_props, String data_props,
042: boolean no_channel) throws Exception {
043:
044: this .control_props = control_props;
045: this .data_props = data_props;
046: this .no_channel = no_channel;
047: }
048:
049: public static void main(String[] args) {
050: Draw2Channels draw = null;
051: String control_props = null, data_props = null;
052: boolean no_channel = false;
053:
054: for (int i = 0; i < args.length; i++) {
055: if ("-help".equals(args[i])) {
056: help();
057: return;
058: }
059: if ("-no_channel".equals(args[i])) {
060: no_channel = true;
061: continue;
062: }
063: help();
064: return;
065: }
066:
067: control_props = "UDP(mcast_addr=224.0.0.35;mcast_port=45566;ip_ttl=32;"
068: + "mcast_send_buf_size=150000;mcast_recv_buf_size=80000):"
069: + "PING(timeout=2000;num_initial_members=3):"
070: + "MERGE2(min_interval=5000;max_interval=10000):"
071: + "FD_SOCK:"
072: + "VERIFY_SUSPECT(timeout=1500):"
073: + "pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800):"
074: + "UNICAST(timeout=5000):"
075: + "pbcast.STABLE(desired_avg_gossip=20000):"
076: + "FRAG(frag_size=4096;down_thread=false;up_thread=false):"
077: + "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;"
078: + "shun=false;print_local_addr=true)";
079:
080: data_props = "UDP(mcast_addr=224.10.10.200;mcast_port=5679)";
081:
082: try {
083:
084: draw = new Draw2Channels(control_props, data_props,
085: no_channel);
086: draw.go();
087: } catch (Exception e) {
088: System.err.println(e);
089: System.exit(0);
090: }
091: }
092:
093: static void help() {
094: System.out.println("Draw2Channels [-help] [-no_channel]");
095: }
096:
097: private Color selectColor() {
098: int red = (Math.abs(random.nextInt()) % 255);
099: int green = (Math.abs(random.nextInt()) % 255);
100: int blue = (Math.abs(random.nextInt()) % 255);
101: return new Color(red, green, blue);
102: }
103:
104: public void go() {
105: try {
106: if (!no_channel) {
107: control_receiver = new ControlReceiver();
108: data_receiver = new DataReceiver();
109: System.out.println("Creating control channel");
110: control_channel = new JChannel(control_props);
111: control_channel.setReceiver(control_receiver);
112: System.out.println("Creating data channel");
113: data_channel = new JChannel(data_props);
114: data_channel.setReceiver(data_receiver);
115: // data_channel.SetOpt(Channel.VIEW, Boolean.FALSE);
116: System.out.println("Connecting data channel");
117: data_channel.connect(data_groupname);
118: System.out.println("Connecting control channel");
119: control_channel.connect(control_groupname);
120: }
121: mainFrame = new JFrame();
122: mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
123: panel = new DrawPanel();
124: panel.setBackground(background_color);
125: sub_panel = new JPanel();
126: mainFrame.getContentPane().add("Center", panel);
127: clear_button = new JButton("Clear");
128: clear_button.setFont(default_font);
129: clear_button.addActionListener(this );
130: leave_button = new JButton("Leave & Exit");
131: leave_button.setFont(default_font);
132: leave_button.addActionListener(this );
133: sub_panel.add("South", clear_button);
134: sub_panel.add("South", leave_button);
135: mainFrame.getContentPane().add("South", sub_panel);
136: mainFrame.setVisible(true);
137: mainFrame.setBackground(background_color);
138: clear_button.setForeground(Color.blue);
139: leave_button.setForeground(Color.blue);
140: setTitle();
141: mainFrame.pack();
142: mainFrame.setLocation(15, 25);
143: mainFrame.setVisible(true);
144: } catch (Exception e) {
145: System.err.println(e);
146: }
147: }
148:
149: void setTitle() {
150: String title = "";
151: if (no_channel) {
152: mainFrame.setTitle(" Draw Demo ");
153: return;
154: }
155: if (control_channel.getLocalAddress() != null)
156: title += control_channel.getLocalAddress();
157: title += " (" + member_size + ") mbrs";
158: mainFrame.setTitle(title);
159: }
160:
161: public void clearPanel() {
162: if (panel != null)
163: panel.clear();
164: }
165:
166: public void sendClearPanelMsg() {
167: int tmp[] = new int[1];
168: tmp[0] = 0;
169: DrawCommand comm = new DrawCommand(DrawCommand.CLEAR);
170:
171: try {
172: byte[] buf = Util.streamableToByteBuffer(comm);
173: data_channel.send(new Message(null, null, buf));
174: } catch (Exception ex) {
175: System.err.println(ex);
176: }
177: }
178:
179: public void actionPerformed(ActionEvent e) {
180: String command = e.getActionCommand();
181: if ("Clear".equals(command)) {
182: if (no_channel) {
183: clearPanel();
184: return;
185: }
186: sendClearPanelMsg();
187: } else if ("Leave & Exit".equals(command)) {
188: if (!no_channel) {
189: try {
190: control_channel.close();
191: } catch (Exception ex) {
192: System.err.println(ex);
193: }
194: try {
195: data_channel.close();
196: } catch (Exception ex) {
197: System.err.println(ex);
198: }
199: }
200: mainFrame.setVisible(false);
201: mainFrame.dispose();
202: System.exit(0);
203: } else
204: System.out.println("Unknown action");
205: }
206:
207: private class DrawPanel extends JPanel implements
208: MouseMotionListener {
209: final Dimension preferred_size = new Dimension(235, 170);
210: Image img = null; // for drawing pixels
211: Dimension d, imgsize;
212: Graphics gr = null;
213:
214: public DrawPanel() {
215: addMouseMotionListener(this );
216: addComponentListener(new ComponentAdapter() {
217: public void componentResized(ComponentEvent e) {
218: if (getWidth() <= 0 || getHeight() <= 0)
219: return;
220: createOffscreenImage();
221: }
222: });
223: }
224:
225: void createOffscreenImage() {
226: d = getSize();
227: if (img == null || imgsize == null
228: || imgsize.width != d.width
229: || imgsize.height != d.height) {
230: img = createImage(d.width, d.height);
231: gr = img.getGraphics();
232: imgsize = d;
233: }
234: }
235:
236: /* ---------------------- MouseMotionListener interface------------------------- */
237:
238: public void mouseMoved(MouseEvent e) {
239: }
240:
241: public void mouseDragged(MouseEvent e) {
242: int x = e.getX(), y = e.getY();
243: DrawCommand comm = new DrawCommand(DrawCommand.DRAW, x, y,
244: draw_color.getRed(), draw_color.getGreen(),
245: draw_color.getBlue());
246:
247: if (no_channel) {
248: drawPoint(comm);
249: return;
250: }
251:
252: try {
253: byte[] buf = Util.streamableToByteBuffer(comm);
254: data_channel.send(new Message(null, null, buf));
255: Thread.yield(); // gives the repainter some breath
256: } catch (Exception ex) {
257: System.err.println(ex);
258: }
259: }
260:
261: /* ------------------- End of MouseMotionListener interface --------------------- */
262:
263: /**
264: * Adds pixel to queue and calls repaint() whenever we have MAX_ITEMS pixels in the queue
265: * or when MAX_TIME msecs have elapsed (whichever comes first). The advantage compared to just calling
266: * repaint() after adding a pixel to the queue is that repaint() can most often draw multiple points
267: * at the same time.
268: */
269: public void drawPoint(DrawCommand c) {
270: if (c == null)
271: return;
272: gr.setColor(new Color(c.r, c.g, c.b));
273: gr.fillOval(c.x, c.y, 10, 10);
274: repaint();
275: }
276:
277: public void clear() {
278: gr.clearRect(0, 0, getSize().width, getSize().height);
279: repaint();
280: }
281:
282: public Dimension getPreferredSize() {
283: return preferred_size;
284: }
285:
286: public void paintComponent(Graphics g) {
287: super .paintComponent(g);
288: if (img != null) {
289: g.drawImage(img, 0, 0, null);
290: }
291: }
292:
293: }
294:
295: class ControlReceiver extends ExtendedReceiverAdapter {
296: public void viewAccepted(View v) {
297: member_size = v.size();
298: if (mainFrame != null)
299: mainFrame.setTitle(member_size + " mbrs");
300: data_channel.down(new Event(Event.VIEW_CHANGE, v));
301: }
302: }
303:
304: class DataReceiver extends ExtendedReceiverAdapter implements
305: ChannelListener {
306:
307: public void receive(Message msg) {
308: byte[] buf = msg.getRawBuffer();
309: DrawCommand comm = null;
310: try {
311: comm = (DrawCommand) Util.streamableFromByteBuffer(
312: DrawCommand.class, buf, msg.getOffset(), msg
313: .getLength());
314: switch (comm.mode) {
315: case DrawCommand.DRAW:
316: if (panel != null)
317: panel.drawPoint(comm);
318: break;
319: case DrawCommand.CLEAR:
320: clearPanel();
321: break;
322: default:
323: System.err
324: .println("***** Draw2Channels.run(): received invalid draw command "
325: + comm.mode);
326: break;
327: }
328: } catch (Exception ex) {
329: ex.printStackTrace();
330: }
331: }
332:
333: public void viewAccepted(View v) {
334: System.out.println("** View=" + v);
335: member_size = v.size();
336: if (mainFrame != null)
337: setTitle();
338: }
339:
340: public void channelConnected(Channel channel) {
341: }
342:
343: public void channelDisconnected(Channel channel) {
344: }
345:
346: public void channelClosed(Channel channel) {
347: }
348:
349: public void channelShunned() {
350: System.out
351: .println("received EXIT, waiting for ChannelReconnected callback");
352: }
353:
354: public void channelReconnected(Address addr) {
355: }
356: }
357:
358: }
|