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    }