1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
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.event.ActionEvent;
33  import java.awt.event.ActionListener;
34  import java.beans.PropertyChangeEvent;
35  import java.beans.PropertyChangeListener;
36  import java.text.SimpleDateFormat;
37  import java.util.ArrayList;
38  import java.util.Collections;
39  import java.util.LinkedList;
40  import java.util.List;
41  
42  import javax.swing.Box;
43  import javax.swing.ImageIcon;
44  import javax.swing.JButton;
45  import javax.swing.JMenuItem;
46  import javax.swing.JPanel;
47  import javax.swing.JPopupMenu;
48  import javax.swing.JProgressBar;
49  import javax.swing.JScrollPane;
50  import javax.swing.JTable;
51  import javax.swing.JToolBar;
52  import javax.swing.ListSelectionModel;
53  import javax.swing.ScrollPaneConstants;
54  import javax.swing.SwingUtilities;
55  import javax.swing.event.ListSelectionEvent;
56  import javax.swing.event.ListSelectionListener;
57  import javax.swing.event.TableModelEvent;
58  import javax.swing.event.TableModelListener;
59  import javax.swing.table.TableModel;
60  
61  import org.slf4j.Logger;
62  import org.slf4j.LoggerFactory;
63  
64  import ca.uhn.hl7v2.testpanel.controller.Controller;
65  import ca.uhn.hl7v2.testpanel.model.ActivityBase;
66  import ca.uhn.hl7v2.testpanel.model.ActivityIncomingBytes;
67  import ca.uhn.hl7v2.testpanel.model.ActivityIncomingMessage;
68  import ca.uhn.hl7v2.testpanel.model.ActivityMessage;
69  import ca.uhn.hl7v2.testpanel.model.ActivityOutgoingBytes;
70  import ca.uhn.hl7v2.testpanel.model.ActivityOutgoingMessage;
71  import ca.uhn.hl7v2.testpanel.model.conn.AbstractConnection;
72  import ca.uhn.hl7v2.testpanel.model.conn.InboundConnection;
73  import ca.uhn.hl7v2.testpanel.ui.conn.JGraph;
74  import ca.uhn.hl7v2.testpanel.util.ISendProgressCallback;
75  
76  public class ActivityTable extends JPanel implements IDestroyable {
77  
78  	@SuppressWarnings("unused")
79  	private static final Logger ourLog = LoggerFactory.getLogger(ActivityTable.class);
80  
81  	private static final SimpleDateFormat ourTimestampFormat = new SimpleDateFormat("HH:mm:ss.SSS");
82  
83  	private JButton clearButton;
84  	private ActivityTableModel myActivityTableModel;
85  	private AbstractConnection myConnection;
86  	private Controller myController;
87  	private JMenuItem myEditAllButton;
88  	private JButton myEditButton;
89  	private JPopupMenu myEditMenu;
90  	private JMenuItem myEditSelectedButton;
91  	private boolean myInboundConnection;
92  	private PropertyChangeListener myRecentActivityListener;
93  	private JMenuItem mySaveAllButton;
94  	private JButton mySaveButton;
95  
96  	
97  
98  
99  	private JPopupMenu mySaveMenu;
100 
101 	private JMenuItem mySaveSelectedButton;
102 	private JScrollPane myScrollPane;
103 	private JTable myTable;
104 	private ActivityDetailsCellRenderer myDetailsCellRenderer;
105 	private JProgressBar myProgressBar;
106 	private Component myhorizontalGlue;
107 	private JButton myStop;
108 
109 	protected boolean myTransmissionCancelled;
110 
111 	private JGraph mySendThroughputGraph;
112 
113 	public ActivityTable() {
114 		super(new BorderLayout());
115 		setBorder(null);
116 
117 		JToolBar toolBar = new JToolBar();
118 		toolBar.setRollover(true);
119 		toolBar.setFloatable(false);
120 		add(toolBar, BorderLayout.NORTH);
121 
122 		clearButton = new JButton("Clear");
123 		clearButton.addMouseListener(new HoverButtonMouseAdapter(clearButton));
124 		clearButton.setIcon(new ImageIcon(ActivityTable.class.getResource("/ca/uhn/hl7v2/testpanel/images/clear.png")));
125 		clearButton.setBorderPainted(false);
126 		clearButton.addActionListener(new ActionListener() {
127 
128 			public void actionPerformed(ActionEvent theE) {
129 				myConnection.clearRecentActivity();
130 			}
131 		});
132 		toolBar.add(clearButton);
133 
134 		mySaveButton = new JButton("Save");
135 		mySaveButton.addMouseListener(new HoverButtonMouseAdapter(mySaveButton));
136 		mySaveButton.setBorderPainted(false);
137 		mySaveButton.setEnabled(false);
138 		mySaveButton.setIcon(new ImageIcon(ActivityTable.class.getResource("/ca/uhn/hl7v2/testpanel/images/save.png")));
139 		mySaveButton.addActionListener(new ActionListener() {
140 			public void actionPerformed(ActionEvent e) {
141 				mySaveMenu.show(mySaveButton, mySaveButton.getX(), mySaveButton.getY() + mySaveButton.getHeight());
142 			}
143 		});
144 		toolBar.add(mySaveButton);
145 
146 		myEditButton = new JButton("Edit");
147 		myEditButton.setEnabled(false);
148 		myEditButton.setBorderPainted(false);
149 		myEditButton.addMouseListener(new HoverButtonMouseAdapter(myEditButton));
150 		myEditButton.setIcon(new ImageIcon(ActivityTable.class.getResource("/ca/uhn/hl7v2/testpanel/images/edit_one.png")));
151 		myEditButton.addActionListener(new ActionListener() {
152 			public void actionPerformed(ActionEvent e) {
153 				myEditMenu.show(myEditButton, myEditButton.getX(), myEditButton.getY() + myEditButton.getHeight());
154 			}
155 		});
156 		toolBar.add(myEditButton);
157 
158 		myhorizontalGlue = Box.createHorizontalGlue();
159 		toolBar.add(myhorizontalGlue);
160 
161 		mySendThroughputGraph = new JGraph();
162 		mySendThroughputGraph.setPreferredSize(new Dimension(200, 0));
163 		mySendThroughputGraph.setMinimumSize(new Dimension(200, 0));
164 		mySendThroughputGraph.setMaximumSize(new Dimension(200, 32767));
165 		toolBar.add(mySendThroughputGraph);
166 
167 		myStop = new JButton();
168 		myStop.addActionListener(new ActionListener() {
169 			public void actionPerformed(ActionEvent e) {
170 				myTransmissionCancelled = true;
171 				myStop.setEnabled(false);
172 			}
173 		});
174 		myStop.setEnabled(false);
175 		myStop.setBorderPainted(false);
176 		myStop.setIcon(new ImageIcon(ActivityTable.class.getResource("/ca/uhn/hl7v2/testpanel/images/stop.png")));
177 		myStop.addMouseListener(new HoverButtonMouseAdapter(myStop));
178 		toolBar.add(myStop);
179 
180 		myProgressBar = new JProgressBar();
181 		myProgressBar.setEnabled(false);
182 		myProgressBar.setMaximumSize(new Dimension(150, 20));
183 		myProgressBar.setMinimumSize(new Dimension(150, 20));
184 		myProgressBar.setPreferredSize(new Dimension(150, 20));
185 		toolBar.add(myProgressBar);
186 
187 		myScrollPane = new JScrollPane();
188 		myScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
189 		add(myScrollPane, BorderLayout.CENTER);
190 
191 		myTable = new JTable();
192 		myTable.setGridColor(Color.LIGHT_GRAY);
193 		
194 		
195 		myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
196 		myScrollPane.setViewportView(myTable);
197 
198 		myEditMenu = new JPopupMenu();
199 
200 		myEditSelectedButton = new JMenuItem("Edit Selected Message");
201 		myEditSelectedButton.setIcon(new ImageIcon(ActivityTable.class.getResource("/ca/uhn/hl7v2/testpanel/images/edit_one.png")));
202 		myEditSelectedButton.addActionListener(new ActionListener() {
203 			public void actionPerformed(ActionEvent theE) {
204 				ActivityMessage selected = (ActivityMessage) myActivityTableModel.getActivity(myTable.getSelectedRow());
205 				myController.editMessages(Collections.singletonList(selected));
206 			}
207 		});
208 		myEditMenu.add(myEditSelectedButton);
209 
210 		myEditAllButton = new JMenuItem("Edit All Messages");
211 		myEditAllButton.setIcon(new ImageIcon(ActivityTable.class.getResource("/ca/uhn/hl7v2/testpanel/images/edit_all.png")));
212 		myEditAllButton.addActionListener(new ActionListener() {
213 			public void actionPerformed(ActionEvent theE) {
214 				List<ActivityMessage> messages = myConnection.getRecentActivityEntriesOfType(ActivityMessage.class);
215 				myController.editMessages(messages);
216 			}
217 		});
218 		myEditMenu.add(myEditAllButton);
219 
220 		mySaveMenu = new JPopupMenu();
221 
222 		mySaveSelectedButton = new JMenuItem("Save Selected Message");
223 		mySaveSelectedButton.setIcon(new ImageIcon(ActivityTable.class.getResource("/ca/uhn/hl7v2/testpanel/images/save.png")));
224 		mySaveMenu.add(mySaveSelectedButton);
225 
226 		mySaveAllButton = new JMenuItem("Save All Messages");
227 		mySaveAllButton.setIcon(new ImageIcon(ActivityTable.class.getResource("/ca/uhn/hl7v2/testpanel/images/save_all.png")));
228 		mySaveMenu.add(mySaveAllButton);
229 
230 		myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
231 			public void valueChanged(ListSelectionEvent theE) {
232 				updateUiBasedOnSelectedRow();
233 			}
234 		});
235 		updateUiBasedOnSelectedRow();
236 
237 		setProgressIndicatorsEnabled(false);
238 	}
239 
240 	
241 
242 
243 	public JScrollPane getScrollPane() {
244 		return myScrollPane;
245 	}
246 
247 	public void destroy() {
248 		removeListeners();
249 	}
250 
251 	
252 
253 
254 	public AbstractConnection getConnection() {
255 		return myConnection;
256 	}
257 
258 	
259 
260 
261 	public boolean isInboundConnection() {
262 		return myInboundConnection;
263 	}
264 
265 	public boolean isResponseAtRow(int theRow) {
266 		ActivityBase activity = myConnection.getRecentActivity().get(theRow);
267 		if ((activity instanceof ActivityOutgoingMessage || activity instanceof ActivityOutgoingBytes) && isInboundConnection()) {
268 			return true;
269 		}
270 
271 		if ((activity instanceof ActivityIncomingMessage || activity instanceof ActivityIncomingBytes) && !isInboundConnection()) {
272 			return true;
273 		}
274 
275 		return false;
276 	}
277 
278 	private void removeListeners() {
279 		if (myConnection != null) {
280 			myConnection.removePropertyChangeListener(AbstractConnection.RECENT_ACTIVITY_PROPERTY, myRecentActivityListener);
281 		}
282 	}
283 
284 	public void setConnection(AbstractConnection theConnection) {
285 		setConnection(theConnection, true);
286 	}
287 
288 	public void setConnection(AbstractConnection theConnection, boolean theIncludePreviousEvents) {
289 		removeListeners();
290 
291 		myConnection = theConnection;
292 		if (myConnection instanceof InboundConnection) {
293 			myInboundConnection = true;
294 		}
295 
296 		myActivityTableModel = new ActivityTableModel();
297 		myTable.setModel(myActivityTableModel);
298 
299 		myRecentActivityListener = new PropertyChangeListener() {
300 			public void propertyChange(PropertyChangeEvent theEvt) {
301 				SwingUtilities.invokeLater(new Runnable() {
302 					public void run() {
303 						myActivityTableModel.update();
304 						myDetailsCellRenderer.markScrollToBottom();
305 
306 					}
307 				});
308 			}
309 		};
310 		myConnection.addPropertyChangeListener(AbstractConnection.RECENT_ACTIVITY_PROPERTY, myRecentActivityListener);
311 		myActivityTableModel.update();
312 
313 		
314 		
315 		
316 
317 		myTable.getColumnModel().getColumn(0).setCellRenderer(new ActivityCellRendererBase(this));
318 		myTable.getColumnModel().getColumn(1).setCellRenderer(new ActivityTypeCellRenderer(this, theConnection instanceof InboundConnection));
319 
320 		myDetailsCellRenderer = new ActivityDetailsCellRenderer(this);
321 		myTable.getColumnModel().getColumn(2).setCellRenderer(myDetailsCellRenderer);
322 
323 		final int timestampWidth = 100;
324 		myTable.getColumnModel().getColumn(0).setMaxWidth(timestampWidth);
325 		myTable.getColumnModel().getColumn(0).setMinWidth(timestampWidth);
326 		myTable.getColumnModel().getColumn(0).setPreferredWidth(timestampWidth);
327 
328 		final int activityWidth = 150;
329 		myTable.getColumnModel().getColumn(1).setMaxWidth(activityWidth);
330 		myTable.getColumnModel().getColumn(1).setMinWidth(activityWidth);
331 		myTable.getColumnModel().getColumn(1).setPreferredWidth(activityWidth);
332 
333 		int detailWidth = 5000;
334 		myTable.getColumnModel().getColumn(2).setMaxWidth(detailWidth);
335 		myTable.getColumnModel().getColumn(2).setMinWidth(detailWidth);
336 		myTable.getColumnModel().getColumn(2).setPreferredWidth(detailWidth);
337 	}
338 
339 	
340 
341 
342 
343 	public void setController(Controller theController) {
344 		assert theController != null;
345 
346 		myController = theController;
347 	}
348 
349 	private void updateUiBasedOnSelectedRow() {
350 		boolean messageSelected = false;
351 		int selectedRow = myTable.getSelectedRow();
352 		if (selectedRow != -1) {
353 			Object activity = myActivityTableModel.getActivity(selectedRow);
354 			if (activity instanceof ActivityMessage) {
355 				messageSelected = true;
356 			}
357 		}
358 
359 		mySaveSelectedButton.setEnabled(messageSelected);
360 		myEditSelectedButton.setEnabled(messageSelected);
361 	}
362 
363 	class ActivityTableModel implements TableModel {
364 
365 		private List<TableModelListener> myTableListeners = new ArrayList<TableModelListener>();
366 
367 		public ActivityTableModel() {
368 		}
369 
370 		public void addTableModelListener(TableModelListener theL) {
371 			myTableListeners.add(theL);
372 		}
373 
374 		public Object getActivity(int theRowIndex) {
375 			return myConnection.getRecentActivity().get(theRowIndex);
376 		}
377 
378 		public Class<?> getColumnClass(int theColumnIndex) {
379 			return String.class;
380 		}
381 
382 		public int getColumnCount() {
383 			return 3;
384 		}
385 
386 		public String getColumnName(int theColumnIndex) {
387 			switch (theColumnIndex) {
388 			case 0:
389 				return "Timestamp";
390 			case 1:
391 				return "Activity";
392 			case 2:
393 				return "Details";
394 			default:
395 				throw new IllegalArgumentException(theColumnIndex + "");
396 			}
397 		}
398 
399 		public int getRowCount() {
400 			return myConnection.getRecentActivity().size();
401 		}
402 
403 		public Object getValueAt(int theRowIndex, int theColumnIndex) {
404 			ActivityBase activity = myConnection.getRecentActivity().get(theRowIndex);
405 
406 			switch (theColumnIndex) {
407 			case 0:
408 				return ourTimestampFormat.format(activity.getTimestamp());
409 			case 1:
410 			case 2:
411 			default:
412 				return activity;
413 			}
414 		}
415 
416 		public boolean isCellEditable(int theRowIndex, int theColumnIndex) {
417 			return false;
418 		}
419 
420 		public void removeTableModelListener(TableModelListener theL) {
421 			myTableListeners.remove(theL);
422 		}
423 
424 		public void setValueAt(Object theAValue, int theRowIndex, int theColumnIndex) {
425 			throw new UnsupportedOperationException();
426 		}
427 
428 		public void update() {
429 			if (mySaveButton.isEnabled() == false && myConnection.getRecentActivity().isEmpty() == false) {
430 				mySaveButton.setEnabled(true);
431 				myEditButton.setEnabled(true);
432 			}
433 			for (TableModelListener next : myTableListeners) {
434 				TableModelEvent event = new TableModelEvent(this);
435 				next.tableChanged(event);
436 			}
437 		}
438 
439 	}
440 
441 	public ActivityTableModel getTableModel() {
442 		return myActivityTableModel;
443 	}
444 
445 	
446 	
447 	
448 	
449 	
450 	
451 	
452 	
453 	
454 	
455 	
456 	
457 	
458 	
459 	
460 	
461 	
462 	
463 	
464 	
465 	
466 	
467 	
468 	
469 	
470 	
471 	
472 	
473 	
474 	
475 	
476 	
477 	
478 	
479 	
480 	
481 	
482 	
483 	
484 	
485 	
486 	
487 	
488 	
489 	
490 	
491 	
492 	
493 
494 	public ISendProgressCallback provideTransmissionCallback() {
495 		return new ISendProgressCallback() {
496 
497 			private LinkedList<Integer> myValues = new LinkedList<Integer>();
498 
499 			public void activityStopped() {
500 				setProgressIndicatorsEnabled(false);
501 			}
502 
503 			public void activityStarted() {
504 				setProgressIndicatorsEnabled(true);
505 				myTransmissionCancelled = false;
506 			}
507 
508 			public void progressUpdate(double theProgress) throws OperationCancelRequestedException {
509 				setProgress(theProgress);
510 				if (myTransmissionCancelled) {
511 					throw new OperationCancelRequestedException();
512 				}
513 			}
514 
515 			public void updateAvgThroughputPerSecond(int theThroughput) {
516 				myValues.add(theThroughput);
517 				while (myValues.size() > 100) {
518 					myValues.pop();
519 				}
520 				ourLog.info("Throughput values: {}", myValues);
521 				mySendThroughputGraph.setText(theThroughput + " msgs/sec");
522 				mySendThroughputGraph.setValues(myValues);
523 			}
524 
525 			public void updateAvgResponseTimeMillis(int theMillis) {
526 				
527 
528 			}
529 		};
530 	}
531 
532 	public void setProgressIndicatorsEnabled(boolean theEnabled) {
533 		myStop.setEnabled(theEnabled);
534 		myStop.setVisible(theEnabled);
535 		myProgressBar.setEnabled(theEnabled);
536 		myProgressBar.setVisible(theEnabled);
537 	}
538 
539 	public void setProgress(double theProgress) {
540 		myProgressBar.setValue(Math.max(0, Math.min(100, (int) (theProgress * 100))));
541 	}
542 
543 }