001 /****************************************************************************** 002 * Copyright (C) MActor Developers. All rights reserved. * 003 * ---------------------------------------------------------------------------* 004 * This file is part of MActor. * 005 * * 006 * MActor is free software; you can redistribute it and/or modify * 007 * it under the terms of the GNU General Public License as published by * 008 * the Free Software Foundation; either version 2 of the License, or * 009 * (at your option) any later version. * 010 * * 011 * MActor is distributed in the hope that it will be useful, * 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 014 * GNU General Public License for more details. * 015 * * 016 * You should have received a copy of the GNU General Public License * 017 * along with MActor; if not, write to the Free Software * 018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * 019 ******************************************************************************/ 020 package org.mactor.ui.gui.testrunner; 021 022 import java.awt.BorderLayout; 023 import java.awt.Component; 024 import java.awt.FlowLayout; 025 import java.io.File; 026 import java.util.ArrayList; 027 import java.util.List; 028 029 import javax.swing.Icon; 030 import javax.swing.JButton; 031 import javax.swing.JPanel; 032 import javax.swing.JScrollPane; 033 import javax.swing.JTable; 034 import javax.swing.ListSelectionModel; 035 import javax.swing.SwingUtilities; 036 import javax.swing.event.ListSelectionEvent; 037 import javax.swing.event.ListSelectionListener; 038 import javax.swing.table.AbstractTableModel; 039 import javax.swing.table.DefaultTableCellRenderer; 040 041 import org.mactor.brokers.MessageBrokerManager; 042 import org.mactor.brokers.MessageBrokerManager.MessageInfo; 043 import org.mactor.brokers.MessageBrokerManager.MessageInfoListener; 044 import org.mactor.framework.MactorException; 045 import org.mactor.ui.gui.AsyncAction; 046 import org.mactor.ui.gui.GuiUtil; 047 048 public class ChannelMessageLogPanel extends JPanel { 049 private JTable table; 050 MessageHistoryTableModel model = new MessageHistoryTableModel(); 051 JButton loadButton = new JButton(new AsyncAction("Load Log from Archive", false, new AsyncAction.AsyncRunnable() { 052 public void run() { 053 try { 054 model.setMessageHistory(MessageBrokerManager.getInstance().loadMessageInfoFromArchive(channel)); 055 } catch (MactorException e) { 056 GuiUtil.showGuiError(ChannelMessageLogPanel.this, e); 057 } 058 } 059 })); 060 JButton clearButton = new JButton(new AsyncAction("Clear GUI", false, new AsyncAction.AsyncRunnable() { 061 public void run() { 062 model.setMessageHistory(new ArrayList<MessageInfo>()); 063 } 064 })); 065 JButton clearDiskButton = new JButton(new AsyncAction("Clear Archive", true, new AsyncAction.AsyncRunnable() { 066 public void run() { 067 try { 068 MessageBrokerManager.getInstance().clearArchive(channel); 069 model.setMessageHistory(new ArrayList<MessageInfo>()); 070 } catch (MactorException e) { 071 GuiUtil.showGuiError(ChannelMessageLogPanel.this, e); 072 } 073 } 074 })); 075 String channel; 076 public ChannelMessageLogPanel(String channel) throws MactorException { 077 super(new BorderLayout()); 078 this.channel = channel; 079 table = new JTable(model); 080 table.getColumnModel().getColumn(0).setCellRenderer(new MessageTableCellRendere()); 081 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 082 table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { 083 public void valueChanged(ListSelectionEvent event) { 084 if (listener != null) { 085 int row = table.getSelectedRow(); 086 if (row >= 0) { 087 Object name = model.getValueAt(row, 2); 088 if (name != null) { 089 listener.onChange(new File(name.toString())); 090 } 091 } 092 } 093 } 094 }); 095 // summaryTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 096 table.getColumnModel().getColumn(0).setMaxWidth(25); 097 JScrollPane tableSp = new JScrollPane(table); 098 add(tableSp, BorderLayout.CENTER); 099 JPanel buttonPanel = new JPanel(new FlowLayout()); 100 buttonPanel.add(clearButton); 101 buttonPanel.add(clearDiskButton); 102 buttonPanel.add(loadButton); 103 add(buttonPanel, BorderLayout.SOUTH); 104 MessageBrokerManager.getInstance().addMessageInfoListener(channel, miListener); 105 } 106 MessageSelectionChangedListener listener; 107 public void setMessageSelectionChangedListener(MessageSelectionChangedListener listener) { 108 this.listener = listener; 109 } 110 public static interface MessageSelectionChangedListener { 111 void onChange(File archivedFile); 112 } 113 MessageInfoListener miListener = new MessageInfoListener() { 114 public void onMessageInfo(final MessageInfo messageInfo) { 115 SwingUtilities.invokeLater(new Runnable() { 116 public void run() { 117 model.addMessage(messageInfo); 118 } 119 }); 120 }; 121 }; 122 public void stop() throws MactorException { 123 MessageBrokerManager.getInstance().removeMessageInfoListener(channel, miListener); 124 } 125 static final int MAX = 2000; 126 static final int HYST = 300; 127 private static class MessageHistoryTableModel extends AbstractTableModel { 128 private static final Icon INCOMING_ICON = GuiUtil.loadIcon("/incoming_16.PNG"); 129 private static final Icon INCOMING_RESP_ICON = GuiUtil.loadIcon("/incoming_resp_16.PNG"); 130 private static final Icon OUTGOING_ICON = GuiUtil.loadIcon("/outgoing_16.PNG"); 131 private static final Icon OUTGOING_RESP_ICON = GuiUtil.loadIcon("/outgoing_resp_16.PNG"); 132 ArrayList<MessageInfo> history = new ArrayList<MessageInfo>(); 133 String[] colums = new String[] { "", "Timestamp", "Path" }; 134 @Override 135 public String getColumnName(int col) { 136 return colums[col]; 137 } 138 public void setMessageHistory(List<MessageInfo> history) { 139 this.history = new ArrayList<MessageInfo>(history); 140 adjust(); 141 super.fireTableDataChanged(); 142 } 143 public void addMessage(MessageInfo messageInfo) { 144 this.history.add(messageInfo); 145 adjust(); 146 super.fireTableDataChanged(); 147 } 148 final private void adjust() { 149 if (this.history.size() > MAX) 150 this.history = new ArrayList<MessageInfo>(this.history.subList((history.size() - MAX) + HYST, history.size() - 1)); 151 } 152 public int getColumnCount() { 153 return colums.length; 154 } 155 public int getRowCount() { 156 if (history == null) 157 return 0; 158 return history.size(); 159 } 160 public MessageInfo getMessageInfo(int row) { 161 if (history == null || row < 0 || row >= history.size()) 162 return null; 163 return history.get(history.size() - 1 - row); 164 } 165 public Object getValueAt(int row, int col) { 166 if (history == null) 167 return null; 168 MessageInfo mi = history.get(history.size() - 1 - row); 169 if (col == 0) 170 return getCol_0(mi); 171 if (col == 1) 172 return getCol_1(mi); 173 if (col == 2) 174 return getCol_2(mi); 175 throw new RuntimeException("Invalid column '" + col + "'"); 176 } 177 private Object getCol_0(MessageInfo mi) { 178 if (mi.isIncoming()) { 179 if (mi.isResponse()) 180 return INCOMING_RESP_ICON; 181 return INCOMING_ICON; 182 } 183 if (mi.isResponse()) 184 return OUTGOING_RESP_ICON; 185 return OUTGOING_ICON; 186 } 187 private Object getCol_1(MessageInfo mi) { 188 return GuiUtil.format(mi.getCreatedTime()); 189 } 190 private String getCol_2(MessageInfo mi) { 191 return mi.getArchivePath(); 192 } 193 } 194 public class MessageTableCellRendere extends DefaultTableCellRenderer { 195 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 196 if (value instanceof Icon) 197 setIcon((Icon) value); 198 else 199 setIcon(null); 200 setText(null); 201 return this; 202 } 203 } 204 }