package org.marketcetera.photon.views.fixmessagedetail; import java.util.ArrayList; import java.util.Iterator; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.part.ViewPart; import org.marketcetera.core.ClassVersion; import org.marketcetera.messagehistory.ReportHolder; import org.marketcetera.photon.EclipseUtils; import org.marketcetera.photon.Messages; import org.marketcetera.photon.PhotonPlugin; import org.marketcetera.photon.ui.EventListContentProvider; import org.marketcetera.photon.ui.IndexedTableViewer; import org.marketcetera.photon.ui.TableComparatorChooser; import org.marketcetera.photon.views.AbstractFIXMessagesView; import org.marketcetera.quickfix.FIXDataDictionary; import org.marketcetera.quickfix.FIXMessageUtil; import org.marketcetera.quickfix.FIXValueExtractor; import quickfix.DataDictionary; import quickfix.Field; import quickfix.FieldMap; import quickfix.Message; import quickfix.field.MsgType; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.SortedList; /* $License$ */ @ClassVersion("$Id: FIXMessageDetailView.java 16154 2012-07-14 16:34:05Z colin $") //$NON-NLS-1$ public class FIXMessageDetailView extends ViewPart implements ISelectionListener, IFIXMessageDetail, Messages { public static final String ID = "org.marketcetera.photon.views.FIXMessageDetailView"; //$NON-NLS-1$ private final int MESSAGE_TEXT_WIDTH_HINT = 80; private FormToolkit formToolkit; private ScrolledForm form = null; private Table messageTable; private IndexedTableViewer messageViewer; private Composite messageTextComposite; private Text messageText; private Clipboard clipboard; private TableComparatorChooser<FIXMessageDetailTableRow> comparatorChooser; private FIXMessageDetailLabelProvider labelProvider; private FormToolkit getFormToolkit() { if (formToolkit == null) { formToolkit = new FormToolkit(Display.getCurrent()); } return formToolkit; } private Composite getDefaultOuterParent() { return form.getBody(); } @Override public void createPartControl(Composite parent) { getViewSite().getWorkbenchWindow().getSelectionService().addSelectionListener( this ); createOuterForm(parent); createFieldTable(); createMessageDetailComposite(); createLayoutDataForOuterWidgets(); clipboard = new Clipboard(getSite().getShell().getDisplay()); } public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (part instanceof AbstractFIXMessagesView) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; boolean shouldClear = true; // only display message detail for a single message if (structuredSelection.size() == 1) { ReportHolder messageHolder = (ReportHolder) structuredSelection .getFirstElement(); if (messageHolder != null) { Message message = messageHolder.getMessage(); shouldClear = false; showMessage(message); } } if (shouldClear) { showMessage(null); // clear the view } } } @Override public void dispose() { getViewSite().getWorkbenchWindow().getSelectionService().removeSelectionListener( this ); if (clipboard != null && !clipboard.isDisposed()) { clipboard.dispose(); } } private void createLayoutDataForOuterWidgets() { { FormData layoutData = new FormData(); layoutData.left = new FormAttachment(0); layoutData.top = new FormAttachment(0); layoutData.right = new FormAttachment(100); layoutData.bottom = new FormAttachment(75); messageTable.setLayoutData(layoutData); } { FormData layoutData = new FormData(); layoutData.left = new FormAttachment(0); layoutData.top = new FormAttachment(messageTable); layoutData.right = new FormAttachment(100); layoutData.bottom = new FormAttachment(100); messageTextComposite.setLayoutData(layoutData); } } @Override public void setFocus() { messageTable.setFocus(); } private void createOuterForm(Composite parent) { form = getFormToolkit().createScrolledForm(parent); form.setLayout(new FillLayout()); form.getBody().setLayout(new FormLayout()); } private void createFieldTable() { messageTable = getFormToolkit().createTable(getDefaultOuterParent(), SWT.MULTI | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.BORDER); messageTable.setHeaderVisible(true); messageViewer = new IndexedTableViewer(messageTable); getSite().setSelectionProvider(messageViewer); labelProvider = new FIXMessageDetailLabelProvider(messageTable); messageViewer.setLabelProvider(labelProvider); messageViewer .setContentProvider(new EventListContentProvider<FIXMessageDetailTableRow>()); } private Label messageDetailLabel; private void createMessageDetailComposite() { messageTextComposite = getFormToolkit().createComposite( getDefaultOuterParent(), SWT.BORDER); messageDetailLabel = new Label(messageTextComposite, SWT.WRAP); messageDetailLabel.setBackground(getDefaultOuterParent() .getBackground()); messageDetailLabel.setText(FULL_MESSAGE_LABEL.getText()); Button copyRawMessageButton = new Button(messageTextComposite, SWT.FLAT); copyRawMessageButton.setText(COPY_MESSAGE_LABEL.getText()); copyRawMessageButton.setToolTipText(COPY_MESSAGE_TOOLTIPS.getText()); Button copyTableButton = new Button(messageTextComposite, SWT.FLAT); copyTableButton.setText(COPY_TABLE_LABEL.getText()); copyTableButton.setToolTipText(COPY_TABLE_TOOLTIPS.getText()); messageText = getFormToolkit().createText(messageTextComposite, "", //$NON-NLS-1$ SWT.V_SCROLL | SWT.READ_ONLY | SWT.WRAP | SWT.MULTI); createLayoutDataForMessageDetailComposite(messageDetailLabel, copyRawMessageButton, copyTableButton); addMessageDetailCompositeListeners(copyRawMessageButton, copyTableButton); } private void createLayoutDataForMessageDetailComposite( Label fullMessageLabel, Button copyRawMessageButton, Button copyTableButton) { { FormLayout layout = new FormLayout(); messageTextComposite.setLayout(layout); } { FormData data = new FormData(); data.left = new FormAttachment(0); data.top = new FormAttachment(0); data.right = new FormAttachment(copyRawMessageButton); // Two rows of text are possible when there's a preferences link. data.height = 2 * EclipseUtils.getTextAreaSize(fullMessageLabel, null, 1, 1.2).y; fullMessageLabel.setLayoutData(data); } { FormData data = new FormData(); data.right = new FormAttachment(copyTableButton); data.top = new FormAttachment(0); copyRawMessageButton.setLayoutData(data); } { FormData data = new FormData(); data.right = new FormAttachment(100); data.top = new FormAttachment(0); copyTableButton.setLayoutData(data); } { FormData data = new FormData(); data.left = new FormAttachment(0); data.right = new FormAttachment(100); data.bottom = new FormAttachment(100); data.top = new FormAttachment(fullMessageLabel); data.width = MESSAGE_TEXT_WIDTH_HINT; data.height = 40; messageText.setLayoutData(data); } } private void addMessageDetailCompositeListeners( Button copyRawMessageButton, Button copyTableButton) { copyRawMessageButton.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { String textStr = messageText.getText(); if (textStr != null && textStr.length() > 0) { messageText.selectAll(); messageText.copy(); messageText.setSelection(0, 0); } } }); copyTableButton.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { String textStr = getTableAsFormattedString(); copyToClipboard(textStr); } }); } private String getTableAsFormattedString() { TableItem[] tableItems = messageTable.getItems(); if (tableItems == null) { return ""; //$NON-NLS-1$ } StringBuilder tableAsString = new StringBuilder(); for (TableItem tableItem : tableItems) { Object dataObj = tableItem.getData(); if (dataObj instanceof FIXMessageDetailTableRow) { FIXMessageDetailTableRow row = (FIXMessageDetailTableRow) dataObj; String rowAsStr = row.toFormattedString(); tableAsString.append(rowAsStr); } } return tableAsString.toString(); } private void copyToClipboard(String textToCopy) { if (textToCopy == null) { return; } final Transfer[] dataTypes = { TextTransfer.getInstance() }; Object[] data = { textToCopy }; clipboard.setContents(data, dataTypes); } public void showMessage(Message fixMessage) { PhotonPlugin.getMainConsoleLogger().debug( getClass().getName() + ": " + fixMessage); //$NON-NLS-1$ ArrayList<FIXMessageDetailTableRow> rows = createRowsFromMessage(fixMessage); BasicEventList<FIXMessageDetailTableRow> eventList = new BasicEventList<FIXMessageDetailTableRow>(); eventList.addAll(rows); SortedList<FIXMessageDetailTableRow> sortedList = new SortedList<FIXMessageDetailTableRow>( eventList); if (comparatorChooser != null) { comparatorChooser.dispose(); comparatorChooser = null; } comparatorChooser = TableComparatorChooser.install(messageTable, labelProvider, sortedList, false); // This code sets an initial sort order and is currently disabled. // final int initialSortIndex = // FIXMessageDetailColumnType.Tag.getIndex(); // comparatorChooser.appendComparator(initialSortIndex, 0, false); // comparatorChooser.updateSortIndicatorIcon(initialSortIndex); messageViewer.setInput(sortedList); String messageTextStr = getFIXMessageDisplayString(fixMessage); messageText.setText(messageTextStr); } private ArrayList<FIXMessageDetailTableRow> createRowsFromMessage( Message fixMessage) { if (fixMessage == null) { return new ArrayList<FIXMessageDetailTableRow>(); } ArrayList<FIXMessageDetailTableRow> rows = new ArrayList<FIXMessageDetailTableRow>(); FIXDataDictionary fixDictionary = PhotonPlugin.getDefault() .getFIXDataDictionary(); String msgType = ""; //$NON-NLS-1$ try { msgType = fixMessage.getHeader().getString(MsgType.FIELD); } catch (Exception ex) { /* do nothing */ } // Show all fields that are set on the message. addFieldsFromMap(fixMessage.getHeader(), rows, fixDictionary, msgType ); addFieldsFromMap(fixMessage, rows, fixDictionary, msgType); addFieldsFromMap(fixMessage.getTrailer(), rows, fixDictionary, msgType); return rows; } private void addFieldsFromMap(FieldMap map, ArrayList<FIXMessageDetailTableRow> rows, FIXDataDictionary fixDictionary, String msgType) { Iterator<?> it = map.iterator(); while (it.hasNext()){ Field<?> aField = (Field<?>) it.next(); addFIXMessageDetailTableRow(map, aField.getTag(), rows, fixDictionary, msgType); } } private void addFIXMessageDetailTableRow(FieldMap map, int fieldNumber, ArrayList<FIXMessageDetailTableRow> rows, FIXDataDictionary fixDictionary, String msgType ) { if (map.isSetField(fieldNumber)) { DataDictionary dict = fixDictionary.getDictionary(); String fieldValueActual = FIXValueExtractor.fieldValueFromMap(map, fieldNumber, dict, false).toString(); String fieldValueReadable = ""; //$NON-NLS-1$ if (dict.hasFieldValue(fieldNumber)){ Object fieldValueFromMap = FIXValueExtractor.fieldValueFromMap(map, fieldNumber, dict, true); fieldValueReadable = (fieldValueFromMap == null) ? fieldValueActual : fieldValueFromMap.toString(); } String fieldName = fixDictionary.getHumanFieldName(fieldNumber); boolean required = FIXMessageUtil.isRequiredField(msgType, fieldNumber); FIXMessageDetailTableRow newRow = new FIXMessageDetailTableRow( fieldName, fieldNumber, fieldValueActual, fieldValueReadable, required); rows.add(newRow); } } private String getFIXMessageDisplayString(Message fixMessage) { String messageTextStr = ""; //$NON-NLS-1$ if (fixMessage != null) { String fixStr = fixMessage.toString(); if (fixStr != null) { fixStr = fixStr.replace('\001', ' '); } messageTextStr = fixStr; } return messageTextStr; } }