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 }