/* * Copyright 2003,2004,2005 Colin Crist * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package hermes.browser.actions; import hermes.browser.HermesBrowser; import hermes.browser.IconCache; import hermes.browser.tasks.Task; import hermes.browser.tasks.TaskListener; import hermes.fix.FIXMessage; import hermes.fix.FIXMessageTable; import hermes.fix.FIXUtils; import hermes.swing.FilterablePanel; import hermes.swing.SwingRunner; import hermes.swing.SwingUtils; import hermes.util.DumpUtils; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Font; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Timer; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.border.EtchedBorder; import javax.swing.event.ListSelectionEvent; import org.apache.commons.collections.map.LRUMap; import org.apache.log4j.Logger; import com.jidesoft.document.DocumentComponentEvent; import com.jidesoft.document.DocumentComponentListener; import com.jidesoft.swing.JideScrollPane; import com.jidesoft.swing.JideTabbedPane; /** * @author colincrist@hermesjms.com * @version $Id: AbstractFIXBrowserDocumentComponent.java,v 1.4 2006/07/17 * 21:20:54 colincrist Exp $ */ public abstract class AbstractFIXBrowserDocumentComponent extends AbstractDocumentComponent implements DocumentComponentListener, TaskListener { private static final Logger log = Logger.getLogger(AbstractFIXBrowserDocumentComponent.class); private final JLabel statusMessage = new JLabel(); protected static final Timer timer = new Timer(); private int screenUpdateTimeout = 100; private JPanel statusPanel; private JPanel topPanel; private boolean taskStopped = false; private String title; private Task task; private List<FIXMessage> cachedRows = new ArrayList<FIXMessage>(); private JideTabbedPane messageTabbedPane = new JideTabbedPane(); private JideScrollPane messagePayloadPanel = new JideScrollPane(); private JideScrollPane headerScrollPane = new JideScrollPane(); private final JPanel bottomPanel = new JPanel(new BorderLayout()); private final Map<FIXMessage, JComponent> renderedLRUMap = new LRUMap(100); public abstract Collection<Object> getSelectedMessages(); public AbstractFIXBrowserDocumentComponent(String title) { super(new JPanel(), title); this.title = title; this.topPanel = (JPanel) getComponent(); } protected void setCachedRows(List<FIXMessage> cachedRows) { this.cachedRows = cachedRows; } protected Collection<FIXMessage> getCachedRows() { return cachedRows; } protected abstract Component getHeaderComponent(); protected Component getBottomComponent() { return bottomPanel; } protected void updateMessageTabbedPane(FIXMessage m) { final int index = getMessageTabbedPane().getSelectedIndex(); getMessageTabbedPane().removeAll(); getMessageTabbedPane().add("Parsed", getMessagePayloadPanel()); getMessageTabbedPane().add("Hex", createHexPanel(m)); getMessageTabbedPane().add("Text", createPrettyPrintPanel(m)); if (index >= 0) { getMessageTabbedPane().setSelectedIndex(index); } } public void addMessage(FIXMessage message) { synchronized (cachedRows) { try { cachedRows.add(message); } catch (Exception ex) { log.error(ex.getMessage(), ex); } } } protected void init() { headerScrollPane.setViewportView(getHeaderComponent()); bottomPanel.add(new FilterablePanel(), BorderLayout.NORTH); bottomPanel.add(getStatusPanel(), BorderLayout.SOUTH); getTopPanel().setLayout(new BorderLayout()); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); splitPane.setDividerLocation(200); splitPane.setOneTouchExpandable(false); splitPane.setContinuousLayout(false); splitPane.add(headerScrollPane, "top"); splitPane.add(messageTabbedPane, "bottom"); messageTabbedPane.setTabPlacement(JTabbedPane.BOTTOM); getTopPanel().add(splitPane, BorderLayout.CENTER); getTopPanel().add(getBottomComponent(), BorderLayout.SOUTH); HermesBrowser.getBrowser().addDocumentComponent(this); addDocumentComponentListener(this); updateTableRows(true); } /** * When a user selects a row, bring up the messages in the below panel. Uses * the MessengerRenderer's that have been configured with the first one * returning a panel being the one used. */ public void doSelectionChanged(FIXMessageTable table, ListSelectionEvent e) { int selectedRow = table.getSelectedRow(); if (table.getRowCount() > selectedRow && selectedRow >= 0) { final int row = selectedRow; final FIXMessage m = table.getMessageAt(row); // // // // Keep the selected row visible. // // table.scrollRectToVisible(table.getCellRect(selectedRow, 0, true)); try { if (!renderedLRUMap.containsKey(m)) { JComponent rendered = FIXUtils.createView(m, true, true); renderedLRUMap.put(m, rendered); } getMessagePayloadPanel().setViewportView(renderedLRUMap.get(m)); } catch (Exception e1) { log.error(e1.getMessage(), e1); JTextArea text = new JTextArea(e1.getMessage()); text.setEditable(false); getMessagePayloadPanel().setViewportView(text); } updateMessageTabbedPane(m); } } public JPanel getTopPanel() { return topPanel; } /* * (non-Javadoc) * * @see hermes.browser.tasks.TaskListener#onStarted() */ public void onStarted(Task task) { // NOP } public void onThrowable(Task task, Throwable t) { // NOP } /* * (non-Javadoc) * * @see hermes.browser.tasks.TaskListener#onStatus(java.lang.String) */ public void onStatus(Task task, final String status) { SwingRunner.invokeLater(new Runnable() { public void run() { statusMessage.setText(status); } }); } public boolean isTaskStopped() { return taskStopped; } protected abstract void updateTableRows(final boolean reschedule); /* * (non-Javadoc) * * @see hermes.browser.tasks.TaskListener#onStopped() */ public void onStopped(Task task) { updateTableRows(false); taskStopped = true; } public void setStatusText(String text) { statusMessage.setText(text); } protected void doClose() { if (task != null) { task.stop(); } renderedLRUMap.clear(); } public void documentComponentDocked(DocumentComponentEvent arg0) { // TODO Auto-generated method stub } public void documentComponentFloated(DocumentComponentEvent arg0) { // TODO Auto-generated method stub } public void documentComponentMoved(DocumentComponentEvent arg0) { // NOP } public void documentComponentMoving(DocumentComponentEvent arg0) { // NOP } /* * (non-Javadoc) * * @see * com.jidesoft.document.DocumentComponentListener#documentComponentActivated * (com.jidesoft.document.DocumentComponentEvent) */ public void documentComponentActivated(DocumentComponentEvent arg0) { } /* * (non-Javadoc) * * @see * com.jidesoft.document.DocumentComponentListener#documentComponentClosed * (com.jidesoft.document.DocumentComponentEvent) */ public void documentComponentClosed(DocumentComponentEvent arg0) { doClose(); } public void documentComponentClosing(DocumentComponentEvent arg0) { // NOP } public void documentComponentDeactivated(DocumentComponentEvent arg0) { // NOP } public void documentComponentOpened(DocumentComponentEvent arg0) { // NOP } protected JPanel getStatusPanel() { if (statusPanel == null) { statusPanel = new JPanel(); statusPanel.setLayout(new java.awt.BorderLayout()); statusPanel.setAlignmentY(java.awt.Component.BOTTOM_ALIGNMENT); statusMessage.setText("Reading..."); statusMessage.setBorder(new EtchedBorder()); statusPanel.add(statusMessage); } return statusPanel; } public String getTooltip() { return getTitle(); } public Icon getIcon() { return IconCache.getIcon("hermes.file.fix"); } public void setTask(Task task) { this.task = task; task.addTaskListener(this); } @Override public String getTitle() { return title; } public boolean isRunning() { return !taskStopped; } protected Component createPrettyPrintPanel(FIXMessage m) { final JTextArea textArea = new JTextArea(); textArea.setEditable(false); textArea.setFont(Font.decode("Monospaced-PLAIN-12")); byte[] bytes = null; try { textArea.setText(FIXUtils.prettyPrint(m)); } catch (Throwable e) { textArea.setText(e.getMessage()); log.error("exception converting message to byte[]: ", e); } textArea.setCaretPosition(0); return SwingUtils.createJScrollPane(textArea); } protected Component createHexPanel(FIXMessage m) { final JTextArea textArea = new JTextArea(); textArea.setEditable(false); textArea.setFont(Font.decode("Monospaced-PLAIN-12")); byte[] bytes = null; try { textArea.setText(DumpUtils.dumpBinary(m.getBytes(), DumpUtils.DUMP_AS_HEX_AND_ALPHA)); } catch (Throwable e) { textArea.setText(e.getMessage()); log.error("exception converting message to byte[]: ", e); } textArea.setCaretPosition(0); final JScrollPane scrollPane = new JScrollPane(); scrollPane.setViewportView(textArea); return scrollPane; } public int getScreenUpdateTimeout() { return screenUpdateTimeout; } protected JideScrollPane getMessagePayloadPanel() { return messagePayloadPanel; } protected JideTabbedPane getMessageTabbedPane() { return messageTabbedPane; } }