1 package org.convey;
2 
3 import javax.swing.*;
4 import javax.swing.event.*;
5 import java.awt.event.*;
6 import java.awt.*;
7 
8 import com.echomine.jabber.*;
9 import com.echomine.common.*;
10 import com.echomine.net.*;
11 
12 import org.jdom.*;
13 import org.jdom.input.*;
14 
15 import org.jdom.output.*;
16 import java.io.*;
17 import java.util.*;
18 
19 import java.net.*;
20 
21 /**
22  * @author Andy Ames
23  * @version 0.3
24  */
25 public class ConveyFrame extends JFrame implements ChangeListener {
26 
27 	private static ConveyFrame conveyFrame = null;
28 
29 	protected ColorComboBox fillColorComboBox;
30 
31 	protected ColorComboBox strokeColorComboBox;
32 
33 	protected ColorComboBox textColorComboBox;
34 
35 	/**
36 	 * Jabber connect action. Fired when the user selects the Jabber "Connect"
37 	 * tool.
38 	 */
39 	protected Action connectAction;
40 	protected JButton connectButton;
41 
42 	/**
43 	 * Jabber disconnect action. Fired when the user selects the Jabber
44 	 * "Disconnect" tool.
45 	 */
46 	protected Action disconnectAction;
47 	protected JButton disconnectButton;
48 
49 	/**
50 	 * Jabber Chat action. Fired when the user selects the Jabber "Chat" tool.
51 	 */
52 	protected Action chatAction;
53 	protected JButton chatButton;
54 
55 	protected Action newCanvasAction;
56 	protected JButton newCanvasButton;
57 
58 	protected Action exitAction;
59 
60 	protected Action reportAction;
61 	protected Button reportButton;
62 
63 	protected ConnectDialog connectDialog;
64 
65 	protected ChatDialog chatDialog;
66 
67 	protected JabberSession session = null;
68 
69 	protected JabberMessageListener listener = null;
70 
71 	protected ActionListener chatActionListener = null;
72 
73 	protected java.util.Timer timer = new java.util.Timer();
74 
75 	protected Hashtable jabberCanvasPanels = new Hashtable();
76 
77 	protected transient Vector clipboardGraphics = new Vector();
78 
79 	protected JTabbedPaneWithCloseIcons tabbedPane;
80 
81 	protected Box toolBarBox;
82 
83 	protected JFileChooser fileChooser = null;
84 
85 	protected JTextField status;
86 
87 	/**
88 	 * Graphic select action. Fired when the user selects the Graphic "Select"
89 	 * tool.
90 	 */
91 	protected Action selectAction;
92 	protected JToggleButton selectButton = null;
93 	protected JRadioButtonMenuItem selectMenuItem = null;
94 
95 	/**
96 	 * Graphic scale action. Fired when the user selects the Graphic
97 	 * "Scale" tool.
98 	 */
99 	protected Action scaleAction;
100 	protected JToggleButton scaleButton = null;
101 	protected JRadioButtonMenuItem scaleMenuItem = null;
102 
103 	/**
104 	 * Graphic create text action. Fired when the user selects the create
105 	 * "Text" tool.
106 	 */
107 	protected Action createTextAction;
108 	protected JToggleButton createTextButton = null;
109 	protected JRadioButtonMenuItem textMenuItem = null;
110 
111 	/**
112 	 * Graphic create rectangle action. Fired when the user selects the create
113 	 * "Rectangle" tool.
114 	 */
115 	protected Action createRectangleAction;
116 	protected JToggleButton createRectangleButton = null;
117 	protected JRadioButtonMenuItem rectangleMenuItem = null;
118 
119 	/**
120 	 * Graphic create rectangle action. Fired when the user selects the create
121 	 * "Ellipse" tool.
122 	 */
123 	protected Action createEllipseAction;
124 	protected JToggleButton createEllipseButton = null;
125 	protected JRadioButtonMenuItem ellipseMenuItem = null;
126 	/**
127 	 * Graphic create rectangle action. Fired when the user selects the create
128 	 * "Polyline" tool.
129 	 */
130 	protected Action createPolylineAction;
131 	protected JToggleButton createPolylineButton = null;
132 	protected JRadioButtonMenuItem polylineMenuItem = null;
133 
134 	/**
135 	 * Graphic create rectangle action. Fired when the user selects the create
136 	 * "Polygon" tool.
137 	 */
138 	protected Action createPolygonAction;
139 	protected JToggleButton createPolygonButton = null;
140 	protected JRadioButtonMenuItem polygonMenuItem = null;
141 
142 	/**
143 	 * Graphic create rectangle action. Fired when the user selects the create
144 	 * "QCurve" tool.
145 	 */
146 	protected Action createQuadCurveAction;
147 	protected JToggleButton createQuadCurveButton = null;
148 	protected JRadioButtonMenuItem quadcurveMenuItem = null;
149 	/**
150 	 * Graphic create rectangle action. Fired when the user selects the create
151 	 * "CCurve" tool.
152 	 */
153 	protected Action createCubicCurveAction;
154 	protected JToggleButton createCubicCurveButton = null;
155 	protected JRadioButtonMenuItem cubicMenuItem = null;
156 
157 	/**
158 	 * Graphic create fitted curve action. Fired when the user selects the create
159 	 * "Fitted Curve" tool.
160 	 */
161 	protected Action createFittedCurveAction;
162 	protected JToggleButton createFittedCurveButton = null;
163 	protected JRadioButtonMenuItem fittedcurveMenuItem = null;
164 
165 	/**
166 	 * Graphic create freehand curve action. Fired when the user selects the create
167 	 * "Freehand Curve" tool.
168 	 */
169 	protected Action createFreehandCurveAction;
170 	protected JToggleButton createFreehandCurveButton = null;
171 	protected JRadioButtonMenuItem freehandcurveMenuItem = null;
172 
173 	/**
174 	 * Graphic group action. Fired when the user selects the graphic "Group" tool.
175 	 */
176 	protected Action groupAction;
177 	protected JButton groupButton;
178 
179 	/**
180 	 * Graphic ungroup action. Fired when the user selects the graphic "Ungroup"
181 	 * tool.
182 	 */
183 	protected Action ungroupAction;
184 	protected JButton ungroupButton;
185 
186 	/**
187 	 * Graphic cut action. Fired when the user selects the graphic "Cut"
188 	 * tool.
189 	 */
190 	protected Action cutAction;
191 	protected JButton cutButton;
192 
193 	/**
194 	 * Graphic copy action. Fired when the user selects the graphic "Copy"
195 	 * tool.
196 	 */
197 	protected Action copyAction;
198 	protected JButton copyButton;
199 
200 	/**
201 	 * Graphic paste action. Fired when the user selects the graphic "Paste"
202 	 * tool.
203 	 */
204 	protected Action pasteAction;
205 	protected JButton pasteButton;
206 
207 	protected Action selectAllAction;
208 
209 	/**
210 	 * Graphic delete action. Fired when the user selects the graphic "Delete"
211 	 * tool.
212 	 */
213 	protected Action deleteAction;
214 	protected JButton deleteButton;
215 
216 	/**
217 	 * Graphic clear action. Fired when the user selects the graphic "Clear"
218 	 * tool.
219 	 */
220 	protected Action clearAction;
221 	protected JButton clearButton;
222 
223 	protected Action bringForwardAction;
224 	protected JButton bringForwardButton;
225 
226 	protected Action sendBackwardAction;
227 	protected JButton sendBackwardButton;
228 
229 	protected Action bringToFrontAction;
230 	protected JButton bringToFrontButton;
231 
232 	protected Action sendToBackAction;
233 	protected JButton sendToBackButton;
234 
235 	protected Action yieldPenAction;
236 	protected JButton yieldPenButton;
237 
238 	protected Action requestPenAction;
239 	protected JButton requestPenButton;
240 
241 	protected Action revokePenAction;
242 	protected JButton revokePenButton;
243 
244 	protected Action autoSendAction;
245 	protected JToggleButton autoSendButton;
246 	protected JRadioButtonMenuItem autoSendMenuItem;
247 
248 	/**
249 	 * Open existing file action. Fired when the user selects open in the
250 	 * file menu or the open button.
251 	 *
252 	 */
253 	protected Action openAction;
254 	protected JButton openButton;
255 
256 	/**
257 	 * Save file action. Fired when the user selects save in the
258 	 * file menu or the save button.
259 	 */
260 	protected Action saveAction;
261 	protected JButton saveButton;
262 
263 	/**
264 	 * SaveAs file action. Fired when the user selects saveas in the
265 	 * file menu.
266 	 */
267 	protected Action saveAsAction;
268 	protected JButton saveAsButton;
269 
270 	protected Action closeAction;
271 	protected JButton closeButton;
272 
273 	/**
274 	 * Jabber user account that is connected. This is non-null when the user
275 	 * is connected, regardless of whether they are sending or receiving messages.
276 	 * <p>
277 	 * This field consists of the username, an ampersand, and the server
278 	 * (johndoe@jabber.org). The Jabbber resource is not included.
279 	 * (johndoe@jabber.org/Convey is incorrect.)
280 	 */
281 	protected String from = null;
282 
283 	/**
284 	 * Constructor
285 	 */
ConveyFrame()286 	public ConveyFrame() {
287 		super("Convey [disconnected]");
288 
289 		Dimension dim = super.getToolkit().getScreenSize();
290 
291 		int w = (int)(dim.getWidth() * 3.0 / 4.0);
292 		int h = (int)(dim.getHeight() * 4.0 / 5.0);
293 		super.setSize(w, h);
294 
295 		super.setLocation((int)(dim.getWidth() / 2.0 - w / 2.0),
296 											(int)(dim.getHeight() / 2.0 - h / 2.0));
297 
298 		super.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
299 
300 		WindowListener l = new WindowAdapter() {
301 			public void windowClosing(WindowEvent evt) {
302 				if(disconnect(true)) {
303 					saveConfig();
304 					System.exit(0);
305 				}
306 			}
307 		};
308 		super.addWindowListener(l);
309 
310 		super.getContentPane().setLayout(new BorderLayout(5, 5));
311 
312 		JMenuBar menuBar = new JMenuBar();
313 
314 		JMenu conveyMenu = new JMenu("Convey");
315 		conveyMenu.setMnemonic('C');
316 
317 		JToolBar conveyToolBar = new JToolBar(JToolBar.HORIZONTAL);
318 		conveyToolBar.setFloatable(false);
319 
320 		this.connectAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/connect.png")) {
321 			public void actionPerformed(ActionEvent evt) {
322 				connect();
323 			}
324 		};
325 		this.connectButton = new JButton(this.connectAction);
326 		this.connectButton.setToolTipText("Connect...");
327 		this.connectButton.setMargin(new Insets(1, 1, 1, 1));
328 		this.connectAction.setEnabled(true);
329 		conveyToolBar.add(this.connectButton);
330 		JMenuItem connectMenuItem = new JMenuItem(this.connectAction);
331 		connectMenuItem.setText("Connect...");
332 		conveyMenu.add(connectMenuItem);
333 
334 		this.disconnectAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/disconnect.png")) {
335 			public void actionPerformed(ActionEvent evt) {
336 				disconnect(true);
337 			}
338 		};
339 		this.disconnectButton = new JButton(this.disconnectAction);
340 		this.disconnectButton.setToolTipText("Disconnect");
341 		this.disconnectButton.setMargin(new Insets(1, 1, 1, 1));
342 		this.disconnectAction.setEnabled(false);
343 		conveyToolBar.add(this.disconnectButton);
344 		JMenuItem disconnectMenuItem = new JMenuItem(this.disconnectAction);
345 		disconnectMenuItem.setText("Disconnect");
346 		conveyMenu.add(disconnectMenuItem);
347 
348 		this.chatAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/chat.png")) {
349 			public void actionPerformed(ActionEvent evt) {
350 				newChat();
351 			}
352 		};
353 		this.chatButton = new JButton(this.chatAction);
354 		this.chatButton.setToolTipText("Chat...");
355 		this.chatButton.setMargin(new Insets(1, 1, 1, 1));
356 		this.chatAction.setEnabled(false);
357 		conveyToolBar.add(this.chatButton);
358 		JMenuItem chatMenuItem = new JMenuItem(this.chatAction);
359 		chatMenuItem.setText("Chat...");
360 		conveyMenu.add(chatMenuItem);
361 
362 		conveyMenu.addSeparator();
363 		conveyToolBar.addSeparator();
364 
365 		this.autoSendAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/autosend.png")) {
366 			public void actionPerformed(ActionEvent evt) {
367 				if(evt.getSource() == autoSendButton) {
368 					if(autoSendButton.isSelected()) {
369 						Iterator iter = jabberCanvasPanels.entrySet().iterator();
370 						while(iter.hasNext()) {
371 							JabberCanvasPanel jabberCanvasPanel = (JabberCanvasPanel)((Map.Entry)iter.next()).getValue();
372 							jabberCanvasPanel.getGraphicPanel().flushGraphicEventQueue();
373 						}
374 					}
375 
376 					autoSendMenuItem.setSelected(autoSendButton.isSelected());
377 				} else {
378 					if(autoSendMenuItem.isSelected()) {
379 						Iterator iter = jabberCanvasPanels.entrySet().iterator();
380 						while(iter.hasNext()) {
381 							JabberCanvasPanel jabberCanvasPanel = (JabberCanvasPanel)((Map.Entry)iter.next()).getValue();
382 							jabberCanvasPanel.getGraphicPanel().flushGraphicEventQueue();
383 						}
384 					}
385 
386 					autoSendButton.setSelected(autoSendMenuItem.isSelected());
387 				}
388 			}
389 		};
390 		this.autoSendButton = new JToggleButton(this.autoSendAction);
391 		this.autoSendButton.setMargin(new Insets(1,1,1,1));
392 		this.autoSendButton.setToolTipText("Auto Send");
393 		conveyToolBar.add(this.autoSendButton);
394 		this.autoSendMenuItem = new JRadioButtonMenuItem(this.autoSendAction);
395 		this.autoSendMenuItem.setText("Auto Send");
396 		this.autoSendButton.setSelected(true);
397 		this.autoSendMenuItem.setSelected(true);
398 		conveyMenu.add(autoSendMenuItem);
399 
400 		conveyMenu.addSeparator();
401 		conveyToolBar.addSeparator();
402 
403 		this.yieldPenAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/yieldpen.png")) {
404 			public void actionPerformed(ActionEvent evt) {
405 				CanvasPanel canvasPanel = getSelectedCanvasPanel();
406 				if(canvasPanel instanceof JabberCanvasPanel)
407 					((JabberCanvasPanel)canvasPanel).penYield();
408 			}
409 		};
410 		this.yieldPenButton = new JButton(this.yieldPenAction);
411 		this.yieldPenButton.setToolTipText("Yield Pen");
412 		this.yieldPenButton.setMargin(new Insets(1, 1, 1, 1));
413 		this.yieldPenAction.setEnabled(false);
414 		conveyToolBar.add(this.yieldPenButton);
415 		JMenuItem yieldPenMenuItem = new JMenuItem(this.yieldPenAction);
416 		yieldPenMenuItem.setText("Yield Pen");
417 		conveyMenu.add(yieldPenMenuItem);
418 
419 		this.requestPenAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/requestpen.png")) {
420 			public void actionPerformed(ActionEvent evt) {
421 				CanvasPanel canvasPanel = getSelectedCanvasPanel();
422 				if(canvasPanel instanceof JabberCanvasPanel)
423 					((JabberCanvasPanel)canvasPanel).penRequest();
424 			}
425 		};
426 		this.requestPenButton = new JButton(this.requestPenAction);
427 		this.requestPenButton.setToolTipText("Request Pen");
428 		this.requestPenButton.setMargin(new Insets(1, 1, 1, 1));
429 		this.requestPenAction.setEnabled(false);
430 		conveyToolBar.add(this.requestPenButton);
431 		JMenuItem requestPenMenuItem = new JMenuItem(this.requestPenAction);
432 		requestPenMenuItem.setText("Request Pen");
433 		conveyMenu.add(requestPenMenuItem);
434 
435 		this.revokePenAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/revokepen.png")) {
436 			public void actionPerformed(ActionEvent evt) {
437 				CanvasPanel canvasPanel = getSelectedCanvasPanel();
438 				if(canvasPanel instanceof JabberCanvasPanel)
439 					((JabberCanvasPanel)canvasPanel).penRevoke();
440 			}
441 		};
442 		this.revokePenButton = new JButton(this.revokePenAction);
443 		this.revokePenButton.setToolTipText("Revoke Pen");
444 		this.revokePenButton.setMargin(new Insets(1, 1, 1, 1));
445 		this.revokePenAction.setEnabled(false);
446 		conveyToolBar.add(this.revokePenButton);
447 		JMenuItem revokePenMenuItem = new JMenuItem(this.revokePenAction);
448 		revokePenMenuItem.setText("Revoke Pen");
449 		conveyMenu.add(revokePenMenuItem);
450 
451 		conveyMenu.addSeparator();
452 		this.exitAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/null.png")) {
453 			public void actionPerformed(ActionEvent evt) {
454 				if(disconnect(true)) {
455 					saveConfig();
456 					System.exit(0);
457 				}
458 			}
459 		};
460 		JMenuItem exitMenuItem = new JMenuItem(this.exitAction);
461 		exitMenuItem.setText("Exit");
462 		conveyMenu.add(exitMenuItem);
463 
464 		menuBar.add(conveyMenu);
465 
466 		JMenu fileMenu = new JMenu("File");
467 		fileMenu.setMnemonic('F');
468 
469 		JToolBar fileToolBar = new JToolBar(JToolBar.HORIZONTAL);
470 		fileToolBar.setFloatable(false);
471 
472 		this.newCanvasAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/newcanvas.png")) {
473 			public void actionPerformed(ActionEvent evt) {
474 				newLocal();
475 			}
476 		};
477 		this.newCanvasButton = new JButton(this.newCanvasAction);
478 		this.newCanvasButton.setMargin(new Insets(1, 1, 1, 1));
479 		this.newCanvasButton.setToolTipText("New Canvas...");
480 		fileToolBar.add(this.newCanvasButton);
481 		JMenuItem newCanvasMenuItem = new JMenuItem(this.newCanvasAction);
482 		newCanvasMenuItem.setText("New Canvas...");
483 		fileMenu.add(newCanvasMenuItem);
484 
485 		this.openAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/open.png")) {
486 			public void actionPerformed(ActionEvent evt) {
487 				fileOpen();
488 			}
489 		};
490 		this.openButton = new JButton(this.openAction);
491 		this.openButton.setMargin(new Insets(1, 1, 1, 1));
492 		this.openButton.setToolTipText("Open   Ctrl-O");
493 		fileToolBar.add(this.openButton);
494 		JMenuItem openMenuItem = new JMenuItem(this.openAction);
495 		openMenuItem.setText("Open...");
496 		openMenuItem.setMnemonic('O');
497 		openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Event.CTRL_MASK));
498 		fileMenu.add(openMenuItem);
499 
500 		this.saveAsAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/save.png")) {
501 			public void actionPerformed(ActionEvent evt) {
502 				fileSaveAs();
503 			}
504 		};
505 		this.saveAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/save.png")) {
506 			public void actionPerformed(ActionEvent evt) {
507 				fileSave();
508 			}
509 		};
510 		this.saveButton = new JButton(this.saveAction);
511 		this.saveButton.setMargin(new Insets(1, 1, 1, 1));
512 		this.saveButton.setToolTipText("Save   Ctrl-S");
513 		fileToolBar.add(this.saveButton);
514 		JMenuItem saveMenuItem = new JMenuItem(this.saveAction);
515 		saveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK));
516 		saveMenuItem.setText("Save");
517 		saveMenuItem.setMnemonic('S');
518 		fileMenu.add(saveMenuItem);
519 
520 		this.saveAsAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/null.png")) {
521 			public void actionPerformed(ActionEvent evt) {
522 				fileSaveAs();
523 			}
524 		};
525 		this.saveAsButton = new JButton(this.saveAsAction);
526 		this.saveAsButton.setMargin(new Insets(1, 1, 1, 1));
527 		JMenuItem saveAsMenuItem = new JMenuItem(this.saveAsAction);
528 		saveAsMenuItem.setText("Save As...");
529 		saveAsMenuItem.setMnemonic('v');
530 		fileMenu.add(saveAsMenuItem);
531 
532 		fileMenu.addSeparator();
533 		this.closeAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/null.png")) {
534 			public void actionPerformed(ActionEvent evt) {
535 				int tab = tabbedPane.getSelectedIndex();
536 				if(tab > 0)
537 					tabbedPane.remove(tab);
538 			}
539 		};
540 		JMenuItem closeMenuItem = new JMenuItem(this.closeAction);
541 		closeMenuItem.setText("Close");
542 		closeMenuItem.setMnemonic('C');
543 		fileMenu.add(closeMenuItem);
544 		menuBar.add(fileMenu);
545 
546 		JToolBar graphicToolBar = new JToolBar(JToolBar.HORIZONTAL);
547 		JMenu graphicMenu = new JMenu("Graphic");
548 		graphicMenu.setMnemonic('G');
549 
550 		this.selectAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/select16.png")) {
551 			public void actionPerformed(ActionEvent evt) {
552 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
553 				if(graphicPanel != null)
554 					graphicPanel.setState(GraphicPanel.SELECT);
555 				selectButton.setSelected(true);
556 				selectMenuItem.setSelected(true);
557 				status.setText("Move graphic or one of its vertices");
558 			}
559 		};
560 		this.selectButton = new JToggleButton(this.selectAction);
561 		this.selectButton.setMargin(new Insets(1,1,1,1));
562 		this.selectButton.setToolTipText("Select   Ctrl-`");
563 		graphicToolBar.add(this.selectButton);
564 		graphicToolBar.setFloatable(false);
565 		this.selectMenuItem = new JRadioButtonMenuItem(this.selectAction);
566 		this.selectMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_QUOTE, Event.CTRL_MASK));
567 		this.selectMenuItem.setText("Select");
568 		this.selectMenuItem.setMnemonic('S');
569 		graphicMenu.add(selectMenuItem);
570 
571 		this.scaleAction = new AbstractAction(null,ResourceLoader.loadImageIcon("org/convey/images/scale16.png")) {
572 			public void actionPerformed(ActionEvent evt) {
573 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
574 				if(graphicPanel != null)
575 					graphicPanel.setState(GraphicPanel.SCALE);
576 				scaleButton.setSelected(true);
577 				scaleMenuItem.setSelected(true);
578 				status.setText("Move vertex to scale graphic");
579 			}
580 		};
581 		this.scaleButton = new JToggleButton(this.scaleAction);
582 		this.scaleButton.setMargin(new Insets(1,1,1,1));
583 		this.scaleButton.setToolTipText("Scale   Ctrl-1");
584 		graphicToolBar.add(this.scaleButton);
585 		this.scaleMenuItem = new JRadioButtonMenuItem(this.scaleAction);
586 		this.scaleMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, Event.CTRL_MASK));
587 		this.scaleMenuItem.setText("Scale");
588 		this.scaleMenuItem.setMnemonic('a');
589 		graphicMenu.add(scaleMenuItem);
590 
591 		graphicToolBar.addSeparator();
592 		graphicMenu.addSeparator();
593 
594 		this.createTextAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/text16.png")) {
595 			public void actionPerformed(ActionEvent evt) {
596 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
597 				if(graphicPanel != null)
598 					graphicPanel.setState(GraphicPanel.TEXT);
599 				createTextButton.setSelected(true);
600 				textMenuItem.setSelected(true);
601 				status.setText("Click mouse to create text box");
602 			}
603 		};
604 		this.createTextButton = new JToggleButton(this.createTextAction);
605 		this.createTextButton.setMargin(new Insets(1,1,1,1));
606 		this.createTextButton.setToolTipText("Text   Ctrl-2");
607 		graphicToolBar.add(this.createTextButton);
608 		this.textMenuItem = new JRadioButtonMenuItem(this.createTextAction);
609 		this.textMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, Event.CTRL_MASK));
610 		this.textMenuItem.setText("Text");
611 		this.textMenuItem.setMnemonic('T');
612 		graphicMenu.add(textMenuItem);
613 
614 		this.createRectangleAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/rectangle16.png")) {
615 			public void actionPerformed(ActionEvent evt) {
616 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
617 				if(graphicPanel != null)
618 					graphicPanel.setState(GraphicPanel.RECTANGLE);
619 				createRectangleButton.setSelected(true);
620 				rectangleMenuItem.setSelected(true);
621 				status.setText("Drag mouse to create rectangle");
622 			}
623 		};
624 		this.createRectangleButton = new JToggleButton(this.createRectangleAction);
625 		this.createRectangleButton.setMargin(new Insets(1,1,1,1));
626 		this.createRectangleButton.setToolTipText("Rectangle   Ctrl-3");
627 		graphicToolBar.add(this.createRectangleButton);
628 		this.rectangleMenuItem = new JRadioButtonMenuItem(this.createRectangleAction);
629 		this.rectangleMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3, Event.CTRL_MASK));
630 		this.rectangleMenuItem.setText("Rectangle");
631 		this.rectangleMenuItem.setMnemonic('R');
632 		graphicMenu.add(rectangleMenuItem);
633 
634 		this.createEllipseAction = new AbstractAction(null,ResourceLoader.loadImageIcon("org/convey/images/ellipse16.png")) {
635 			public void actionPerformed(ActionEvent evt) {
636 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
637 				if(graphicPanel != null)
638 					graphicPanel.setState(GraphicPanel.ELLIPSE);
639 				createEllipseButton.setSelected(true);
640 				ellipseMenuItem.setSelected(true);
641 				status.setText("Drag mouse to create ellipse");
642 			}
643 		};
644 		this.createEllipseButton = new JToggleButton(this.createEllipseAction);
645 		this.createEllipseButton.setMargin(new Insets(1,1,1,1));
646 		this.createEllipseButton.setToolTipText("Ellipse   Ctrl-4");
647 		graphicToolBar.add(this.createEllipseButton);
648 		this.ellipseMenuItem = new JRadioButtonMenuItem(this.createEllipseAction);
649 		this.ellipseMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_4, Event.CTRL_MASK));
650 		this.ellipseMenuItem.setText("Ellipse");
651 		this.ellipseMenuItem.setMnemonic('E');
652 		graphicMenu.add(ellipseMenuItem);
653 
654 		this.createPolylineAction = new AbstractAction(null,ResourceLoader.loadImageIcon("org/convey/images/polyline16.png")) {
655 			public void actionPerformed(ActionEvent evt) {
656 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
657 				if(graphicPanel != null)
658 					graphicPanel.setState(GraphicPanel.POLYLINE);
659 				createPolylineButton.setSelected(true);
660 				polylineMenuItem.setSelected(true);
661 				status.setText("Click mouse to add polyline points (Shift+Click to finish)");
662 			}
663 		};
664 		this.createPolylineButton = new JToggleButton(this.createPolylineAction);
665 		this.createPolylineButton.setMargin(new Insets(1,1,1,1));
666 		this.createPolylineButton.setToolTipText("Polyline   Ctrl-5");
667 		graphicToolBar.add(this.createPolylineButton);
668 		this.polylineMenuItem = new JRadioButtonMenuItem(this.createPolylineAction);
669 		this.polylineMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_5, Event.CTRL_MASK));
670 		this.polylineMenuItem.setText("Polyline");
671 		this.polylineMenuItem.setMnemonic('n');
672 		graphicMenu.add(polylineMenuItem);
673 
674 
675 		this.createPolygonAction = new AbstractAction(null,ResourceLoader.loadImageIcon("org/convey/images/polygon16.png")) {
676 			public void actionPerformed(ActionEvent evt) {
677 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
678 				if(graphicPanel != null)
679 					graphicPanel.setState(GraphicPanel.POLYGON);
680 				createPolygonButton.setSelected(true);
681 				polygonMenuItem.setSelected(true);
682 				status.setText("Click mouse to add polygon points (Shift+Click to finish)");
683 			}
684 		};
685 		this.createPolygonButton = new JToggleButton(this.createPolygonAction);
686 		this.createPolygonButton.setMargin(new Insets(1,1,1,1));
687 		this.createPolygonButton.setToolTipText("Polygon   Ctrl-6");
688 		graphicToolBar.add(this.createPolygonButton);
689 		this.polygonMenuItem = new JRadioButtonMenuItem(this.createPolygonAction);
690 		this.polygonMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_6, Event.CTRL_MASK));
691 		this.polygonMenuItem.setText("Polygon");
692 		this.polygonMenuItem.setMnemonic('g');
693 		graphicMenu.add(polygonMenuItem);
694 
695 		this.createQuadCurveAction = new AbstractAction(null,ResourceLoader.loadImageIcon("org/convey/images/quadcurve16.png")) {
696 			public void actionPerformed(ActionEvent evt) {
697 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
698 				if(graphicPanel != null)
699 					graphicPanel.setState(GraphicPanel.QUADCURVE);
700 				createQuadCurveButton.setSelected(true);
701 				quadcurveMenuItem.setSelected(true);
702 				status.setText("Click mouse in three places on canvas to create Quadratic curve");
703 			}
704 		};
705 		this.createQuadCurveButton = new JToggleButton(this.createQuadCurveAction);
706 		this.createQuadCurveButton.setMargin(new Insets(1,1,1,1));
707 		this.createQuadCurveButton.setToolTipText("Quadratic Curve   Ctrl-7");
708 		graphicToolBar.add(this.createQuadCurveButton);
709 		this.quadcurveMenuItem = new JRadioButtonMenuItem(this.createQuadCurveAction);
710 		this.quadcurveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_7, Event.CTRL_MASK));
711 		this.quadcurveMenuItem.setText("Quadratic Curve");
712 		this.quadcurveMenuItem.setMnemonic('Q');
713 		graphicMenu.add(quadcurveMenuItem);
714 
715 		this.createCubicCurveAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/cubiccurve16.png")) {
716 			public void actionPerformed(ActionEvent evt) {
717 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
718 				if(graphicPanel != null)
719 					graphicPanel.setState(GraphicPanel.CUBICCURVE);
720 				createCubicCurveButton.setSelected(true);
721 				cubicMenuItem.setSelected(true);
722 				status.setText("Click mouse in four places on canvas to create Cubic curve");
723 			}
724 		};
725 		this.createCubicCurveButton = new JToggleButton(this.createCubicCurveAction);
726 		this.createCubicCurveButton.setMargin(new Insets(1,1,1,1));
727 		this.createCubicCurveButton.setToolTipText("Cubic Curve   Ctrl-8");
728 		graphicToolBar.add(this.createCubicCurveButton);
729 		this.cubicMenuItem = new JRadioButtonMenuItem(this.createCubicCurveAction);
730 		this.cubicMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_8, Event.CTRL_MASK));
731 		this.cubicMenuItem.setText("Cubic Curve");
732 		this.cubicMenuItem.setMnemonic('C');
733 		graphicMenu.add(cubicMenuItem);
734 
735 		this.createFittedCurveAction = new AbstractAction(null,ResourceLoader.loadImageIcon("org/convey/images/fittedcurve16.png")) {
736 			public void actionPerformed(ActionEvent evt) {
737 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
738 				if(graphicPanel != null)
739 					graphicPanel.setState(GraphicPanel.FITTEDCURVE);
740 				createFittedCurveButton.setSelected(true);
741 				fittedcurveMenuItem.setSelected(true);
742 				status.setText("Drag mouse to make curve. Smooth curve is created on mouse release");
743 			}
744 		};
745 		this.createFittedCurveButton = new JToggleButton(this.createFittedCurveAction);
746 		this.createFittedCurveButton.setMargin(new Insets(1,1,1,1));
747 		this.createFittedCurveButton.setToolTipText("Smooth Curve   Ctrl-9");
748 		graphicToolBar.add(this.createFittedCurveButton);
749 		this.fittedcurveMenuItem = new JRadioButtonMenuItem(this.createFittedCurveAction);
750 		this.fittedcurveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_9, Event.CTRL_MASK));
751 		this.fittedcurveMenuItem.setText("Smooth Curve");
752 		this.fittedcurveMenuItem.setMnemonic('m');
753 		graphicMenu.add(fittedcurveMenuItem);
754 
755 		this.createFreehandCurveAction = new AbstractAction(null,ResourceLoader.loadImageIcon("org/convey/images/freehand16.png")) {
756 			public void actionPerformed(ActionEvent evt) {
757 				GraphicPanel graphicPanel = getSelectedGraphicPanel();
758 				if(graphicPanel != null)
759 					graphicPanel.setState(GraphicPanel.FREEHANDCURVE);
760 				createFreehandCurveButton.setSelected(true);
761 				freehandcurveMenuItem.setSelected(true);
762 				status.setText("What you drag is what you get...");
763 			}
764 		};
765 		this.createFreehandCurveButton = new JToggleButton(this.createFreehandCurveAction);
766 		this.createFreehandCurveButton.setMargin(new Insets(1,1,1,1));
767 		this.createFreehandCurveButton.setToolTipText("Freehand Drawing   Ctrl-0");
768 		graphicToolBar.add(this.createFreehandCurveButton);
769 		this.freehandcurveMenuItem = new JRadioButtonMenuItem(this.createFreehandCurveAction);
770 		this.freehandcurveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_0, Event.CTRL_MASK));
771 		this.freehandcurveMenuItem.setText("Freehand Drawing");
772 		this.freehandcurveMenuItem.setMnemonic('h');
773 		graphicMenu.add(freehandcurveMenuItem);
774 
775 		this.strokeColorComboBox = new ColorComboBox();
776 		this.strokeColorComboBox.setMaximumSize(new Dimension(250, 100));
777 		this.strokeColorComboBox.setSelectedColor(Color.black);
778 		ActionListener al = new ActionListener() {
779 			public void actionPerformed(ActionEvent e) {
780 				getSelectedGraphicPanel().setSelectedStrokeColors(strokeColorComboBox.getSelectedColor());
781 			}
782 		};
783 		this.strokeColorComboBox.addActionListener(al);
784 		graphicToolBar.addSeparator();
785 		graphicToolBar.add(new JLabel("Stroke: "));
786 		graphicToolBar.add(this.strokeColorComboBox);
787 
788 		this.fillColorComboBox = new ColorComboBox();
789 		this.fillColorComboBox.setMaximumSize(new Dimension(250, 100));
790 		al = new ActionListener() {
791 			public void actionPerformed(ActionEvent e) {
792 				getSelectedGraphicPanel().setSelectedFillColors(fillColorComboBox.getSelectedColor());
793 			}
794 		};
795 		this.fillColorComboBox.addActionListener(al);
796 		graphicToolBar.add(new JLabel(" Fill: "));
797 		graphicToolBar.add(this.fillColorComboBox);
798 
799 		this.textColorComboBox = new ColorComboBox(false);
800 		this.textColorComboBox.setMaximumSize(new Dimension(250, 100));
801 		this.textColorComboBox.setSelectedColor(Color.black);
802 		al = new ActionListener() {
803 			public void actionPerformed(ActionEvent e) {
804 				getSelectedGraphicPanel().setSelectedTextColors(textColorComboBox.getSelectedColor());
805 			}
806 		};
807 		this.textColorComboBox.addActionListener(al);
808 		graphicToolBar.add(new JLabel(" Text: "));
809 		graphicToolBar.add(this.textColorComboBox);
810 
811 		JMenu editMenu = new JMenu("Edit");
812 		editMenu.setMnemonic('E');
813 
814 		fileToolBar.addSeparator();
815 		this.cutAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/cut.png")) {
816 			public void actionPerformed(ActionEvent evt) {
817 				getSelectedGraphicPanel().editCut();
818 				pasteAction.setEnabled(true);
819 			}
820 		};
821 		this.cutButton = new JButton(this.cutAction);
822 		this.cutButton.setMargin(new Insets(1, 1, 1, 1));
823 		this.cutButton.setToolTipText("Cut   Ctrl-X");
824 		this.cutAction.setEnabled(false);
825 		fileToolBar.add(this.cutButton);
826 		JMenuItem cutMenuItem = new JMenuItem(this.cutAction);
827 		cutMenuItem.setText("Cut");
828 		cutMenuItem.setMnemonic('t');
829 		cutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK));
830 		editMenu.add(cutMenuItem);
831 
832 
833 		this.copyAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/copy.png")) {
834 			public void actionPerformed(ActionEvent evt) {
835 				getSelectedGraphicPanel().editCopy();
836 				pasteAction.setEnabled(true);
837 			}
838 		};
839 		this.copyButton = new JButton(this.copyAction);
840 		this.copyButton.setMargin(new Insets(1, 1, 1, 1));
841 		this.copyButton.setToolTipText("Copy   Ctrl-C");
842 		this.copyAction.setEnabled(false);
843 		fileToolBar.add(this.copyButton);
844 		JMenuItem copyMenuItem = new JMenuItem(this.copyAction);
845 		copyMenuItem.setText("Copy");
846 		copyMenuItem.setMnemonic('C');
847 		copyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Event.CTRL_MASK));
848 		editMenu.add(copyMenuItem);
849 
850 
851 		this.pasteAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/paste.png")) {
852 			public void actionPerformed(ActionEvent evt) {
853 				getSelectedGraphicPanel().editPaste();
854 			}
855 		};
856 		this.pasteButton = new JButton(this.pasteAction);
857 		this.pasteButton.setMargin(new Insets(1, 1, 1, 1));
858 		this.pasteButton.setToolTipText("Paste   Ctrl-V");
859 		fileToolBar.add(this.pasteButton);
860 		if(this.clipboardGraphics.size() == 0)
861 			this.pasteAction.setEnabled(false);
862 		JMenuItem pasteMenuItem = new JMenuItem(this.pasteAction);
863 		pasteMenuItem.setText("Paste");
864 		pasteMenuItem.setMnemonic('s');
865 		pasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Event.CTRL_MASK));
866 		editMenu.add(pasteMenuItem);
867 
868 
869 		this.deleteAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/delete.png")) {
870 			public void actionPerformed(ActionEvent evt) {
871 				getSelectedGraphicPanel().editDelete();
872 			}
873 		};
874 		this.deleteButton = new JButton(this.deleteAction);
875 		this.deleteButton.setMargin(new Insets(1, 1, 1, 1));
876 		this.deleteButton.setToolTipText("Delete");
877 		fileToolBar.add(this.deleteButton);
878 		this.deleteAction.setEnabled(false);
879 		JMenuItem deleteMenuItem = new JMenuItem(this.deleteAction);
880 		deleteMenuItem.setText("Delete");
881 		deleteMenuItem.setMnemonic('D');
882 		deleteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
883 		editMenu.add(deleteMenuItem);
884 
885 		this.clearAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/null.png")) {
886 			public void actionPerformed(ActionEvent evt) {
887 				getSelectedGraphicPanel().editClear();
888 			}
889 		};
890 		this.clearAction.setEnabled(false);
891 		JMenuItem clearMenuItem = new JMenuItem(this.clearAction);
892 		clearMenuItem.setText("Clear");
893 		clearMenuItem.setMnemonic('r');
894 		editMenu.add(clearMenuItem);
895 
896 		fileToolBar.addSeparator();
897 		editMenu.addSeparator();
898 		this.groupAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/group.png")) {
899 			public void actionPerformed(ActionEvent evt) {
900 				getSelectedGraphicPanel().editGroup();
901 			}
902 		};
903 		this.groupButton = new JButton(this.groupAction);
904 		this.groupButton.setMargin(new Insets(1, 1, 1, 1));
905 		this.groupButton.setToolTipText("Group   Ctrl-G");
906 		fileToolBar.add(this.groupButton);
907 		this.groupAction.setEnabled(false);
908 		JMenuItem groupMenuItem = new JMenuItem(this.groupAction);
909 		groupMenuItem.setText("Group");
910 		groupMenuItem.setMnemonic('G');
911 		groupMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_MASK));
912 		editMenu.add(groupMenuItem);
913 
914 		this.ungroupAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/ungroup.png")) {
915 			public void actionPerformed(ActionEvent evt) {
916 				getSelectedGraphicPanel().editUngroup();
917 			}
918 		};
919 		this.ungroupButton = new JButton(this.ungroupAction);
920 		this.ungroupButton.setMargin(new Insets(1, 1, 1, 1));
921 		this.ungroupButton.setToolTipText("Ungroup   Ctrl-U");
922 		fileToolBar.add(this.ungroupButton);
923 		this.ungroupAction.setEnabled(false);
924 		JMenuItem ungroupMenuItem = new JMenuItem(this.ungroupAction);
925 		ungroupMenuItem.setText("Ungroup");
926 		ungroupMenuItem.setMnemonic('U');
927 		ungroupMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_MASK));
928 		editMenu.add(ungroupMenuItem);
929 
930 		editMenu.addSeparator();
931 		this.selectAllAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/selectall.png")) {
932 			public void actionPerformed(ActionEvent evt) {
933 				getSelectedGraphicPanel().selectAll();
934 			}
935 		};
936 		selectAllAction.setEnabled(false);
937 		JMenuItem selectAllMenuItem = new JMenuItem(this.selectAllAction);
938 		selectAllMenuItem.setText("Select All");
939 		selectAllMenuItem.setMnemonic('A');
940 		selectAllMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK));
941 		editMenu.add(selectAllMenuItem);
942 
943 		editMenu.addSeparator();
944 		fileToolBar.addSeparator();
945 		this.sendToBackAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/toback.png")) {
946 			public void actionPerformed(ActionEvent evt) {
947 				getSelectedGraphicPanel().editSendToBack();
948 			}
949 		};
950 		this.sendToBackButton = new JButton(this.sendToBackAction);
951 		this.sendToBackButton.setMargin(new Insets(1, 1, 1, 1));
952 		this.sendToBackButton.setToolTipText("Send To Back   Ctrl-B");
953 		fileToolBar.add(this.sendToBackButton);
954 		JMenuItem sendToBackMenuItem = new JMenuItem(this.sendToBackAction);
955 		sendToBackMenuItem.setText("Send To Back");
956 		sendToBackMenuItem.setMnemonic('B');
957 		sendToBackMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_MASK));
958 		editMenu.add(sendToBackMenuItem);
959 
960 		this.bringToFrontAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/tofront.png")) {
961 			public void actionPerformed(ActionEvent evt) {
962 				getSelectedGraphicPanel().editBringToFront();
963 			}
964 		};
965 		this.bringToFrontButton = new JButton(this.bringToFrontAction);
966 		this.bringToFrontButton.setMargin(new Insets(1, 1, 1, 1));
967 		this.bringToFrontButton.setToolTipText("Bring To Front   Ctrl-F");
968 		fileToolBar.add(this.bringToFrontButton);
969 		JMenuItem bringToFrontMenuItem = new JMenuItem(this.bringToFrontAction);
970 		bringToFrontMenuItem.setText("Bring To Front");
971 		bringToFrontMenuItem.setMnemonic('F');
972 		bringToFrontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_MASK));
973 		editMenu.add(bringToFrontMenuItem);
974 
975 		this.sendBackwardAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/backward.png")) {
976 			public void actionPerformed(ActionEvent evt) {
977 				getSelectedGraphicPanel().editSendBackward();
978 			}
979 		};
980 		this.sendBackwardButton = new JButton(this.sendBackwardAction);
981 		this.sendBackwardButton.setMargin(new Insets(1, 1, 1, 1));
982 		this.sendBackwardButton.setToolTipText("Send Backward   Ctrl-Shift-B");
983 		fileToolBar.add(this.sendBackwardButton);
984 		JMenuItem sendBackwardMenuItem = new JMenuItem(this.sendBackwardAction);
985 		sendBackwardMenuItem.setText("Send Backward");
986 		sendBackwardMenuItem.setMnemonic('A');
987 		sendBackwardMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl shift B"));
988 		editMenu.add(sendBackwardMenuItem);
989 
990 		this.bringForwardAction = new AbstractAction(null, ResourceLoader.loadImageIcon("org/convey/images/forward.png")) {
991 			public void actionPerformed(ActionEvent evt) {
992 				getSelectedGraphicPanel().editBringForward();
993 			}
994 		};
995 		this.bringForwardButton = new JButton(this.bringForwardAction);
996 		this.bringForwardButton.setMargin(new Insets(1, 1, 1, 1));
997 		this.bringForwardButton.setToolTipText("Bring Forward   Ctrl-Shift-F");
998 		fileToolBar.add(this.bringForwardButton);
999 		JMenuItem bringForwardMenuItem = new JMenuItem(this.bringForwardAction);
1000 		bringForwardMenuItem.setText("Bring Forward");
1001 		bringForwardMenuItem.setMnemonic('O');
1002 		bringForwardMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl shift F"));
1003 		editMenu.add(bringForwardMenuItem);
1004 
1005 		menuBar.add(editMenu);
1006 		menuBar.add(graphicMenu);
1007 
1008 		super.setJMenuBar(menuBar);
1009 
1010 		ButtonGroup group = new ButtonGroup();
1011 		group.add(this.selectButton);
1012 		group.add(this.scaleButton);
1013 		group.add(this.createTextButton);
1014 		group.add(this.createRectangleButton);
1015 		group.add(this.createEllipseButton);
1016 		group.add(this.createPolylineButton);
1017 		group.add(this.createPolygonButton);
1018 		group.add(this.createQuadCurveButton);
1019 		group.add(this.createCubicCurveButton);
1020 		group.add(this.createFittedCurveButton);
1021 		group.add(this.createFreehandCurveButton);
1022 
1023 		ButtonGroup graphicsMenuGroup = new ButtonGroup();
1024 		graphicsMenuGroup.add((AbstractButton)selectMenuItem);
1025 		graphicsMenuGroup.add((AbstractButton)scaleMenuItem);
1026 		graphicsMenuGroup.add((AbstractButton)rectangleMenuItem);
1027 		graphicsMenuGroup.add((AbstractButton)ellipseMenuItem);
1028 		graphicsMenuGroup.add((AbstractButton)polylineMenuItem);
1029 		graphicsMenuGroup.add((AbstractButton)polygonMenuItem);
1030 		graphicsMenuGroup.add((AbstractButton)quadcurveMenuItem);
1031 		graphicsMenuGroup.add((AbstractButton)cubicMenuItem);
1032 		graphicsMenuGroup.add((AbstractButton)fittedcurveMenuItem);
1033 		graphicsMenuGroup.add((AbstractButton)freehandcurveMenuItem);
1034 
1035 		this.toolBarBox = new Box(BoxLayout.Y_AXIS);
1036 
1037 		Box conveyToolBarBox = new Box(BoxLayout.X_AXIS);
1038 
1039 		conveyToolBarBox.add(conveyToolBar);
1040 		conveyToolBarBox.add(Box.createHorizontalGlue());
1041 
1042 		this.toolBarBox.add(conveyToolBarBox);
1043 
1044 		Box fileToolBarBox = new Box(BoxLayout.X_AXIS);
1045 
1046 		fileToolBarBox.add(fileToolBar);
1047 		fileToolBarBox.add(Box.createHorizontalGlue());
1048 
1049 		this.toolBarBox.add(fileToolBarBox);
1050 
1051 		Box graphicToolBarBox = new Box(BoxLayout.X_AXIS);
1052 
1053 		graphicToolBarBox.add(graphicToolBar);
1054 		graphicToolBarBox.add(Box.createHorizontalGlue());
1055 
1056 		this.toolBarBox.add(graphicToolBarBox);
1057 		super.getContentPane().add(this.toolBarBox, BorderLayout.NORTH);
1058 
1059 		this.tabbedPane = new JTabbedPaneWithCloseIcons();
1060 		this.tabbedPane.addChangeListener(this);
1061 
1062 		this.status = new JTextField();
1063 		this.status.setBackground(Color.lightGray);
1064 		this.status.setForeground(Color.blue);
1065 
1066 		super.getContentPane().add(this.tabbedPane, BorderLayout.CENTER);
1067 		super.getContentPane().add(this.status, BorderLayout.SOUTH);
1068 
1069 		this.selectAction.actionPerformed(new ActionEvent(this, 0, ""));
1070 
1071 		this.newLocal();
1072 
1073 		this.updateButtons();
1074 
1075 		super.show();
1076 	}
1077 
getSelectedGraphicPanel()1078 	public GraphicPanel getSelectedGraphicPanel() {
1079 		CanvasPanel canvasPanel = this.getSelectedCanvasPanel();
1080 		if(canvasPanel != null)
1081 			return canvasPanel.getGraphicPanel();
1082 		return null;
1083 	}
1084 
getSelectedCanvasPanel()1085 	public CanvasPanel getSelectedCanvasPanel() {
1086 		Component component = tabbedPane.getSelectedComponent();
1087 		if(component == null)
1088 			return null;
1089 		return ((CanvasPanel)component);
1090 	}
1091 
1092 	class FlashTimerTask extends TimerTask {
1093 
1094 		private boolean isColored = false;
1095 
1096 		private Color color = null;
1097 
1098 		private JabberCanvasPanel jabberCanvasPanel;
1099 
1100 		private int count = 0;
1101 
FlashTimerTask(JabberCanvasPanel jabberCanvasPanel, Color color)1102 		FlashTimerTask(JabberCanvasPanel jabberCanvasPanel, Color color) {
1103 			this.jabberCanvasPanel = jabberCanvasPanel;
1104 			this.color = color;
1105 		}
1106 
run()1107 		public void run() {
1108 			int index = tabbedPane.indexOfComponent(jabberCanvasPanel);
1109 			if(isColored) {
1110 				tabbedPane.setBackgroundAt(index, null);
1111 				isColored = false;
1112 			} else {
1113 				tabbedPane.setBackgroundAt(index, this.color);
1114 				isColored = true;
1115 				count++;
1116 			}
1117 			if(count > 5 || tabbedPane.getSelectedComponent() == jabberCanvasPanel) {
1118 				if(tabbedPane.getSelectedComponent() == jabberCanvasPanel)
1119 					tabbedPane.setBackgroundAt(index, null);
1120 
1121 				cancel();
1122 			}
1123 		}
1124 
1125 	};
1126 
handleMessage(JabberConveyMessage msg)1127 	public void handleMessage(JabberConveyMessage msg) {
1128 		String threadId = msg.getThreadID();
1129 		String from = msg.getFrom();
1130 		StringTokenizer fromString = new StringTokenizer(from,"@");
1131 		String user = fromString.nextToken();
1132 
1133 		String subj = msg.getSubject();
1134 		if(subj == null)
1135 			subj = "{no subject}";
1136 
1137 		JabberCanvasPanel jabberCanvasPanel;
1138 		if(threadId != null) {
1139 			String key = from + ":" + threadId;
1140 			Object obj = jabberCanvasPanels.get(key);
1141 			if(obj != null)
1142 				jabberCanvasPanel = (JabberCanvasPanel) obj;
1143 			else {
1144 				jabberCanvasPanel = new JabberCanvasPanel(this, msg.getFrom(), threadId, subj);
1145 				jabberCanvasPanel.getGraphicPanel().setHasPen(false);
1146 				jabberCanvasPanel.setInitiator(false);
1147 				jabberCanvasPanels.put(key, jabberCanvasPanel);
1148 
1149 				StringTokenizer strtok = new StringTokenizer(msg.getFrom(), "@");
1150 				this.tabbedPane.addTab(strtok.nextToken(), jabberCanvasPanel,
1151 																		ResourceLoader.loadImageIcon("org/convey/images/no_pen.png"));
1152 				this.tabbedPane.setToolTipTextAt(this.tabbedPane.getComponentCount() - 1,
1153 						msg.getFrom() + "  \"" + subj + "\"");
1154 			}
1155 		} else {
1156 			jabberCanvasPanel = new JabberCanvasPanel(this, msg.getFrom(), "", subj);
1157 
1158 			StringTokenizer strtok = new StringTokenizer(msg.getFrom(), "@");
1159 			this.tabbedPane.addTab(strtok.nextToken(), jabberCanvasPanel,
1160 														ResourceLoader.loadImageIcon("org/convey/images/no_pen.png"));
1161 			this.tabbedPane.setToolTipTextAt(this.tabbedPane.getComponentCount() - 1,
1162 																			 msg.getFrom() + "  \"" + subj + "\"");
1163 		}
1164 		jabberCanvasPanel.handleMessage(msg);
1165 
1166 		boolean foundPane = false;
1167 		for (int i = 0; i < this.tabbedPane.getComponentCount(); i++) {
1168 			if (this.tabbedPane.getComponentAt(i) == jabberCanvasPanel) {
1169 				foundPane = true;
1170 				break;
1171 			}
1172 		}
1173 		if (!foundPane) {
1174 			this.tabbedPane.addTab(user, jabberCanvasPanel,
1175 														ResourceLoader.loadImageIcon("org/convey/images/no_pen.png"));
1176 			this.tabbedPane.setToolTipTextAt(this.tabbedPane.getComponentCount() - 1,
1177 																			 jabberCanvasPanel.getTo()   + "  \""+jabberCanvasPanel.getSubject()+"\"");
1178 		}
1179 
1180 		if(this.tabbedPane.getSelectedComponent() != jabberCanvasPanel) {
1181 			FlashTimerTask task = null;
1182 			if(msg.isPen())
1183 				task = new FlashTimerTask(jabberCanvasPanel, Color.yellow);
1184 			else
1185 				task = new FlashTimerTask(jabberCanvasPanel, Color.green);
1186 			this.timer.scheduleAtFixedRate(task, 0, 500);
1187 		}
1188 
1189 		this.updateButtons();
1190 	}
1191 
newChat(String server, String user, String subject)1192 	public void newChat(String server, String user, String subject) {
1193 		String to = user + "@" + server;
1194 		JabberCanvasPanel jabberCanvasPanel = new JabberCanvasPanel(this, to, subject);
1195 		jabberCanvasPanel.getGraphicPanel().setHasPen(true);
1196 		jabberCanvasPanel.setInitiator(true);
1197 		String threadId = jabberCanvasPanel.getThreadId();
1198 
1199 		this.jabberCanvasPanels.put(to + ":" + threadId, jabberCanvasPanel);
1200 
1201 		this.tabbedPane.addTab(user, jabberCanvasPanel, ResourceLoader.loadImageIcon("org/convey/images/pen.png"));
1202 		this.tabbedPane.setSelectedIndex(this.tabbedPane.getComponentCount() - 1);
1203 		this.tabbedPane.setToolTipTextAt(this.tabbedPane.getComponentCount() - 1,
1204 																		 to + "  \""+subject+"\"");
1205 
1206 		this.updateButtons();
1207 	}
1208 
newLocal()1209 	public void newLocal() {
1210 
1211 		CanvasPanel canvasPanel = new CanvasPanel(this);
1212 		this.tabbedPane.addTab("Untitled", canvasPanel);
1213 		this.tabbedPane.setSelectedIndex(this.tabbedPane.getComponentCount() - 1);
1214 		this.tabbedPane.setToolTipTextAt(this.tabbedPane.getComponentCount() - 1,
1215 																		 "A canvas for your ideas - it's not networked");
1216 
1217 		this.updateButtons();
1218 	}
1219 
getClipboardGraphics()1220 	public Vector getClipboardGraphics() {
1221 		return this.clipboardGraphics;
1222 	}
1223 
updateButtons()1224 	public void updateButtons() {
1225 		boolean hasPen = true;
1226 		if(this.session != null && this.session.getConnection().isConnected()) {
1227 			CanvasPanel canvasPanel = this.getSelectedCanvasPanel();
1228 			if(canvasPanel instanceof JabberCanvasPanel) {
1229 				JabberCanvasPanel jabberCanvasPanel = (JabberCanvasPanel)canvasPanel;
1230 				if(jabberCanvasPanel.getGraphicPanel().hasPen()) {
1231 					this.yieldPenAction.setEnabled(true);
1232 					this.requestPenAction.setEnabled(false);
1233 					this.revokePenAction.setEnabled(false);
1234 				} else {
1235 					hasPen = false;
1236 					this.yieldPenAction.setEnabled(false);
1237 					if(jabberCanvasPanel.isRequest())
1238 						this.requestPenAction.setEnabled(false);
1239 					else
1240 						this.requestPenAction.setEnabled(true);
1241 					if(jabberCanvasPanel.isInitiator() && !jabberCanvasPanel.isRevoke())
1242 						this.revokePenAction.setEnabled(true);
1243 					else
1244 						this.revokePenAction.setEnabled(false);
1245 				}
1246 			} else {
1247 				this.yieldPenAction.setEnabled(false);
1248 				this.requestPenAction.setEnabled(false);
1249 				this.revokePenAction.setEnabled(false);
1250 			}
1251 		}
1252 
1253 		if(this.getSelectedGraphicPanel().graphicCount() > 0) {
1254 			if(hasPen)
1255 				this.clearAction.setEnabled(true);
1256 			else
1257 				this.clearAction.setEnabled(false);
1258 			this.selectAllAction.setEnabled(true);
1259 		} else {
1260 			this.clearAction.setEnabled(false);
1261 			this.selectAllAction.setEnabled(false);
1262 		}
1263 
1264 		switch(this.getSelectedGraphicPanel().selectedGraphicCount()) {
1265 			case 0:
1266 				if(hasPen) {
1267 					this.groupAction.setEnabled(false);
1268 					this.ungroupAction.setEnabled(false);
1269 					this.scaleAction.setEnabled(true);
1270 					this.copyAction.setEnabled(false);
1271 					this.cutAction.setEnabled(false);
1272 					this.copyAction.setEnabled(false);
1273 					this.deleteAction.setEnabled(false);
1274 					this.sendBackwardAction.setEnabled(false);
1275 					this.bringForwardAction.setEnabled(false);
1276 					this.sendToBackAction.setEnabled(false);
1277 					this.bringToFrontAction.setEnabled(false);
1278 				} else {
1279 					this.groupAction.setEnabled(false);
1280 					this.ungroupAction.setEnabled(false);
1281 					this.scaleAction.setEnabled(false);
1282 					this.copyAction.setEnabled(true);
1283 					this.cutAction.setEnabled(false);
1284 					this.copyAction.setEnabled(false);
1285 					this.deleteAction.setEnabled(false);
1286 					this.sendBackwardAction.setEnabled(false);
1287 					this.bringForwardAction.setEnabled(false);
1288 					this.sendToBackAction.setEnabled(false);
1289 					this.bringToFrontAction.setEnabled(false);
1290 				}
1291 				break;
1292 			case 1:
1293 				if(hasPen) {
1294 					this.groupAction.setEnabled(false);
1295 					Graphic selected = this.getSelectedGraphicPanel().selectedGraphic(0);
1296 					this.copyAction.setEnabled(true);
1297 					this.cutAction.setEnabled(true);
1298 					this.deleteAction.setEnabled(true);
1299 					if(selected instanceof GroupGraphic)
1300 						this.ungroupAction.setEnabled(true);
1301 					else
1302 						this.ungroupAction.setEnabled(false);
1303 					this.scaleAction.setEnabled(true);
1304 					this.sendBackwardAction.setEnabled(true);
1305 					this.bringForwardAction.setEnabled(true);
1306 					this.sendToBackAction.setEnabled(true);
1307 					this.bringToFrontAction.setEnabled(true);
1308 				} else {
1309 					this.groupAction.setEnabled(false);
1310 					this.copyAction.setEnabled(true);
1311 					this.cutAction.setEnabled(false);
1312 					this.deleteAction.setEnabled(false);
1313 					this.ungroupAction.setEnabled(false);
1314 					this.scaleAction.setEnabled(false);
1315 					this.sendBackwardAction.setEnabled(false);
1316 					this.bringForwardAction.setEnabled(false);
1317 					this.sendToBackAction.setEnabled(false);
1318 					this.bringToFrontAction.setEnabled(false);
1319 				}
1320 				break;
1321 			default:
1322 				if(hasPen) {
1323 					this.groupAction.setEnabled(true);
1324 					this.ungroupAction.setEnabled(false);
1325 					this.scaleAction.setEnabled(false);
1326 					this.copyAction.setEnabled(true);
1327 					this.cutAction.setEnabled(true);
1328 					this.deleteAction.setEnabled(true);
1329 					this.sendBackwardAction.setEnabled(true);
1330 					this.bringForwardAction.setEnabled(true);
1331 					this.sendToBackAction.setEnabled(true);
1332 					this.bringToFrontAction.setEnabled(true);
1333 				} else {
1334 					this.groupAction.setEnabled(false);
1335 					this.ungroupAction.setEnabled(false);
1336 					this.scaleAction.setEnabled(false);
1337 					this.copyAction.setEnabled(true);
1338 					this.cutAction.setEnabled(false);
1339 					this.deleteAction.setEnabled(false);
1340 					this.sendBackwardAction.setEnabled(false);
1341 					this.bringForwardAction.setEnabled(false);
1342 					this.sendToBackAction.setEnabled(false);
1343 					this.bringToFrontAction.setEnabled(false);
1344 				}
1345 				break;
1346 		}
1347 
1348 		if(!hasPen) {
1349 			this.selectButton.setSelected(true);
1350 			this.selectMenuItem.setSelected(true);
1351 
1352 			this.pasteAction.setEnabled(false);
1353 			this.scaleAction.setEnabled(false);
1354 			this.createRectangleAction.setEnabled(false);
1355 			this.createEllipseAction.setEnabled(false);
1356 			this.createTextAction.setEnabled(false);
1357 			this.createPolygonAction.setEnabled(false);
1358 			this.createPolylineAction.setEnabled(false);
1359 			this.createQuadCurveAction.setEnabled(false);
1360 			this.createCubicCurveAction.setEnabled(false);
1361 			this.createFittedCurveAction.setEnabled(false);
1362 			this.createFreehandCurveAction.setEnabled(false);
1363 		} else {
1364 			if(this.clipboardGraphics.size() > 0)
1365 				this.pasteAction.setEnabled(true);
1366 			this.scaleAction.setEnabled(true);
1367 			this.createRectangleAction.setEnabled(true);
1368 			this.createEllipseAction.setEnabled(true);
1369 			this.createTextAction.setEnabled(true);
1370 			this.createPolygonAction.setEnabled(true);
1371 			this.createPolylineAction.setEnabled(true);
1372 			this.createQuadCurveAction.setEnabled(true);
1373 			this.createCubicCurveAction.setEnabled(true);
1374 			this.createFittedCurveAction.setEnabled(true);
1375 			this.createFreehandCurveAction.setEnabled(true);
1376 		}
1377 	}
1378 
1379 	/**
1380 	 * @todo provide filter for accepting only supported svg tags in convey
1381 	 */
fileOpen()1382 	public void fileOpen() {
1383 		if(fileChooser == null) {
1384 			fileChooser = new JFileChooser();
1385 			fileChooser.setAcceptAllFileFilterUsed(false);
1386 			fileChooser.addChoosableFileFilter(new ExtensionFilter());
1387 		}
1388 		if(fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
1389 			File file = fileChooser.getSelectedFile();
1390 			if(file == null || file.getName().equals("")) {
1391 				JOptionPane.showMessageDialog(this, "Invalid File Name",
1392 																			"Invalid File Name", JOptionPane.ERROR_MESSAGE);
1393 			}
1394 			else {
1395 				CanvasPanel canvasPanel = new CanvasPanel(this);
1396 				this.tabbedPane.addTab(file.getName(), canvasPanel);
1397 				canvasPanel.openSVG(file);
1398 			}
1399 		}
1400 		this.updateButtons();
1401 	}
1402 
fileSaveAs()1403 	public void fileSaveAs() {
1404 		//@todo: implement fileSaveAs
1405 	}
1406 
fileSave()1407 	public void fileSave() {
1408 		if(fileChooser == null) {
1409 			fileChooser = new JFileChooser();
1410 			fileChooser.setAcceptAllFileFilterUsed(false);
1411 			fileChooser.addChoosableFileFilter(new ExtensionFilter());
1412 		}
1413 		int response = fileChooser.showSaveDialog(this);
1414 		if(response == JFileChooser.APPROVE_OPTION) {
1415 			File file = fileChooser.getSelectedFile();
1416 			this.getSelectedCanvasPanel().saveSVG(file);
1417 			if (!this.getSelectedGraphicPanel().canvasPanel.isNetworked) {
1418 				this.tabbedPane.setTitleAt(this.tabbedPane.getSelectedIndex(), file.getName());
1419 			}
1420 		}
1421 	}
1422 
stateChanged(ChangeEvent e)1423 	public void stateChanged(ChangeEvent e) {
1424 		if (this.selectButton.isSelected())
1425 			this.getSelectedGraphicPanel().setState(GraphicPanel.SELECT);
1426 		else if (this.scaleButton.isSelected())
1427 			this.getSelectedGraphicPanel().setState(GraphicPanel.SCALE);
1428 		else if (this.createRectangleButton.isSelected())
1429 			this.getSelectedGraphicPanel().setState(GraphicPanel.RECTANGLE);
1430 		else if (this.createEllipseButton.isSelected())
1431 			this.getSelectedGraphicPanel().setState(GraphicPanel.ELLIPSE);
1432 		else if (this.createPolylineButton.isSelected())
1433 			this.getSelectedGraphicPanel().setState(GraphicPanel.POLYLINE);
1434 		else if (this.createPolygonButton.isSelected())
1435 			this.getSelectedGraphicPanel().setState(GraphicPanel.POLYGON);
1436 		else if (this.createQuadCurveButton.isSelected())
1437 			this.getSelectedGraphicPanel().setState(GraphicPanel.QUADCURVE);
1438 		else if (this.createCubicCurveButton.isSelected())
1439 			this.getSelectedGraphicPanel().setState(GraphicPanel.CUBICCURVE);
1440 		else if (this.createFittedCurveButton.isSelected())
1441 			this.getSelectedGraphicPanel().setState(GraphicPanel.FITTEDCURVE);
1442 		else if (this.createFreehandCurveButton.isSelected())
1443 			this.getSelectedGraphicPanel().setState(GraphicPanel.FREEHANDCURVE);
1444 
1445 		this.setTitle();
1446 
1447 		CanvasPanel canvasPanel = this.getSelectedCanvasPanel();
1448 		if (canvasPanel != null && canvasPanel instanceof JabberCanvasPanel) {
1449 			JabberCanvasPanel jabberCanvasPanel = (JabberCanvasPanel) canvasPanel;
1450 			if (jabberCanvasPanel.isRequest())
1451 				jabberCanvasPanel.doRequest();
1452 		}
1453 
1454 		this.updateButtons();
1455 	}
1456 
setTitle()1457 	public void setTitle() {
1458 		if(this.tabbedPane.getComponentCount() == 0) {
1459 			if(this.session != null)
1460 				super.setTitle("Convey " + "[" + this.from + "]");
1461 			else
1462 				super.setTitle("Convey " + "[disconnected]");
1463 		} else {
1464 			Component component = this.tabbedPane.getSelectedComponent();
1465 			if(component instanceof JabberCanvasPanel) {
1466 				JabberCanvasPanel panel = (JabberCanvasPanel) component;
1467 				String title;
1468 				if(this.session != null)
1469 					title = "Convey [" + this.from + " - " + panel.getTo() + "] " + panel.getSubject();
1470 				else
1471 					title = "Convey [disconnected - " + panel.getTo() + "] " + panel.getSubject();
1472 				super.setTitle(title);
1473 				tabbedPane.setBackgroundAt(this.tabbedPane.indexOfComponent(panel), null);
1474 			} else {
1475 				String title;
1476 				if(this.session != null)
1477 					title = "Convey [" + this.from + "] " + ((CanvasPanel)component).getSavedFilename();
1478 				else
1479 					title = "Convey [disconnected] " + ((CanvasPanel)component).getSavedFilename();
1480 				super.setTitle(title);
1481 			}
1482 		}
1483 	}
1484 
1485 	/**
1486 	 * Display connect dialog and connects to a Jabber server if the user does
1487 	 * not cancel the operation.
1488 	 */
connect()1489 	public void connect() {
1490 		if(this.connectDialog == null) {
1491 			File homeFile;
1492 			File configDirFile;
1493 			File connectFile;
1494 
1495 			String home = System.getProperty("user.home");
1496 			if(home == null)
1497 				home = ".";
1498 			homeFile = new File(home);
1499 
1500 			configDirFile = new File(homeFile, ".convey");
1501 
1502 			if(configDirFile.exists()) {
1503 				connectFile = new File(configDirFile, ".connect");
1504 
1505 				if(connectFile.exists()) {
1506 					try {
1507 						FileInputStream fis = new FileInputStream(connectFile.getPath());
1508 						ObjectInputStream ois = new ObjectInputStream(fis);
1509 						this.connectDialog = new ConnectDialog();
1510 						this.connectDialog.readExternal(ois);
1511 					} catch (Exception e) {
1512 						e.printStackTrace();
1513 					}
1514 				}
1515 			}
1516 		}
1517 
1518 		if(this.connectDialog == null)
1519 			this.connectDialog = new ConnectDialog(this);
1520 
1521 		this.connectDialog.show();
1522 		while(this.connectDialog.getResult() == JOptionPane.OK_OPTION) {
1523 			try {
1524 				this.connect(this.connectDialog.getServer(), this.connectDialog.getUser(),
1525 										 this.connectDialog.getPassword(), this.connectDialog.isNewUser());
1526 				return;
1527 			} catch(JabberMessageException e) {
1528 				JOptionPane.showMessageDialog(this, "User name or password is invalid.",
1529 																			"Unauthorized", JOptionPane.ERROR_MESSAGE);
1530 				this.session = null;
1531 			} catch(UnknownHostException e) {
1532 				JOptionPane.showMessageDialog(this, "Unknown Host.",
1533 																			"Unknown Host", JOptionPane.ERROR_MESSAGE);
1534 				this.session = null;
1535 			} catch(Exception e) {
1536 				e.printStackTrace();
1537 				this.session = null;
1538 			}
1539 
1540 			this.connectDialog.show();
1541 		}
1542 	}
1543 
1544 	/**
1545 	 * Connect to a jabber server as the specified user.
1546 	 *
1547 	 * @todo Modify title bar somehow to indicate connect status and Jabber ID.
1548 	 * @todo Chat history should auto scroll to bottom when a message is added,
1549 	 *       except if the user manually scrolled away from bottom. Then, when the
1550 	 *       user scrolls back to bottom, reset flag.
1551 	 */
connect(String server, String user, String password, boolean newUser)1552 	public void connect(String server, String user, String password, boolean newUser)
1553 			throws JabberMessageException, UnknownHostException,
1554 	ConnectionFailedException, SendMessageFailedException,
1555 	ParseException {
1556 		if(this.session == null) {
1557 			if(server == null || user == null || password == null)
1558 				throw new NullPointerException();
1559 
1560 			if(newUser) {
1561 				Jabber jabber = new Jabber();
1562 				JabberContext context = new JabberContext(null, null, server);
1563 				this.session = jabber.createSession(context);
1564 				this.session.connect(server, 5222);
1565 				JabberUserService userService = this.session.getUserService();
1566 				HashMap fieldMap = userService.getRegisterFields("jabber.org");
1567 				Iterator iter = fieldMap.keySet().iterator();
1568 				fieldMap.put("username", user);
1569 				fieldMap.put("password", password);
1570 				try {
1571 					userService.register("jabber.org", fieldMap);
1572 				} catch(JabberMessageException e) {
1573 					JOptionPane.showMessageDialog(this, e.getErrorMessage(),
1574 																				"Registration Error",
1575 																				JOptionPane.ERROR_MESSAGE);
1576 					this.session.disconnect();
1577 					this.session = null;
1578 					return;
1579 				}
1580 				this.session.disconnect();
1581 			}
1582 
1583 			Jabber jabber = new Jabber();
1584 			DefaultMessageParser parser = new DefaultMessageParser();
1585 			parser.setParser("message", JabberCode.XMLNS_CHAT, "org.convey.JabberConveyMessage");
1586 			JabberContext context = new JabberContext(user, password, server);
1587 			this.session = jabber.createSession(context, parser);
1588 			this.session.connect(server, 5222);
1589 			this.session.getUserService().login();
1590 
1591 			JabberPresenceMessage msg = new JabberPresenceMessage(PresenceCode.TYPE_AVAILABLE);
1592 			msg.setPriority("1");
1593 			msg.setShowState("Online");
1594 			msg.setStatus("Online");
1595 
1596 			String str = msg.encode();
1597 
1598 			this.session.getPresenceService().setToAvailable("Online", null);
1599 
1600 			final ConveyFrame thisConveyFrame = this;
1601 			JabberMessageListener listener = new JabberMessageListener() {
1602 				public void messageReceived(JabberMessageEvent evt) {
1603 					if(evt.getMessageType() == JabberCode.MSG_CHAT) {
1604 						JabberConveyMessage msg = (JabberConveyMessage)evt.getMessage();
1605 						thisConveyFrame.handleMessage(msg);
1606 					}
1607 				}
1608 			};
1609 			this.session.addMessageListener(listener);
1610 
1611 			this.from = user + "@" + server;
1612 			this.setTitle();
1613 			this.disconnectAction.setEnabled(true);
1614 			this.chatAction.setEnabled(true);
1615 			this.connectAction.setEnabled(false);
1616 		}
1617 	}
1618 
1619 	/**
1620 	 * Disconnects from the Jabber server, optionally displaying a prompt for the
1621 	 * user to cancel the disconnect action,
1622 	 *
1623 	 * @return true if the user chose to disconnect; false, otherwise.
1624 	 *
1625 	 * @todo Modify title bar somehow to indicate disconnect status.
1626 	 */
disconnect(boolean prompt)1627 	public boolean disconnect(boolean prompt) {
1628 		if(this.session != null) {
1629 			if(prompt == true) {
1630 				int result = JOptionPane.showConfirmDialog(this,
1631 						"Are you sure you want to disconnect?",
1632 						"Disconnect", JOptionPane.YES_NO_OPTION,
1633 						JOptionPane.PLAIN_MESSAGE);
1634 				if(result == JOptionPane.NO_OPTION)
1635 					return false;
1636 			}
1637 
1638 			try {
1639 				this.session.getPresenceService().setToUnavailable();
1640 			} catch(SendMessageFailedException e) {
1641 				e.printStackTrace();
1642 			}
1643 
1644 			this.session.removeMessageListener(this.listener);
1645 			this.session.disconnect();
1646 			this.session = null;
1647 
1648 			this.setTitle();
1649 			this.chatAction.setEnabled(false);
1650 			this.disconnectAction.setEnabled(false);
1651 			this.connectAction.setEnabled(true);
1652 		}
1653 
1654 		return true;
1655 	}
1656 
1657 	/**
1658 	 * Displays chat receiver dialog box and sets up chat receiver status if the
1659 	 * user does not cancel operation.
1660 	 */
newChat()1661 	public void newChat() {
1662 		if(this.chatDialog == null) {
1663 			File homeFile;
1664 			File configDirFile;
1665 			File chatFile;
1666 
1667 			String home = System.getProperty("user.home");
1668 			if(home == null)
1669 				home = ".";
1670 			homeFile = new File(home);
1671 
1672 			configDirFile = new File(homeFile, ".convey");
1673 
1674 			if(configDirFile.exists()) {
1675 				chatFile = new File(configDirFile, ".chat");
1676 
1677 				if(chatFile.exists()) {
1678 					try {
1679 						FileInputStream fis = new FileInputStream(chatFile.getPath());
1680 						ObjectInputStream ois = new ObjectInputStream(fis);
1681 						this.chatDialog = new ChatDialog();
1682 						this.chatDialog.readExternal(ois);
1683 					} catch (Exception e) {
1684 						e.printStackTrace();
1685 					}
1686 				}
1687 			}
1688 		}
1689 
1690 		if(this.chatDialog == null)
1691 			this.chatDialog = new ChatDialog(this);
1692 
1693 		this.chatDialog.show();
1694 		if(this.chatDialog.getResult() == JOptionPane.OK_OPTION)
1695 			this.newChat(this.chatDialog.getServer(), this.chatDialog.getUser(), this.chatDialog.getSubject());
1696 	}
1697 
getJabberSession()1698 	public JabberSession getJabberSession() {
1699 		return this.session;
1700 	}
1701 
getFrom()1702 	public String getFrom() {
1703 		return this.from;
1704 	}
1705 
getConveyFrame()1706 	public static ConveyFrame getConveyFrame() {
1707 		return ConveyFrame.conveyFrame;
1708 	}
1709 
saveConfig()1710 	public void saveConfig() {
1711 		if(connectDialog != null) {
1712 			try {
1713 				File homeFile;
1714 				File configDirFile;
1715 				File connectFile;
1716 
1717 				String home = System.getProperty("user.home");
1718 				if(home == null)
1719 					home = ".";
1720 				homeFile = new File(home);
1721 
1722 				configDirFile = new File(homeFile, ".convey");
1723 
1724 				if(!configDirFile.exists())
1725 					configDirFile.mkdir();
1726 
1727 				connectFile = new File(configDirFile, ".connect");
1728 
1729 				if(!connectFile.exists())
1730 					connectFile.createNewFile();
1731 
1732 				if(connectFile.canWrite()) {
1733 					FileOutputStream fos = new FileOutputStream(connectFile);
1734 					ObjectOutputStream oos = new ObjectOutputStream(fos);
1735 					this.connectDialog.writeExternal(oos);
1736 				}
1737 			} catch(Exception e) {
1738 				e.printStackTrace();
1739 			}
1740 		}
1741 
1742 		if(chatDialog != null) {
1743 			try {
1744 				File homeFile;
1745 				File configDirFile;
1746 				File chatFile;
1747 
1748 				String home = System.getProperty("user.home");
1749 				if(home == null)
1750 					home = ".";
1751 				homeFile = new File(home);
1752 
1753 				configDirFile = new File(homeFile, ".convey");
1754 
1755 				if(!configDirFile.exists())
1756 					configDirFile.mkdir();
1757 
1758 				chatFile = new File(configDirFile, ".chat");
1759 
1760 				if(!chatFile.exists())
1761 					chatFile.createNewFile();
1762 
1763 				if(chatFile.canWrite()) {
1764 					FileOutputStream fos = new FileOutputStream(chatFile);
1765 					ObjectOutputStream oos = new ObjectOutputStream(fos);
1766 					this.chatDialog.writeExternal(oos);
1767 				}
1768 			} catch(Exception e) {
1769 				e.printStackTrace();
1770 			}
1771 		}
1772 	}
1773 
getFillColor()1774 	public Color getFillColor() {
1775 		return this.fillColorComboBox.getSelectedColor();
1776 	}
1777 
getStrokeColor()1778 	public Color getStrokeColor() {
1779 		return this.strokeColorComboBox.getSelectedColor();
1780 	}
1781 
getTextColor()1782 	public Color getTextColor() {
1783 		return this.textColorComboBox.getSelectedColor();
1784 	}
1785 
isAutoSend()1786 	public boolean isAutoSend() {
1787 		return this.autoSendButton.isSelected();
1788 	}
1789 
changePenIcon(JabberCanvasPanel jabberCanvasPanel, boolean value)1790 	public void changePenIcon(JabberCanvasPanel jabberCanvasPanel, boolean value) {
1791 		int index = this.tabbedPane.indexOfComponent(jabberCanvasPanel);
1792 		if(index != -1) {
1793 			if(value)
1794 				this.tabbedPane.setIconAt(index, new CloseTabIcon(ResourceLoader.loadImageIcon("org/convey/images/pen.png")));
1795 			else
1796 				this.tabbedPane.setIconAt(index, new CloseTabIcon(ResourceLoader.loadImageIcon("org/convey/images/no_pen.png")));
1797 		}
1798 	}
1799 
1800 	/**
1801 	 * Main method invoked when Convey client application starts. Sets up system
1802 	 * look and feel.
1803 	 */
main(String[] args)1804 	public static void main(String[] args) {
1805 		try {
1806 			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1807 		} catch(Exception e) {
1808 			e.printStackTrace();
1809 		}
1810 		ConveyFrame.conveyFrame = new ConveyFrame();
1811 	}
1812 
1813 }