View Javadoc
1   /**
2    * The contents of this file are subject to the Mozilla Public License Version 1.1
3    * (the "License"); you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
5    * Software distributed under the License is distributed on an "AS IS" basis,
6    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
7    * specific language governing rights and limitations under the License.
8    *
9    * The Original Code is ""  Description:
10   * ""
11   *
12   * The Initial Developer of the Original Code is University Health Network. Copyright (C)
13   * 2001.  All Rights Reserved.
14   *
15   * Contributor(s): ______________________________________.
16   *
17   * Alternatively, the contents of this file may be used under the terms of the
18   * GNU General Public License (the  "GPL"), in which case the provisions of the GPL are
19   * applicable instead of those above.  If you wish to allow use of your version of this
20   * file only under the terms of the GPL and not to allow others to use your version
21   * of this file under the MPL, indicate your decision by deleting  the provisions above
22   * and replace  them with the notice and other provisions required by the GPL License.
23   * If you do not delete the provisions above, a recipient may use your version of
24   * this file under either the MPL or the GPL.
25   */
26  package ca.uhn.hl7v2.testpanel.ui;
27  
28  import java.awt.BorderLayout;
29  import java.awt.Color;
30  import java.awt.Component;
31  import java.awt.Dimension;
32  import java.awt.Frame;
33  import java.awt.GridBagConstraints;
34  import java.awt.GridBagLayout;
35  import java.awt.Image;
36  import java.awt.Insets;
37  import java.awt.Point;
38  import java.awt.Rectangle;
39  import java.awt.Toolkit;
40  import java.awt.event.ActionEvent;
41  import java.awt.event.ActionListener;
42  import java.awt.event.KeyEvent;
43  import java.awt.event.WindowAdapter;
44  import java.awt.event.WindowEvent;
45  import java.beans.PropertyChangeEvent;
46  import java.beans.PropertyChangeListener;
47  import java.util.ArrayList;
48  import java.util.List;
49  
50  import javax.swing.DefaultListCellRenderer;
51  import javax.swing.DefaultListModel;
52  import javax.swing.ImageIcon;
53  import javax.swing.JButton;
54  import javax.swing.JFrame;
55  import javax.swing.JLabel;
56  import javax.swing.JList;
57  import javax.swing.JMenu;
58  import javax.swing.JMenuBar;
59  import javax.swing.JMenuItem;
60  import javax.swing.JPanel;
61  import javax.swing.JScrollPane;
62  import javax.swing.JSeparator;
63  import javax.swing.JSplitPane;
64  import javax.swing.JToolBar;
65  import javax.swing.KeyStroke;
66  import javax.swing.SwingConstants;
67  import javax.swing.event.ListSelectionEvent;
68  import javax.swing.event.ListSelectionListener;
69  
70  import org.apache.commons.lang.StringUtils;
71  import org.apache.commons.lang.Validate;
72  import org.slf4j.Logger;
73  import org.slf4j.LoggerFactory;
74  
75  import ca.uhn.hl7v2.testpanel.controller.Controller;
76  import ca.uhn.hl7v2.testpanel.controller.Hl7V2FileDiffController;
77  import ca.uhn.hl7v2.testpanel.controller.Hl7V2FileSortController;
78  import ca.uhn.hl7v2.testpanel.controller.Prefs;
79  import ca.uhn.hl7v2.testpanel.model.MessagesList;
80  import ca.uhn.hl7v2.testpanel.model.conn.AbstractConnection;
81  import ca.uhn.hl7v2.testpanel.model.conn.AbstractConnection.StatusEnum;
82  import ca.uhn.hl7v2.testpanel.model.conn.InboundConnection;
83  import ca.uhn.hl7v2.testpanel.model.conn.InboundConnectionList;
84  import ca.uhn.hl7v2.testpanel.model.conn.OutboundConnection;
85  import ca.uhn.hl7v2.testpanel.model.conn.OutboundConnectionList;
86  import ca.uhn.hl7v2.testpanel.model.msg.Hl7V2MessageCollection;
87  import ca.uhn.hl7v2.testpanel.util.ScreenBoundsUtil;
88  import ca.uhn.hl7v2.testpanel.util.SwingLogAppender;
89  
90  /**
91   * This is the main outer window for the TestPanel
92   */
93  public class TestPanelWindow implements IDestroyable {
94  
95  	private Hl7V2FileDiffController myHl7V2FileDiff;
96  	private Controller myController;
97  	private JFrame myframe;
98  	private JList myMessagesList;
99  	private MyMessagesListModel myMessagesListModel;
100 	private final PropertyChangeListener myMessageDescriptionListener;
101 	private MyOutboundConnectionsListModel myOutboundConnectionsListModel;
102 	private MyInboundConnectionsListModel myInboundConnectionsListModel;
103 	private JButton myMsgSaveButton;
104 	private PropertyChangeListener myOutboundConnectionsListListener;
105 	private PropertyChangeListener myInboundConnectionsListListener;
106 	private JButton myDeleteOutboundConnectionButton;
107 	private JButton myAddInboundConnectionButton;
108 	private PropertyChangeListener myPanelTitleListener;
109 	private AboutDialog myAboutDialog;
110 	private JButton myStartOneOutboundButton;
111 	private JButton myStartAllOutboundButton;
112 	private JButton myStopAllOutboundButton;
113 	private Hl7V2FileSortController myHl7V2FileSort;
114 
115 	/**
116 	 * Create the application.
117 	 */
118 	public TestPanelWindow(Controller theController) {
119 		myController = theController;
120 
121 		myMessageDescriptionListener = new MyMessageDescriptionListener();
122 		new SwingLogAppender();
123 
124 		initialize();
125 		initializeLocal();
126 		initWindowPosition();
127 
128 		if (myController.getLeftSelectedItem() instanceof Hl7V2MessageCollection) {
129 			myMessagesList.setSelectedValue(myController.getLeftSelectedItem(), true);
130 		} else if (myController.getLeftSelectedItem() instanceof InboundConnection) {
131 			myInboundConnectionsList.setSelectedValue(myController.getLeftSelectedItem(), true);
132 		} else if (myController.getLeftSelectedItem() instanceof OutboundConnection) {
133 			myOutboundConnectionsList.setSelectedValue(myController.getLeftSelectedItem(), true);
134 		} else {
135 			ourLog.warn("Unknown type is selected: {}", myController.getLeftSelectedItem());
136 		}
137 
138 		myPanelTitleListener = new PropertyChangeListener() {
139 			public void propertyChange(PropertyChangeEvent theEvt) {
140 				updateWindowTitle();
141 			}
142 		};
143 
144 
145 	}
146 
147 	
148 	/**
149 	 * @return the controller
150 	 */
151 	public Controller getController() {
152 		return myController;
153 	}
154 
155 	private void initWindowPosition() {
156 		if (Prefs.getInstance().getWindowMaximized()) {
157 			myframe.setExtendedState(JFrame.MAXIMIZED_BOTH);
158 			return;
159 		}
160 		
161 		Rectangle screenBounds = ScreenBoundsUtil.getScreenBounds(myframe);
162 		int maxWidth = screenBounds.width;
163 		int maxHeight = screenBounds.height;
164 		int width;
165 		int height;
166 
167 		Point position = Prefs.getInstance().getWindowPosition();
168 		Dimension dimension = Prefs.getInstance().getWindowDimension();
169 		if (dimension.width > 600 && dimension.height > 500) {
170 			if (position.x >= 0 && position.y >= 0) {
171 				if (dimension.width + position.x < maxWidth) {
172 					if (dimension.height + position.y < maxHeight) {
173 						ourLog.info("Restoring window size to {} and location to {}", dimension, position);
174 						myframe.setLocation(position);
175 						myframe.setSize(dimension);
176 						return;
177 					}
178 				}
179 			}
180 		}
181 		
182 		width = (int) (maxWidth * 0.7);
183 		if (width < 1024) {
184 			width = maxWidth;
185 		}
186 		width = Math.min(width, 1600);
187 
188 		height = (int) (maxHeight * 0.7);
189 		if (height < 600) {
190 			height = maxHeight;
191 		}
192 		height = Math.min(height, 1000);
193 
194 		if (width == maxWidth && height == maxHeight) {
195 			ourLog.info("Maximizing window");
196 			myframe.setExtendedState(Frame.MAXIMIZED_BOTH);
197 		} else {
198 			ourLog.info("Setting window size to {} x {}", width, height);
199 			myframe.setSize(width, height);
200 		}
201 
202 		myframe.setLocationByPlatform(true);
203 	}
204 
205 	private void updateWindowTitle() {
206 		String title = myMainPanel != null ? myMainPanel.getWindowTitle() : null;
207 		if (StringUtils.isNotBlank(title)) {
208 			myframe.setTitle("HAPI TestPanel " + myController.getAppVersionString() + " - " + title);
209 		} else {
210 			myframe.setTitle("HAPI TestPanel " + myController.getAppVersionString());
211 		}
212 	}
213 
214 	public void clearMessagesListSelection() {
215 		myMessagesList.clearSelection();
216 	}
217 
218 	private void updateLeftToolbarButtons() {
219 
220 		boolean isMsg = (myController.getLeftSelectedItem() instanceof Hl7V2MessageCollection);
221 		myMsgSaveButton.setEnabled(isMsg);
222 		myDeleteMessageButton.setEnabled(isMsg);
223 		mySaveMenuItem.setEnabled(isMsg);
224 		mySaveAsMenuItem.setEnabled(isMsg);
225 		myRevertToSavedMenuItem.setEnabled(leftMessageHasSaveFilename());
226 		
227 		
228 		if (myController.getLeftSelectedItem() instanceof OutboundConnection) {
229 			myDeleteOutboundConnectionButton.setEnabled(true);
230 			myStartOneOutboundButton.setEnabled(true);
231 		} else {
232 			myDeleteOutboundConnectionButton.setEnabled(false);
233 			myStartOneOutboundButton.setEnabled(false);
234 		}
235 
236 		if (myController.getLeftSelectedItem() instanceof InboundConnection) {
237 			myDeleteInboundConnectionButton.setEnabled(true);
238 			myStartOneInboundButton.setEnabled(true);
239 		} else {
240 			myDeleteInboundConnectionButton.setEnabled(false);
241 			myStartOneInboundButton.setEnabled(false);
242 		}
243 
244 	}
245 	
246 	private boolean leftMessageHasSaveFilename() {
247 		if (myController.getLeftSelectedItem() instanceof Hl7V2MessageCollection) {
248 			Hl7V2MessageCollection left = (Hl7V2MessageCollection) myController.getLeftSelectedItem();
249 			return StringUtils.isNotBlank(left.getSaveFileName());
250 		}
251 		return false;
252 	}
253 
254 	private void updateLeftToolbarInboundStatusButtons() {
255 		boolean haveStarted = false;
256 		boolean haveStopped = false;
257 		for (InboundConnection next : myController.getInboundConnectionList().getConnections()) {
258 			switch (next.getStatus()) {
259 			case FAILED:
260 			case STOPPED:
261 				haveStopped = true;
262 				break;
263 			case STARTED:
264 			case TRYING_TO_START:
265 				haveStarted = true;
266 				break;
267 								
268 			}
269 		}
270 		
271 		myStopAllInboundButton.setEnabled(haveStarted);
272 		myStartAllInboundButton.setEnabled(haveStopped);
273 	}
274 
275 	private void updateLeftToolbarOutboundStatusButtons() {
276 		boolean haveStarted = false;
277 		boolean haveStopped = false;
278 		for (OutboundConnection next : myController.getOutboundConnectionList().getConnections()) {
279 			switch (next.getStatus()) {
280 			case FAILED:
281 			case STOPPED:
282 				haveStopped = true;
283 				break;
284 			case STARTED:
285 			case TRYING_TO_START:
286 				haveStarted = true;
287 				break;
288 								
289 			}
290 		}
291 		
292 		myStopAllOutboundButton.setEnabled(haveStarted);
293 		myStartAllOutboundButton.setEnabled(haveStopped);
294 	}
295 
296 	/**
297 	 * Initialize the contents of the frame.
298 	 */
299 	private void initialize() {
300 		myframe = new JFrame();
301 		myframe.setVisible(false);
302 		
303 		List<Image> l = new ArrayList<Image>();
304 		l.add(Toolkit.getDefaultToolkit().getImage(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/hapi_16.png")));
305 		l.add(Toolkit.getDefaultToolkit().getImage(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/hapi_64.png")));
306 		
307 		myframe.setIconImages(l);
308 		myframe.setTitle("HAPI TestPanel");
309 		myframe.setBounds(100, 100, 796, 603);
310 		myframe.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
311 		myframe.addWindowListener(new WindowAdapter() {
312 			@Override
313 			public void windowClosing(WindowEvent theE) {
314 				myController.close();
315 			}
316 		});
317 
318 		JMenuBar menuBar = new JMenuBar();
319 		myframe.setJMenuBar(menuBar);
320 
321 		JMenu mnFile = new JMenu("File");
322 		mnFile.setMnemonic('f');
323 		menuBar.add(mnFile);
324 
325 		JMenuItem mntmExit = new JMenuItem("Exit");
326 		mntmExit.addActionListener(new ActionListener() {
327 			public void actionPerformed(ActionEvent arg0) {
328 				myController.close();
329 			}
330 		});
331 
332 		JMenuItem mntmNewMessage = new JMenuItem("New Message...");
333 		mntmNewMessage.addActionListener(new ActionListener() {
334 			public void actionPerformed(ActionEvent e) {
335 				myController.addMessage();
336 			}
337 		});
338 		mntmNewMessage.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/message_hl7.png")));
339 		mnFile.add(mntmNewMessage);
340 
341 		mySaveMenuItem = new JMenuItem("Save");
342 		mySaveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
343 		mySaveMenuItem.addActionListener(new ActionListener() {
344 			public void actionPerformed(ActionEvent e) {
345 				doSaveMessages();
346 			}
347 		});
348 		mnFile.add(mySaveMenuItem);
349 
350 		mySaveAsMenuItem = new JMenuItem("Save As...");
351 		mySaveAsMenuItem.addActionListener(new ActionListener() {
352 			public void actionPerformed(ActionEvent e) {
353 				doSaveMessagesAs();
354 			}
355 		});
356 		mnFile.add(mySaveAsMenuItem);
357 		
358 		mymenuItem_3 = new JMenuItem("Open");
359 		mymenuItem_3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
360 		mymenuItem_3.addActionListener(new ActionListener() {
361 			public void actionPerformed(ActionEvent e) {
362 				myController.openMessages();
363 			}
364 		});
365 		
366 		myRevertToSavedMenuItem = new JMenuItem("Revert to Saved");
367 		myRevertToSavedMenuItem.addActionListener(new ActionListener() {
368 			public void actionPerformed(ActionEvent e) {
369 				myController.revertMessage((Hl7V2MessageCollection) myController.getLeftSelectedItem());
370 			}
371 		});
372 		mnFile.add(myRevertToSavedMenuItem);
373 		mnFile.add(mymenuItem_3);
374 		
375 		myRecentFilesMenu = new JMenu("Open Recent");
376 		mnFile.add(myRecentFilesMenu);
377 
378 		JSeparator separator = new JSeparator();
379 		mnFile.add(separator);
380 		mnFile.add(mntmExit);
381 
382 		JMenu mnNewMenu = new JMenu("View");
383 		mnNewMenu.setMnemonic('v');
384 		menuBar.add(mnNewMenu);
385 
386 		myShowLogConsoleMenuItem = new JMenuItem("Show Log Console");
387 		myShowLogConsoleMenuItem.addActionListener(new ActionListener() {
388 			public void actionPerformed(ActionEvent e) {
389 				Prefs.getInstance().setShowLogConsole(!Prefs.getInstance().getShowLogConsole());
390 				updateLogScrollPaneVisibility();
391 				myframe.validate();
392 			}
393 		});
394 		mnNewMenu.add(myShowLogConsoleMenuItem);
395 		
396 		mymenu_1 = new JMenu("Test");
397 		menuBar.add(mymenu_1);
398 		
399 		mymenuItem_1 = new JMenuItem("Populate TestPanel with Sample Message and Connections...");
400 		mymenuItem_1.addActionListener(new ActionListener() {
401 			public void actionPerformed(ActionEvent e) {
402 				myController.populateWithSampleMessageAndConnections();
403 			}
404 		});
405 		mymenu_1.add(mymenuItem_1);
406 		
407 		mymenu_3 = new JMenu("Tools");
408 		menuBar.add(mymenu_3);
409 		
410 		mnHl7V2FileDiff = new JMenuItem("HL7 v2 File Diff...");
411 		mnHl7V2FileDiff.addActionListener(new ActionListener() {
412 
413 			public void actionPerformed(ActionEvent e) {
414 				if (myHl7V2FileDiff == null) {
415 					myHl7V2FileDiff = new Hl7V2FileDiffController(myController);
416 				}
417 				myHl7V2FileDiff.show();
418 			}
419 		});
420 		mymenu_3.add(mnHl7V2FileDiff);
421 		
422 		mymenuItem_5 = new JMenuItem("HL7 v2 File Sort...");
423 		mymenuItem_5.addActionListener(new ActionListener() {
424 			public void actionPerformed(ActionEvent e) {
425 				if (myHl7V2FileSort == null) {
426 					myHl7V2FileSort = new Hl7V2FileSortController(myController);
427 				}
428 				myHl7V2FileSort.show();
429 			}
430 		});
431 		mymenu_3.add(mymenuItem_5);
432 		
433 		mymenu_2 = new JMenu("Conformance");
434 		menuBar.add(mymenu_2);
435 		
436 		mymenuItem_2 = new JMenuItem("Profiles and Tables...");
437 		mymenuItem_2.addActionListener(new ActionListener() {
438 			public void actionPerformed(ActionEvent e) {
439 				myController.showProfilesAndTablesEditor();
440 			}
441 		});
442 		mymenu_2.add(mymenuItem_2);
443 		
444 		mymenu = new JMenu("Help");
445 		mymenu.setMnemonic('H');
446 		menuBar.add(mymenu);
447 		
448 		mymenuItem = new JMenuItem("About HAPI TestPanel...");
449 		mymenuItem.addActionListener(new ActionListener() {
450 			public void actionPerformed(ActionEvent e) {
451 				showAboutDialog();
452 			}
453 		});
454 		mymenuItem.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/hapi_16.png")));
455 		mymenu.add(mymenuItem);
456 		
457 		mymenuItem_4 = new JMenuItem("Licenses...");
458 		mymenuItem_4.addActionListener(new ActionListener() {
459 			public void actionPerformed(ActionEvent e) {
460 				new LicensesDialog().setVisible(true);
461 			}
462 		});
463 		mymenu.add(mymenuItem_4);
464 		myframe.getContentPane().setLayout(new BorderLayout(0, 0));
465 
466 		JSplitPane outerSplitPane = new JSplitPane();
467 		outerSplitPane.setBorder(null);
468 		myframe.getContentPane().add(outerSplitPane);
469 
470 		JSplitPane leftSplitPane = new JSplitPane();
471 		leftSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
472 		outerSplitPane.setLeftComponent(leftSplitPane);
473 
474 		JPanel messagesPanel = new JPanel();
475 		leftSplitPane.setLeftComponent(messagesPanel);
476 		GridBagLayout gbl_messagesPanel = new GridBagLayout();
477 		gbl_messagesPanel.columnWidths = new int[] { 110, 0 };
478 		gbl_messagesPanel.rowHeights = new int[] { 20, 30, 118, 0, 0 };
479 		gbl_messagesPanel.columnWeights = new double[] { 1.0, Double.MIN_VALUE };
480 		gbl_messagesPanel.rowWeights = new double[] { 0.0, 0.0, 100.0, 1.0, Double.MIN_VALUE };
481 		messagesPanel.setLayout(gbl_messagesPanel);
482 
483 		JLabel lblMessages = new JLabel("Messages");
484 		GridBagConstraints gbc_lblMessages = new GridBagConstraints();
485 		gbc_lblMessages.insets = new Insets(0, 0, 5, 0);
486 		gbc_lblMessages.gridx = 0;
487 		gbc_lblMessages.gridy = 0;
488 		messagesPanel.add(lblMessages, gbc_lblMessages);
489 
490 		JToolBar messagesToolBar = new JToolBar();
491 		messagesToolBar.setFloatable(false);
492 		messagesToolBar.setRollover(true);
493 		messagesToolBar.setAlignmentX(Component.LEFT_ALIGNMENT);
494 		GridBagConstraints gbc_messagesToolBar = new GridBagConstraints();
495 		gbc_messagesToolBar.insets = new Insets(0, 0, 5, 0);
496 		gbc_messagesToolBar.weightx = 1.0;
497 		gbc_messagesToolBar.anchor = GridBagConstraints.NORTHWEST;
498 		gbc_messagesToolBar.gridx = 0;
499 		gbc_messagesToolBar.gridy = 1;
500 		messagesPanel.add(messagesToolBar, gbc_messagesToolBar);
501 
502 		JButton msgOpenButton = new JButton("");
503 		msgOpenButton.addActionListener(new ActionListener() {
504 			public void actionPerformed(ActionEvent e) {
505 				myController.openMessages();
506 			}
507 		});
508 
509 		myAddMessageButton = new JButton("");
510 		myAddMessageButton.addActionListener(new ActionListener() {
511 			public void actionPerformed(ActionEvent e) {
512 				myController.addMessage();
513 			}
514 		});
515 		myAddMessageButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/add.png")));
516 		myAddMessageButton.setToolTipText("New Message");
517 		myAddMessageButton.setBorderPainted(false);
518 		myAddMessageButton.addMouseListener(new HoverButtonMouseAdapter(myAddMessageButton));
519 		messagesToolBar.add(myAddMessageButton);
520 
521 		myDeleteMessageButton = new JButton("");
522 		myDeleteMessageButton.setToolTipText("Close Selected Message");
523 		myDeleteMessageButton.addActionListener(new ActionListener() {
524 			public void actionPerformed(ActionEvent e) {
525 				myController.closeMessage((Hl7V2MessageCollection) myController.getLeftSelectedItem());
526 			}
527 		});
528 		myDeleteMessageButton.setBorderPainted(false);
529 		myDeleteMessageButton.addMouseListener(new HoverButtonMouseAdapter(myDeleteMessageButton));
530 		myDeleteMessageButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/close.png")));
531 		messagesToolBar.add(myDeleteMessageButton);
532 		msgOpenButton.setBorderPainted(false);
533 		msgOpenButton.setToolTipText("Open Messages from File");
534 		msgOpenButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/open.png")));
535 		msgOpenButton.addMouseListener(new HoverButtonMouseAdapter(msgOpenButton));
536 		messagesToolBar.add(msgOpenButton);
537 
538 		myMsgSaveButton = new JButton("");
539 		myMsgSaveButton.addActionListener(new ActionListener() {
540 			public void actionPerformed(ActionEvent e) {
541 				doSaveMessages();
542 			}
543 		});
544 		myMsgSaveButton.setBorderPainted(false);
545 		myMsgSaveButton.setToolTipText("Save Selected Messages to File");
546 		myMsgSaveButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/save.png")));
547 		myMsgSaveButton.addMouseListener(new HoverButtonMouseAdapter(myMsgSaveButton));
548 		messagesToolBar.add(myMsgSaveButton);
549 
550 		myMessagesList = new JList();
551 		myMessagesList.addListSelectionListener(new ListSelectionListener() {
552 			public void valueChanged(ListSelectionEvent e) {
553 				if (myMessagesList.getSelectedIndex() >= 0) {
554 					ourLog.debug("New messages selection " + myMessagesList.getSelectedIndex());
555 					myController.setLeftSelectedItem(myMessagesList.getSelectedValue());
556 					myOutboundConnectionsList.clearSelection();
557 					myOutboundConnectionsList.repaint();
558 					myInboundConnectionsList.clearSelection();
559 					myInboundConnectionsList.repaint();
560 				}
561 				updateLeftToolbarButtons();
562 			}
563 		});
564 		GridBagConstraints gbc_MessagesList = new GridBagConstraints();
565 		gbc_MessagesList.gridheight = 2;
566 		gbc_MessagesList.weightx = 1.0;
567 		gbc_MessagesList.weighty = 1.0;
568 		gbc_MessagesList.fill = GridBagConstraints.BOTH;
569 		gbc_MessagesList.gridx = 0;
570 		gbc_MessagesList.gridy = 2;
571 		messagesPanel.add(myMessagesList, gbc_MessagesList);
572 
573 		JPanel connectionsPanel = new JPanel();
574 		leftSplitPane.setRightComponent(connectionsPanel);
575 		GridBagLayout gbl_connectionsPanel = new GridBagLayout();
576 		gbl_connectionsPanel.columnWidths = new int[] { 194, 0 };
577 		gbl_connectionsPanel.rowHeights = new int[] { 0, 30, 0, 0, 0, 0, 0 };
578 		gbl_connectionsPanel.columnWeights = new double[] { 1.0, Double.MIN_VALUE };
579 		gbl_connectionsPanel.rowWeights = new double[] { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, Double.MIN_VALUE };
580 		connectionsPanel.setLayout(gbl_connectionsPanel);
581 
582 		JLabel lblConnections = new JLabel("Sending Connections");
583 		lblConnections.setHorizontalAlignment(SwingConstants.CENTER);
584 		GridBagConstraints gbc_lblConnections = new GridBagConstraints();
585 		gbc_lblConnections.insets = new Insets(0, 0, 5, 0);
586 		gbc_lblConnections.anchor = GridBagConstraints.NORTH;
587 		gbc_lblConnections.fill = GridBagConstraints.HORIZONTAL;
588 		gbc_lblConnections.gridx = 0;
589 		gbc_lblConnections.gridy = 0;
590 		connectionsPanel.add(lblConnections, gbc_lblConnections);
591 
592 		JToolBar toolBar = new JToolBar();
593 		toolBar.setFloatable(false);
594 		GridBagConstraints gbc_toolBar = new GridBagConstraints();
595 		gbc_toolBar.insets = new Insets(0, 0, 5, 0);
596 		gbc_toolBar.anchor = GridBagConstraints.NORTH;
597 		gbc_toolBar.fill = GridBagConstraints.HORIZONTAL;
598 		gbc_toolBar.gridx = 0;
599 		gbc_toolBar.gridy = 1;
600 		connectionsPanel.add(toolBar, gbc_toolBar);
601 
602 		myAddConnectionButton = new JButton("");
603 		myAddConnectionButton.addActionListener(new ActionListener() {
604 			public void actionPerformed(ActionEvent e) {
605 				myController.addOutboundConnection();
606 			}
607 		});
608 		myAddConnectionButton.setBorderPainted(false);
609 		myAddConnectionButton.addMouseListener(new HoverButtonMouseAdapter(myAddConnectionButton));
610 		myAddConnectionButton.setBorder(null);
611 		myAddConnectionButton.setToolTipText("New Connection");
612 		myAddConnectionButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/add.png")));
613 		toolBar.add(myAddConnectionButton);
614 
615 		myDeleteOutboundConnectionButton = new JButton("");
616 		myDeleteOutboundConnectionButton.setToolTipText("Delete Selected Connection");
617 		myDeleteOutboundConnectionButton.addActionListener(new ActionListener() {
618 			public void actionPerformed(ActionEvent e) {
619 				if (myController.getLeftSelectedItem() instanceof OutboundConnection) {
620 					myController.removeOutboundConnection((OutboundConnection) myController.getLeftSelectedItem());
621 				}
622 			}
623 		});
624 		myDeleteOutboundConnectionButton.setBorderPainted(false);
625 		myDeleteOutboundConnectionButton.addMouseListener(new HoverButtonMouseAdapter(myDeleteOutboundConnectionButton));
626 		myDeleteOutboundConnectionButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/delete.png")));
627 		toolBar.add(myDeleteOutboundConnectionButton);
628 
629 		myStartOneOutboundButton = new JButton("");
630 		myStartOneOutboundButton.addActionListener(new ActionListener() {
631 			public void actionPerformed(ActionEvent e) {
632 				if (myController.getLeftSelectedItem() instanceof OutboundConnection) {
633 					myController.startOutboundConnection((OutboundConnection) myController.getLeftSelectedItem());
634 				}
635 			}
636 		});
637 		myStartOneOutboundButton.setBorderPainted(false);
638 		myStartOneOutboundButton.setToolTipText("Start selected connection");
639 		myStartOneOutboundButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/start_one.png")));
640 		myStartOneOutboundButton.addMouseListener(new HoverButtonMouseAdapter(myStartOneOutboundButton));
641 		toolBar.add(myStartOneOutboundButton);
642 		
643 		myStartAllOutboundButton = new JButton("");
644 		myStartAllOutboundButton.setBorderPainted(false);
645 		myStartAllOutboundButton.setToolTipText("Start all sending connections");
646 		myStartAllOutboundButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/start_all.png")));
647 		myStartAllOutboundButton.addMouseListener(new HoverButtonMouseAdapter(myStartAllOutboundButton));
648 		myStartAllOutboundButton.addActionListener(new ActionListener() {
649 			public void actionPerformed(ActionEvent theE) {
650 				myController.startAllOutboundConnections();
651 			}
652 		});
653 		toolBar.add(myStartAllOutboundButton);
654 		
655 		myStopAllOutboundButton = new JButton("");
656 		myStopAllOutboundButton.addActionListener(new ActionListener() {
657 			public void actionPerformed(ActionEvent e) {
658 				myController.stopAllOutboundConnections();
659 			}
660 		});
661 		myStopAllOutboundButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/stop_all.png")));
662 		myStopAllOutboundButton.setToolTipText("Stop all sending connections");
663 		myStopAllOutboundButton.setBorderPainted(false);
664 		myStopAllOutboundButton.addMouseListener(new HoverButtonMouseAdapter(myStopAllOutboundButton));
665 		toolBar.add(myStopAllOutboundButton);
666 		
667 		JScrollPane scrollPane = new JScrollPane();
668 		scrollPane.setBorder(null);
669 		GridBagConstraints gbc_scrollPane = new GridBagConstraints();
670 		gbc_scrollPane.fill = GridBagConstraints.BOTH;
671 		gbc_scrollPane.insets = new Insets(0, 0, 5, 0);
672 		gbc_scrollPane.gridx = 0;
673 		gbc_scrollPane.gridy = 2;
674 		connectionsPanel.add(scrollPane, gbc_scrollPane);
675 
676 		myOutboundConnectionsList = new JList();
677 		myOutboundConnectionsList.setBorder(null);
678 		myOutboundConnectionsList.addListSelectionListener(new ListSelectionListener() {
679 			public void valueChanged(ListSelectionEvent e) {
680 				if (myOutboundConnectionsList.getSelectedIndex() >= 0) {
681 					ourLog.debug("New outbound connection selection " + myOutboundConnectionsList.getSelectedIndex());
682 					myController.setLeftSelectedItem(myOutboundConnectionsList.getSelectedValue());
683 					myMessagesList.clearSelection();
684 					myMessagesList.repaint();
685 					myInboundConnectionsList.clearSelection();
686 					myInboundConnectionsList.repaint();
687 				}
688 				updateLeftToolbarButtons();
689 			}
690 		});
691 		scrollPane.setViewportView(myOutboundConnectionsList);
692 
693 		JLabel lblReceivingConnections = new JLabel("Receiving Connections");
694 		lblReceivingConnections.setHorizontalAlignment(SwingConstants.CENTER);
695 		GridBagConstraints gbc_lblReceivingConnections = new GridBagConstraints();
696 		gbc_lblReceivingConnections.insets = new Insets(0, 0, 5, 0);
697 		gbc_lblReceivingConnections.gridx = 0;
698 		gbc_lblReceivingConnections.gridy = 3;
699 		connectionsPanel.add(lblReceivingConnections, gbc_lblReceivingConnections);
700 
701 		JToolBar toolBar_1 = new JToolBar();
702 		toolBar_1.setFloatable(false);
703 		GridBagConstraints gbc_toolBar_1 = new GridBagConstraints();
704 		gbc_toolBar_1.anchor = GridBagConstraints.WEST;
705 		gbc_toolBar_1.insets = new Insets(0, 0, 5, 0);
706 		gbc_toolBar_1.gridx = 0;
707 		gbc_toolBar_1.gridy = 4;
708 		connectionsPanel.add(toolBar_1, gbc_toolBar_1);
709 
710 		myAddInboundConnectionButton = new JButton("");
711 		myAddInboundConnectionButton.addActionListener(new ActionListener() {
712 			public void actionPerformed(ActionEvent e) {
713 				myController.addInboundConnection();
714 			}
715 		});
716 		myAddInboundConnectionButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/add.png")));
717 		myAddInboundConnectionButton.setToolTipText("New Connection");
718 		myAddInboundConnectionButton.setBorderPainted(false);
719 		myAddInboundConnectionButton.addMouseListener(new HoverButtonMouseAdapter(myAddInboundConnectionButton));
720 		toolBar_1.add(myAddInboundConnectionButton);
721 
722 		myDeleteInboundConnectionButton = new JButton("");
723 		myDeleteInboundConnectionButton.setToolTipText("Delete Selected Connection");
724 		myDeleteInboundConnectionButton.addActionListener(new ActionListener() {
725 			public void actionPerformed(ActionEvent e) {
726 				if (myController.getLeftSelectedItem() instanceof InboundConnection) {
727 					myController.removeInboundConnection((InboundConnection) myController.getLeftSelectedItem());
728 				}
729 			}
730 		});
731 		myDeleteInboundConnectionButton.setBorderPainted(false);
732 		myDeleteInboundConnectionButton.addMouseListener(new HoverButtonMouseAdapter(myDeleteInboundConnectionButton));
733 		myDeleteInboundConnectionButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/delete.png")));
734 		toolBar_1.add(myDeleteInboundConnectionButton);
735 		
736 		myStartOneInboundButton = new JButton("");
737 		myStartOneInboundButton.addActionListener(new ActionListener() {
738 			public void actionPerformed(ActionEvent e) {
739 				if (myController.getLeftSelectedItem() instanceof InboundConnection) {
740 					myController.startInboundConnection((InboundConnection) myController.getLeftSelectedItem());
741 				}
742 			}
743 		});
744 		myStartOneInboundButton.setBorderPainted(false);
745 		myStartOneInboundButton.setToolTipText("Start selected connection");
746 		myStartOneInboundButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/start_one.png")));
747 		myStartOneInboundButton.addMouseListener(new HoverButtonMouseAdapter(myStartOneInboundButton));
748 		toolBar_1.add(myStartOneInboundButton);
749 		
750 		myStartAllInboundButton = new JButton("");
751 		myStartAllInboundButton.setBorderPainted(false);
752 		myStartAllInboundButton.setToolTipText("Start all receiving connections");
753 		myStartAllInboundButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/start_all.png")));
754 		myStartAllInboundButton.addMouseListener(new HoverButtonMouseAdapter(myStartAllInboundButton));
755 		myStartAllInboundButton.addActionListener(new ActionListener() {
756 			public void actionPerformed(ActionEvent theE) {
757 				myController.startAllInboundConnections();
758 			}
759 		});
760 		toolBar_1.add(myStartAllInboundButton);
761 		
762 		myStopAllInboundButton = new JButton("");
763 		myStopAllInboundButton.addActionListener(new ActionListener() {
764 			public void actionPerformed(ActionEvent e) {
765 				myController.stopAllInboundConnections();
766 			}
767 		});
768 		myStopAllInboundButton.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/stop_all.png")));
769 		myStopAllInboundButton.setToolTipText("Stop all receiving connections");
770 		myStopAllInboundButton.setBorderPainted(false);
771 		myStopAllInboundButton.addMouseListener(new HoverButtonMouseAdapter(myStopAllInboundButton));
772 		toolBar_1.add(myStopAllInboundButton);
773 
774 		JScrollPane scrollPane_1 = new JScrollPane();
775 		scrollPane_1.setBorder(null);
776 		GridBagConstraints gbc_scrollPane_1 = new GridBagConstraints();
777 		gbc_scrollPane_1.fill = GridBagConstraints.BOTH;
778 		gbc_scrollPane_1.gridx = 0;
779 		gbc_scrollPane_1.gridy = 5;
780 		connectionsPanel.add(scrollPane_1, gbc_scrollPane_1);
781 
782 		myInboundConnectionsList = new JList();
783 		myInboundConnectionsList.addListSelectionListener(new ListSelectionListener() {
784 			public void valueChanged(ListSelectionEvent e) {
785 				if (myInboundConnectionsList.getSelectedIndex() >= 0) {
786 					ourLog.debug("New inbound connection selection " + myInboundConnectionsList.getSelectedIndex());
787 					myController.setLeftSelectedItem(myInboundConnectionsList.getSelectedValue());
788 					myMessagesList.clearSelection();
789 					myMessagesList.repaint();
790 					myOutboundConnectionsList.clearSelection();
791 					myOutboundConnectionsList.repaint();
792 					myInboundConnectionsList.repaint();
793 				}
794 				updateLeftToolbarButtons();
795 			}
796 		});
797 		scrollPane_1.setViewportView(myInboundConnectionsList);
798 		leftSplitPane.setDividerLocation(200);
799 
800 		myWorkspacePanel = new JPanel();
801 		myWorkspacePanel.setBorder(null);
802 		outerSplitPane.setRightComponent(myWorkspacePanel);
803 		myWorkspacePanel.setLayout(new BorderLayout(0, 0));
804 		outerSplitPane.setDividerLocation(200);
805 
806 		myLogScrollPane = new LogTable();
807 		myLogScrollPane.setPreferredSize(new Dimension(454, 120));
808 		myLogScrollPane.setMaximumSize(new Dimension(32767, 120));
809 		myframe.getContentPane().add(myLogScrollPane, BorderLayout.SOUTH);
810 
811 		updateLogScrollPaneVisibility();
812 
813 		updateLeftToolbarButtons();
814 	}
815 
816 	private void updateLogScrollPaneVisibility() {
817 		if (Prefs.getInstance().getShowLogConsole()) {
818 			myShowLogConsoleMenuItem.setSelected(true);
819 			myLogScrollPane.setVisible(true);
820 			myShowLogConsoleMenuItem.setIcon(new ImageIcon(TestPanelWindow.class.getResource("/ca/uhn/hl7v2/testpanel/images/menu_selected.png")));
821 		} else {
822 			myShowLogConsoleMenuItem.setSelected(false);
823 			myLogScrollPane.setVisible(false);
824 			myShowLogConsoleMenuItem.setIcon(null);
825 		}
826 
827 	}
828 
829 	private void initializeLocal() {
830 		myMessagesListModel = new MyMessagesListModel();
831 		myMessagesList.setModel(myMessagesListModel);
832 		myMessagesList.setCellRenderer(new MyMessagesListCellRencerer());
833 		myController.getMessagesList().addPropertyChangeListener(MessagesList.PROP_LIST, myMessagesListModel);
834 		updateMessagesList();
835 
836 		myOutboundConnectionsListModel = new MyOutboundConnectionsListModel();
837 		myOutboundConnectionsList.setModel(myOutboundConnectionsListModel);
838 		myOutboundConnectionsList.setCellRenderer(new MyOutboundConnectionsListCellRenderer());
839 		updateOutboundConnectionsList();
840 
841 		myOutboundConnectionsListListener = new PropertyChangeListener() {
842 			public void propertyChange(PropertyChangeEvent theEvt) {
843 				updateOutboundConnectionsList();
844 			}
845 		};
846 		myController.getOutboundConnectionList().addPropertyChangeListener(OutboundConnectionList.PROP_LIST, myOutboundConnectionsListListener);
847 
848 		myInboundConnectionsListModel = new MyInboundConnectionsListModel();
849 		myInboundConnectionsList.setModel(myInboundConnectionsListModel);
850 		myInboundConnectionsList.setCellRenderer(new MyInboundConnectionsListCellRenderer());
851 		updateInboundConnectionsList();
852 
853 		myInboundConnectionsListListener = new PropertyChangeListener() {
854 			public void propertyChange(PropertyChangeEvent theEvt) {
855 				updateInboundConnectionsList();
856 			}
857 		};
858 		myController.getInboundConnectionList().addPropertyChangeListener(InboundConnectionList.PROP_LIST, myInboundConnectionsListListener);
859 
860 		updateLeftToolbarInboundStatusButtons();
861 		updateLeftToolbarOutboundStatusButtons();
862 	}
863 
864 	public void updateOutboundConnectionsList() {
865 
866 		int index = 0;
867 		myOutboundConnectionsList.clearSelection();
868 		for (OutboundConnection next : myController.getOutboundConnectionList().getConnections()) {
869 
870 			if (myOutboundConnectionsListModel.size() <= index) {
871 
872 				myOutboundConnectionsListModel.addElement(next);
873 				next.addPropertyChangeListener(OutboundConnection.NAME_PROPERTY, new MyOutboundConnectionDescriptionListener(next));
874 				next.addPropertyChangeListener(OutboundConnection.STATUS_PROPERTY, new MyOutboundConnectionDescriptionListener(next));
875 				next.addPropertyChangeListener(OutboundConnection.PERSISTENT_PROPERTY, new MyOutboundConnectionDescriptionListener(next));
876 
877 			} else if (myOutboundConnectionsListModel.getElementAt(index) != next) {
878 
879 				myOutboundConnectionsListModel.add(index, next);
880 				next.addPropertyChangeListener(OutboundConnection.NAME_PROPERTY, new MyOutboundConnectionDescriptionListener(next));
881 				next.addPropertyChangeListener(OutboundConnection.STATUS_PROPERTY, new MyOutboundConnectionDescriptionListener(next));
882 				next.addPropertyChangeListener(OutboundConnection.PERSISTENT_PROPERTY, new MyOutboundConnectionDescriptionListener(next));
883 
884 			}
885 
886 			if (next == myController.getLeftSelectedItem()) {
887 				myOutboundConnectionsList.setSelectedIndex(index);
888 			}
889 
890 			index++;
891 		}
892 
893 		while (myOutboundConnectionsListModel.size() > index) {
894 			OutboundConnection obj = (OutboundConnection) myOutboundConnectionsListModel.remove(index);
895 			obj.destroy();
896 			obj.removePropertyChangeListener(Hl7V2MessageCollection.PROP_DESCRIPTION, myMessageDescriptionListener);
897 		}
898 
899 	}
900 
901 	/**
902 	 * Save the currently selected message
903 	 */
904 	private void doSaveMessages() {
905 		ourLog.info("Selected index: {}", myMessagesList.getSelectedIndex());
906 		myController.saveMessages((Hl7V2MessageCollection) myController.getLeftSelectedItem());
907 	}
908 
909 	private void doSaveMessagesAs() {
910 		ourLog.info("Selected index: {}", myMessagesList.getSelectedIndex());
911 		myController.saveMessagesAs((Hl7V2MessageCollection) myController.getLeftSelectedItem());
912 	}
913 	
914 	public void updateInboundConnectionsList() {
915 
916 		int index = 0;
917 		myInboundConnectionsList.clearSelection();
918 		for (InboundConnection next : myController.getInboundConnectionList().getConnections()) {
919 
920 			if (myInboundConnectionsListModel.size() <= index) {
921 
922 				myInboundConnectionsListModel.addElement(next);
923 				next.addPropertyChangeListener(InboundConnection.NAME_PROPERTY, new MyInboundConnectionDescriptionListener(next));
924 				next.addPropertyChangeListener(InboundConnection.STATUS_PROPERTY, new MyInboundConnectionDescriptionListener(next));
925 				next.addPropertyChangeListener(InboundConnection.NEW_MESSAGES_PROPERTY, new MyInboundConnectionDescriptionListener(next));
926 
927 			} else if (myInboundConnectionsListModel.getElementAt(index) != next) {
928 
929 				myInboundConnectionsListModel.add(index, next);
930 				next.addPropertyChangeListener(InboundConnection.NAME_PROPERTY, new MyInboundConnectionDescriptionListener(next));
931 				next.addPropertyChangeListener(InboundConnection.STATUS_PROPERTY, new MyInboundConnectionDescriptionListener(next));
932 				next.addPropertyChangeListener(InboundConnection.NEW_MESSAGES_PROPERTY, new MyInboundConnectionDescriptionListener(next));
933 
934 			}
935 
936 			if (next == myController.getLeftSelectedItem()) {
937 				myInboundConnectionsList.setSelectedIndex(index);
938 			}
939 
940 			index++;
941 		}
942 
943 		while (myInboundConnectionsListModel.size() > index) {
944 			InboundConnection obj = (InboundConnection) myInboundConnectionsListModel.remove(index);
945 			obj.destroy();
946 			obj.removePropertyChangeListener(Hl7V2MessageCollection.PROP_DESCRIPTION, myMessageDescriptionListener);
947 		}
948 
949 	}
950 
951 	private class MyInboundConnectionDescriptionListener implements PropertyChangeListener {
952 
953 		private AbstractConnection myConnection;
954 
955 		public MyInboundConnectionDescriptionListener(AbstractConnection theConnection) {
956 			myConnection = theConnection;
957 		}
958 
959 		public void propertyChange(PropertyChangeEvent theEvt) {
960 			String propertyName = theEvt.getPropertyName();
961 
962 			int rowIndex = myInboundConnectionsListModel.indexOf(myConnection);
963 			myInboundConnectionsListModel.fireChangeAtRow(rowIndex);
964 			
965 			if (propertyName == InboundConnection.STATUS_PROPERTY) {
966 				updateLeftToolbarInboundStatusButtons();
967 			}
968 		}
969 
970 		
971 	}
972 
973 
974 	private class MyOutboundConnectionDescriptionListener implements PropertyChangeListener {
975 
976 		private AbstractConnection myConnection;
977 
978 		public MyOutboundConnectionDescriptionListener(AbstractConnection theConnection) {
979 			myConnection = theConnection;
980 		}
981 
982 		public void propertyChange(PropertyChangeEvent theEvt) {
983 			int rowIndex = myOutboundConnectionsListModel.indexOf(myConnection);
984 			myOutboundConnectionsListModel.fireChangeAtRow(rowIndex);
985 			
986 			if (theEvt.getPropertyName() == InboundConnection.STATUS_PROPERTY) {
987 				updateLeftToolbarOutboundStatusButtons();
988 			}
989 		}
990 
991 	}
992 
993 	public void updateMessagesList() {
994 
995 		int index = 0;
996 		myMessagesList.clearSelection();
997 		for (Hl7V2MessageCollection next : myController.getMessagesList().getMessages()) {
998 
999 			if (myMessagesListModel.size() <= index) {
1000 				myMessagesListModel.addElement(next);
1001 				next.addPropertyChangeListener(Hl7V2MessageCollection.PROP_DESCRIPTION, myMessageDescriptionListener);
1002 				next.addPropertyChangeListener(Hl7V2MessageCollection.SAVED_PROPERTY, myMessageDescriptionListener);
1003 			} else if (myMessagesListModel.getElementAt(index) != next) {
1004 				myMessagesListModel.add(index, next);
1005 				next.addPropertyChangeListener(Hl7V2MessageCollection.PROP_DESCRIPTION, myMessageDescriptionListener);
1006 				next.addPropertyChangeListener(Hl7V2MessageCollection.SAVED_PROPERTY, myMessageDescriptionListener);
1007 			}
1008 
1009 			if (next == myController.getLeftSelectedItem()) {
1010 				myMessagesList.setSelectedIndex(index);
1011 			}
1012 
1013 			index++;
1014 		}
1015 
1016 		while (myMessagesListModel.size() > index) {
1017 			Hl7V2MessageCollection obj = (Hl7V2MessageCollection) myMessagesListModel.remove(index);
1018 			obj.removePropertyChangeListener(Hl7V2MessageCollection.PROP_DESCRIPTION, myMessageDescriptionListener);
1019 			obj.removePropertyChangeListener(Hl7V2MessageCollection.SAVED_PROPERTY, myMessageDescriptionListener);
1020 		}
1021 	}
1022 
1023 	private static final Logger ourLog = LoggerFactory.getLogger(TestPanelWindow.class);
1024 	private static final Color BG_SELECTED = new Color(0.8f, 0.8f, 1.0f);
1025 	private static final Color BG_NOT_SELECTED = Color.white;
1026 	private JPanel myWorkspacePanel;
1027 	private JButton myAddConnectionButton;
1028 	private JList myOutboundConnectionsList;
1029 	private JList myInboundConnectionsList;
1030 	private JScrollPane myLogScrollPane;
1031 	private BaseMainPanel myMainPanel;
1032 	private JButton myAddMessageButton;
1033 	private JButton myDeleteMessageButton;
1034 	private JButton myDeleteInboundConnectionButton;
1035 	private JMenuItem myShowLogConsoleMenuItem;
1036 	private JMenuItem mySaveMenuItem;
1037 	private JMenuItem mySaveAsMenuItem;
1038 	private JButton myStartAllInboundButton;
1039 	private JButton myStartOneInboundButton;
1040 	private JButton myStopAllInboundButton;
1041 	private JMenu mymenu;
1042 	private JMenuItem mymenuItem;
1043 	private JMenu mymenu_1;
1044 	private JMenuItem mymenuItem_1;
1045 	private JMenu mymenu_2;
1046 	private JMenuItem mymenuItem_2;
1047 	private JMenu myRecentFilesMenu;
1048 	private JMenuItem mymenuItem_3;
1049 	private JMenuItem mymenuItem_4;
1050 	private JMenu mymenu_3;
1051 	private JMenuItem mnHl7V2FileDiff;
1052 	private JMenuItem myRevertToSavedMenuItem;
1053 	private JMenuItem mymenuItem_5;
1054 
1055 	private final class MyMessageDescriptionListener implements PropertyChangeListener {
1056 		public void propertyChange(PropertyChangeEvent theEvt) {
1057 			Hl7V2MessageCollection source = (Hl7V2MessageCollection) theEvt.getSource();
1058 			for (int i = 0; i < myMessagesListModel.getSize(); i++) {
1059 				if (myMessagesListModel.elementAt(i) == source) {
1060 					myMessagesListModel.fireChangeAtRow(i);
1061 				}
1062 			}
1063 		}
1064 	}
1065 
1066 	private class MyMessagesListCellRencerer extends DefaultListCellRenderer {
1067 
1068 		/*
1069 		 * (non-Javadoc)
1070 		 * 
1071 		 * @see
1072 		 * javax.swing.DefaultListCellRenderer#getListCellRendererComponent(
1073 		 * javax.swing.JList, java.lang.Object, int, boolean, boolean)
1074 		 */
1075 		@Override
1076 		public Component getListCellRendererComponent(JList theList, Object theValue, int theIndex, boolean theIsSelected, boolean theCellHasFocus) {
1077 			if (theValue instanceof Hl7V2MessageCollection) {
1078 				setIcon(ImageFactory.getMessageHl7());
1079 
1080 				Hl7V2MessageCollection collection = (Hl7V2MessageCollection) theValue;
1081 				String description = collection.getMessageDescription();
1082 				if (collection.isSaved()) {
1083 					setText(description);
1084 				} else {
1085 					setText("<html><nobr><font color=\"red\" size=\"2\">unsaved</font> " + description + "</nobr></html>");
1086 				}
1087 
1088 				if (theValue == myController.getLeftSelectedItem()) {
1089 					setBackground(BG_SELECTED);
1090 				} else {
1091 					setBackground(BG_NOT_SELECTED);
1092 				}
1093 
1094 			} else {
1095 				ourLog.error("Unknown message element type: " + theValue.getClass().getName());
1096 			}
1097 			return this;
1098 		}
1099 
1100 	}
1101 
1102 	private class MyOutboundConnectionsListCellRenderer extends DefaultListCellRenderer {
1103 
1104 		/*
1105 		 * (non-Javadoc)
1106 		 * 
1107 		 * @see
1108 		 * javax.swing.DefaultListCellRenderer#getListCellRendererComponent(
1109 		 * javax.swing.JList, java.lang.Object, int, boolean, boolean)
1110 		 */
1111 		@Override
1112 		public Component getListCellRendererComponent(JList theList, Object theValue, int theIndex, boolean theIsSelected, boolean theCellHasFocus) {
1113 			OutboundConnection obj = (OutboundConnection) theValue;
1114 			switch (obj.getStatus()) {
1115 			case STARTED:
1116 				setIcon(ImageFactory.getInterfaceOn());
1117 				break;
1118 			case STOPPED:
1119 			case FAILED:
1120 				setIcon(ImageFactory.getInterfaceOff());
1121 				break;
1122 			case TRYING_TO_START:
1123 			default:
1124 				setIcon(ImageFactory.getInterfaceStarting());
1125 				break;
1126 			}
1127 
1128 			StringBuilder b = new StringBuilder();
1129 			b.append(obj.getName());
1130 			boolean html = false;
1131 			
1132 			if (!obj.isPersistent()) {
1133 				b.insert(0, "<font color=\\\"red\\\" size=\\\"2\\\">temp</font> ");
1134 				html = true;
1135 			}
1136 
1137 			if (obj.getNewMessages() > 0) {
1138 				b.append(" - <font color=\\\"red\\\">").append(obj.getNewMessages()).append(" new</font> ");
1139 				html = true;
1140 			}
1141 			
1142 			if (obj.getStatus() == StatusEnum.FAILED) {
1143 				b.append(" <font color=\"red\" size=\"2\">(failed)</font> ");
1144 				html = true;
1145 			}
1146 			
1147 
1148 			if (html) {
1149 				setText("<html><nobr>" + b.toString()+"</nobr></html>");
1150 			}else {
1151 				setText(b.toString());
1152 			}
1153 			
1154 			if (theValue == myController.getLeftSelectedItem()) {
1155 				setBackground(BG_SELECTED);
1156 			} else {
1157 				setBackground(BG_NOT_SELECTED);
1158 			}
1159 
1160 			return this;
1161 		}
1162 
1163 	}
1164 
1165 	private class MyInboundConnectionsListCellRenderer extends DefaultListCellRenderer {
1166 
1167 		/*
1168 		 * (non-Javadoc)
1169 		 * 
1170 		 * @see
1171 		 * javax.swing.DefaultListCellRenderer#getListCellRendererComponent(
1172 		 * javax.swing.JList, java.lang.Object, int, boolean, boolean)
1173 		 */
1174 		@Override
1175 		public Component getListCellRendererComponent(JList theList, Object theValue, int theIndex, boolean theIsSelected, boolean theCellHasFocus) {
1176 			InboundConnection obj = (InboundConnection) theValue;
1177 			switch (obj.getStatus()) {
1178 			case STARTED:
1179 				setIcon(ImageFactory.getInterfaceOn());
1180 				break;
1181 			case STOPPED:
1182 			case FAILED:
1183 				setIcon(ImageFactory.getInterfaceOff());
1184 				break;
1185 			case TRYING_TO_START:
1186 			default:
1187 				setIcon(ImageFactory.getInterfaceStarting());
1188 				break;
1189 			}
1190 
1191 			StringBuilder b = new StringBuilder();
1192 			b.append(obj.getName());
1193 			boolean html = false;
1194 			
1195 			if (!obj.isPersistent()) {
1196 				b.insert(0, "<font color=\"red\" size=\"2\">temp</font> ");
1197 				html = true;
1198 			}
1199 
1200 			if (obj.getNewMessages() > 0) {
1201 				b.append(" <font color=\"red\" size=\"2\">(").append(obj.getNewMessages()).append(" new)</font> ");
1202 				html = true;
1203 			}
1204 			
1205 			if (obj.getStatus() == StatusEnum.FAILED) {
1206 				b.append(" <font color=\"red\" size=\"2\">(failed)</font> ");
1207 				html = true;
1208 			}
1209 			
1210 			if (html) {
1211 				setText("<html><nobr>" + b.toString()+"</nobr></html>");
1212 			}else {
1213 				setText(b.toString());
1214 			}
1215 			
1216 			if (theValue == myController.getLeftSelectedItem()) {
1217 				setBackground(BG_SELECTED);
1218 			} else {
1219 				setBackground(BG_NOT_SELECTED);
1220 			}
1221 
1222 			return this;
1223 		}
1224 
1225 	}
1226 
1227 	public void setMainPanel(BaseMainPanel theOutboundPanel) {
1228 		Validate.notNull(theOutboundPanel);
1229 
1230 		if (myMainPanel != null) {
1231 			if (myMainPanel instanceof IDestroyable) {
1232 				((IDestroyable) myMainPanel).destroy();
1233 			}
1234 			myMainPanel.removePropertyChangeListener(BaseMainPanel.PROP_WINDOWTITLE, myPanelTitleListener);
1235 		}
1236 
1237 		myMainPanel = theOutboundPanel;
1238 		myMainPanel.addPropertyChangeListener(BaseMainPanel.PROP_WINDOWTITLE, myPanelTitleListener);
1239 
1240 		myWorkspacePanel.removeAll();
1241 		myWorkspacePanel.add(theOutboundPanel, BorderLayout.CENTER);
1242 		myWorkspacePanel.validate();
1243 
1244 		myMessagesList.repaint();
1245 		myInboundConnectionsList.repaint();
1246 		myOutboundConnectionsList.repaint();
1247 
1248 		updateLeftToolbarButtons();
1249 		updateWindowTitle();
1250 	}
1251 
1252 	private class MyMessagesListModel extends DefaultListModel implements PropertyChangeListener {
1253 
1254 		public void fireChangeAtRow(int theI) {
1255 			fireContentsChanged(this, theI, theI);
1256 		}
1257 
1258 		public void propertyChange(PropertyChangeEvent theEvt) {
1259 			updateMessagesList();
1260 		}
1261 
1262 	}
1263 
1264 	private class MyOutboundConnectionsListModel extends DefaultListModel {
1265 
1266 		public void fireChangeAtRow(int theI) {
1267 			fireContentsChanged(this, theI, theI);
1268 		}
1269 
1270 	}
1271 
1272 	private class MyInboundConnectionsListModel extends DefaultListModel {
1273 
1274 		public void fireChangeAtRow(int theI) {
1275 			fireContentsChanged(this, theI, theI);
1276 		}
1277 
1278 	}
1279 
1280 	public JFrame getFrame() {
1281 		return myframe;
1282 	}
1283 
1284 	/**
1285 	 * {@inheritDoc}
1286 	 */
1287 	public void destroy() {
1288 		
1289 		// For some reason, on OSX once a window has been maximized it will keep reporting
1290 		// that it is even once it no longer is
1291 		int extState = myframe.getExtendedState();
1292 		if (extState == JFrame.MAXIMIZED_BOTH && !System.getProperty("os.name").contains("Mac")) { 
1293 			Prefs.getInstance().setWindowMaximized(true);
1294 		} else {			
1295 			Point location = myframe.getLocation();
1296 			Dimension size = myframe.getSize();
1297 			ourLog.info("Saving window location of {} and size of {}", location, size);
1298 			Prefs.getInstance().setWindowPosition(location);
1299 			Prefs.getInstance().setWindowDimension(size);
1300 			Prefs.getInstance().setWindowMaximized(false);
1301 		}
1302 	}
1303 
1304 	public void showAboutDialog() {
1305 		if (myAboutDialog == null) {
1306 			myAboutDialog = new AboutDialog();
1307 		}
1308 		myAboutDialog.setVisible(true);
1309 	}
1310 
1311 	public void setRecentMessageFiles(List<Hl7V2MessageCollection> theList) {
1312 		myRecentFilesMenu.removeAll();
1313 		for (final Hl7V2MessageCollection nextFile : theList) {
1314 			JMenuItem nextItem = new JMenuItem(nextFile.getSaveFileName());
1315 			myRecentFilesMenu.add(nextItem);
1316 			nextItem.addActionListener(new ActionListener() {
1317 				public void actionPerformed(ActionEvent theE) {
1318 					myController.openOrSwitchToMessage(nextFile);
1319 				}
1320 			});
1321 		}
1322 	}
1323 
1324 }