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 }