package org.marketcetera.photon.views; import java.util.concurrent.Callable; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.IMemento; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.part.ViewPart; import org.marketcetera.core.ClassVersion; import org.marketcetera.messagehistory.ReportHolder; import org.marketcetera.photon.Messages; import org.marketcetera.photon.ui.EventListContentProvider; import org.marketcetera.photon.ui.IndexedTableViewer; import org.marketcetera.photon.ui.MessageListTableFormat; import org.marketcetera.photon.ui.TableComparatorChooser; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.SortedList; import ca.odell.glazedlists.gui.TableFormat; /* $License$ */ @ClassVersion("$Id: MessagesViewBase.java 16154 2012-07-14 16:34:05Z colin $") //$NON-NLS-1$ public abstract class MessagesViewBase<T> extends ViewPart implements Messages { public static final String COLUMN_ORDER_KEY = "COLUMN_ORDER"; //$NON-NLS-1$ public static final String COLUMN_ORDER_DELIMITER = ","; //$NON-NLS-1$ public static final String COLUMN_WIDTH_KEY = "COLUMN_WIDTH"; //$NON-NLS-1$ public static final String COLUMN_WIDTH_DELIMITER = ","; //$NON-NLS-1$ public static final String SORT_BY_COLUMN_KEY = "SORT_BY_COLUMN"; //$NON-NLS-1$ private Table messageTable; private IndexedTableViewer messagesViewer; private IToolBarManager toolBarManager; private TableFormat<T> tableFormat; private TableComparatorChooser<T> chooser; private Clipboard clipboard; private CopyMessagesAction copyMessagesAction; private EventList<T> rawInputList; private final boolean sortableColumns; private IMemento viewStateMemento; private IAction selectAllAction; public MessagesViewBase() { this(true); } public MessagesViewBase(boolean sortableColumns) { this.sortableColumns = sortableColumns; } protected void formatTable(Table messageTable) { messageTable.getVerticalBar().setEnabled(true); messageTable.setBackground( messageTable.getDisplay().getSystemColor( SWT.COLOR_INFO_BACKGROUND)); messageTable.setForeground( messageTable.getDisplay().getSystemColor( SWT.COLOR_INFO_FOREGROUND)); messageTable.setHeaderVisible(true); for (int i = 0; i < messageTable.getColumnCount(); i++) { messageTable.getColumn(i).setMoveable(true); } } @SuppressWarnings("unchecked") //$NON-NLS-1$ @Override public void createPartControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().applyTo(composite); GridData gridData = new GridData(GridData.FILL, GridData.FILL, true, true); composite.setLayoutData(gridData); messageTable = createMessageTable(composite); messagesViewer = createTableViewer(messageTable, getEnumValues()); tableFormat = (TableFormat<T>)messagesViewer.getLabelProvider(); formatTable(messageTable); restoreColumnWidth(viewStateMemento); restoreColumnOrder(viewStateMemento); toolBarManager = getViewSite().getActionBars().getToolBarManager(); initializeToolBar(toolBarManager); copyMessagesAction = new CopyMessagesAction(getClipboard(), messageTable, COPY_LABEL.getText()); IWorkbench workbench = PlatformUI.getWorkbench(); ISharedImages platformImages = workbench.getSharedImages(); copyMessagesAction.setImageDescriptor(platformImages .getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); copyMessagesAction.setDisabledImageDescriptor(platformImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED)); Object menuObj = messageTable.getData(MenuManager.class.toString()); if (menuObj != null && menuObj instanceof MenuManager) { MenuManager menuManager = (MenuManager) menuObj; menuManager.add(copyMessagesAction); } createSelectAllAction(); hookGlobalActions(); } protected abstract void initializeToolBar(IToolBarManager theToolBarManager); protected abstract Enum<?>[] getEnumValues(); protected void packColumns(final Table table) { for (int i = 0; i < table.getColumnCount(); i++) { table.getColumn(i).pack(); } } @Override public void init(IViewSite site, IMemento memento) throws PartInitException { super.init(site, memento); this.viewStateMemento = memento; } @Override public void saveState(IMemento memento) { super.saveState(memento); saveColumnOrder(memento); saveSortByColumn(memento); saveColumnWidth(memento); } protected String serializeColumnOrder(int[] columnOrder) { StringBuilder sb = new StringBuilder(); for(int columnNumber : columnOrder) { sb.append(columnNumber); sb.append(COLUMN_ORDER_DELIMITER); } return sb.toString(); } protected int[] deserializeDelimitedIntegersIntoArray(String delimiter, String delimitedValue) { if (delimitedValue == null) { return new int[0]; } String[] returnAsStringArray = delimitedValue.split(delimiter); if (returnAsStringArray == null || returnAsStringArray.length == 0) { return new int[0]; } int[] returnAsIntArray = new int[returnAsStringArray.length]; for(int index = 0; index < returnAsIntArray.length; ++index) { try { returnAsIntArray[index] = Integer.parseInt(returnAsStringArray[index]); } catch(Exception anyException) { // TODO Log? // org.marketcetera.photon.PhotonPlugin.getMainConsoleLogger().warn("Failed to load column order.", anyException); return new int[0]; } } return returnAsIntArray; } protected int[] deserializeColumnOrder(String delimitedValue) { return deserializeDelimitedIntegersIntoArray(COLUMN_ORDER_DELIMITER, delimitedValue); } protected void saveColumnOrder(IMemento memento) { if (memento == null) return; int[] columnOrder = messageTable.getColumnOrder(); String serializedColumnOrder = serializeColumnOrder(columnOrder); memento.putString(COLUMN_ORDER_KEY, serializedColumnOrder); } protected void restoreColumnOrder(IMemento memento) { try { if (memento == null) return; String delimitedColumnOrder = memento.getString(COLUMN_ORDER_KEY); int[] columnOrder = deserializeColumnOrder(delimitedColumnOrder); if(columnOrder != null && columnOrder.length > 0) { messageTable.setColumnOrder(columnOrder); } } catch (Throwable t){ // do nothing } } protected void restoreSortByColumn(IMemento memento) { if (memento == null) return; String sortByColumn = memento.getString(SORT_BY_COLUMN_KEY); if (sortByColumn != null && sortByColumn.length() > 0 && chooser != null) { chooser.fromString(sortByColumn); } } protected void saveSortByColumn(IMemento memento) { if (memento == null) return; memento.putString(SORT_BY_COLUMN_KEY, chooser.toString()); } protected void saveColumnWidth(IMemento memento) { if (memento == null) return; TableColumn[] columns = messageTable.getColumns(); StringBuilder sb = new StringBuilder(); for (TableColumn col : columns) { int width = col.getWidth(); sb.append(width); sb.append(COLUMN_WIDTH_DELIMITER); } memento.putString(COLUMN_WIDTH_KEY, sb.toString()); } protected void restoreColumnWidth(IMemento memento) { try { if (memento == null) { packColumns(messageTable); return; } String delimitedColumnWidth = memento.getString(COLUMN_WIDTH_KEY); int[] columnWidth = deserializeDelimitedIntegersIntoArray( COLUMN_WIDTH_DELIMITER, delimitedColumnWidth); if(columnWidth != null && columnWidth.length > 0) { TableColumn[] columns = messageTable.getColumns(); for (int i = 0; i < columns.length; i++) { columns[i].setWidth(columnWidth[i]); } } } catch (Throwable t){ // do nothing } } protected Table createMessageTable(Composite parent) { Table messageTable = new Table(parent, SWT.MULTI | SWT.FULL_SELECTION | SWT.V_SCROLL); GridData messageTableLayout = new GridData(); messageTableLayout.horizontalSpan = 2; messageTableLayout.verticalSpan = 1; messageTableLayout.horizontalAlignment = GridData.FILL; messageTableLayout.verticalAlignment = GridData.FILL; messageTableLayout.grabExcessHorizontalSpace = true; messageTableLayout.grabExcessVerticalSpace = true; messageTable.setLayoutData(messageTableLayout); return messageTable; } protected IndexedTableViewer createTableViewer(Table aMessageTable, Enum<?>[] enums) { IndexedTableViewer aMessagesViewer = new IndexedTableViewer(aMessageTable); getSite().setSelectionProvider(aMessagesViewer); aMessagesViewer.setContentProvider(new EventListContentProvider<ReportHolder>()); aMessagesViewer.setLabelProvider(new MessageListTableFormat(aMessageTable, enums, getSite())); return aMessagesViewer; } public IndexedTableViewer getMessagesViewer() { return messagesViewer; } public void setInput(EventList<T> input) { SortedList<T> extractedList = new SortedList<T>(rawInputList = input); if (sortableColumns){ if (chooser != null){ chooser.dispose(); chooser = null; } chooser = TableComparatorChooser.install(messagesViewer.getTable(), tableFormat, extractedList, false); restoreSortByColumn(viewStateMemento); } messagesViewer.setInput(extractedList); } public EventList<T> getInput() { return rawInputList; } private void hookGlobalActions(){ getViewSite().getActionBars() .setGlobalActionHandler(ActionFactory.COPY.getId(), copyMessagesAction); getViewSite().getActionBars().setGlobalActionHandler( ActionFactory.SELECT_ALL.getId(), selectAllAction); } @Override public void dispose() { if (clipboard != null) clipboard.dispose(); super.dispose(); } protected Clipboard getClipboard() { if (clipboard == null){ clipboard = new Clipboard(getSite().getShell().getDisplay()); } return clipboard; } @Override public void setFocus() { messageTable.setFocus(); } private void createSelectAllAction() { selectAllAction = new Action() { @Override public void run() { getMessagesViewer().getTable().selectAll(); } }; selectAllAction.setActionDefinitionId( "org.eclipse.ui.edit.selectAll" ); //$NON-NLS-1$ } /** * Sets the view cursor to the system wait cursor while the given block executes. * * <p>At the close of the given block, the cursor is guaranteed to be reset to the state it was in at the start of the block. * * @param inSite a <code>IWorkbenchPartSite</code> value * @param inBlock a <code>Callable<V></code> value containing the code to execute while the wait cursor is displayed * @return a <code>V</code> value * @throws Exception if an error occurs during the block execution */ public static <V> V doWaitCursor(IWorkbenchPartSite inSite, Callable<V> inBlock) throws Exception { Cursor initialCursor = inSite.getShell().getCursor(); try { inSite.getShell().setCursor(inSite.getShell().getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); return inBlock.call(); } finally { inSite.getShell().setCursor(initialCursor); } } /** * Sets the view cursor to the system wait cursor while the given block executes. * * <p>At the close of the given block, the cursor is guaranteed to be reset to the state it was in at the start of the block. * * @param inSite a <code>IWorkbenchPartSite</code> value * @param inBlock a <code>Runnable</code> value containing the code to execute while the wait cursor is displayed * @throws Exception if an error occurs during the block execution */ public static void doWaitCursor(IWorkbenchPartSite inSite, Runnable inBlock) { Cursor initialCursor = inSite.getShell().getCursor(); try { inSite.getShell().setCursor(inSite.getShell().getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); inBlock.run(); } finally { inSite.getShell().setCursor(initialCursor); } } }