/* * Copyright (c) 2004-2011 Marco Maccaferri and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Marco Maccaferri - initial API and implementation */ package org.eclipsetrader.ui.internal.trading; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import org.eclipse.core.runtime.IAdapterManager; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; 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.IWorkbenchActionConstants; import org.eclipse.ui.PartInitException; import org.eclipse.ui.XMLMemento; import org.eclipse.ui.part.ViewPart; import org.eclipsetrader.core.trading.BrokerException; import org.eclipsetrader.core.trading.IOrder; import org.eclipsetrader.core.trading.IOrderChangeListener; import org.eclipsetrader.core.trading.IOrderMonitor; import org.eclipsetrader.core.trading.IOrderStatus; import org.eclipsetrader.core.trading.ITradingService; import org.eclipsetrader.core.trading.OrderChangeEvent; import org.eclipsetrader.core.trading.OrderDelta; import org.eclipsetrader.ui.internal.UIActivator; import org.eclipsetrader.ui.trading.AveragePriceColumn; import org.eclipsetrader.ui.trading.DateTimeColumn; import org.eclipsetrader.ui.trading.FilledQuantityColumn; import org.eclipsetrader.ui.trading.OrderIdColumn; import org.eclipsetrader.ui.trading.OrdersLabelProviderWrapper; import org.eclipsetrader.ui.trading.PriceColumn; import org.eclipsetrader.ui.trading.QuantityColumn; import org.eclipsetrader.ui.trading.SecurityNameColumn; import org.eclipsetrader.ui.trading.SideColumn; import org.eclipsetrader.ui.trading.StatusColumn; import org.eclipsetrader.ui.trading.TypeColumn; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; public class OrdersView extends ViewPart { public static final String VIEW_ID = "org.eclipsetrader.ui.views.orders"; //$NON-NLS-1$ public static final String K_VISIBLE_COLUMNS = "VISIBLE_COLUMNS"; //$NON-NLS-1$ private CTabFolder tabFolder; private TableViewer all; private TableViewer pending; private TableViewer filled; private TableViewer canceled; private TableViewer rejected; private ProxySelectionProvider selectionProvider; private IMemento memento; private IDialogSettings dialogSettings; private ServiceReference serviceReference; private ITradingService service; private IOrderChangeListener orderChangedListener = new IOrderChangeListener() { @Override public void orderChanged(OrderChangeEvent event) { IAdapterManager adapterManager = Platform.getAdapterManager(); for (OrderDelta delta : event.deltas) { PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) adapterManager.getAdapter(delta.getOrder(), PropertyChangeSupport.class); if (propertyChangeSupport != null) { if (delta.getKind() == OrderDelta.KIND_ADDED) { propertyChangeSupport.removePropertyChangeListener(propertyChangeListener); propertyChangeSupport.addPropertyChangeListener(propertyChangeListener); } else if (delta.getKind() == OrderDelta.KIND_REMOVED) { propertyChangeSupport.removePropertyChangeListener(propertyChangeListener); } } } try { tabFolder.getDisplay().asyncExec(new Runnable() { @Override public void run() { if (!tabFolder.isDisposed()) { all.refresh(); pending.refresh(); filled.refresh(); canceled.refresh(); rejected.refresh(); } } }); } catch (SWTException e) { // Do nothing } } }; private PropertyChangeListener propertyChangeListener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { try { tabFolder.getDisplay().asyncExec(new Runnable() { @Override public void run() { if (!tabFolder.isDisposed()) { all.refresh(); pending.refresh(); filled.refresh(); canceled.refresh(); rejected.refresh(); } } }); } catch (SWTException e) { // Do nothing } } }; private ControlAdapter columnControlListener = new ControlAdapter() { @Override public void controlResized(ControlEvent e) { TableColumn tableColumn = (TableColumn) e.widget; int index = tableColumn.getParent().indexOf(tableColumn); String[] enabledId = dialogSettings.getArray(K_VISIBLE_COLUMNS); memento.putInteger(enabledId[index], tableColumn.getWidth()); } }; private Action cancelAction; private Action columnsAction; public OrdersView() { } /* (non-Javadoc) * @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento) */ @Override public void init(IViewSite site, IMemento memento) throws PartInitException { super.init(site, memento); if (memento == null) { memento = XMLMemento.createWriteRoot("root"); //$NON-NLS-1$ } this.memento = memento; IDialogSettings pluginDialogSettings = UIActivator.getDefault().getDialogSettings(); dialogSettings = pluginDialogSettings.getSection(VIEW_ID); if (dialogSettings == null) { dialogSettings = pluginDialogSettings.addNewSection(VIEW_ID); dialogSettings.put("VISIBLE_COLUMNS", new String[] { //$NON-NLS-1$ OrderIdColumn.COLUMN_ID, DateTimeColumn.COLUMN_ID, SecurityNameColumn.COLUMN_ID, SideColumn.COLUMN_ID, TypeColumn.COLUMN_ID, QuantityColumn.COLUMN_ID, PriceColumn.COLUMN_ID, FilledQuantityColumn.COLUMN_ID, AveragePriceColumn.COLUMN_ID, StatusColumn.COLUMN_ID }); } initializeActions(); IToolBarManager toolbarManager = site.getActionBars().getToolBarManager(); toolbarManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); toolbarManager.add(cancelAction); IMenuManager menuManager = site.getActionBars().getMenuManager(); menuManager.add(new Separator("group.new")); //$NON-NLS-1$ menuManager.add(new GroupMarker("group.goto")); //$NON-NLS-1$ menuManager.add(new Separator("group.open")); //$NON-NLS-1$ menuManager.add(new GroupMarker("group.openWith")); //$NON-NLS-1$ menuManager.add(new Separator("group.show")); //$NON-NLS-1$ menuManager.add(new Separator("group.edit")); //$NON-NLS-1$ menuManager.add(new GroupMarker("group.reorganize")); //$NON-NLS-1$ menuManager.add(new GroupMarker("group.port")); //$NON-NLS-1$ menuManager.add(new Separator("group.generate")); //$NON-NLS-1$ menuManager.add(new Separator("group.search")); //$NON-NLS-1$ menuManager.add(new Separator("group.build")); //$NON-NLS-1$ menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); menuManager.add(new Separator("group.properties")); //$NON-NLS-1$ menuManager.appendToGroup("group.properties", columnsAction); //$NON-NLS-1$ site.getActionBars().updateActionBars(); } void initializeActions() { ISharedImages sharedImages = getViewSite().getWorkbenchWindow().getWorkbench().getSharedImages(); cancelAction = new Action(Messages.OrdersView_CancelAction) { @Override public void run() { IStructuredSelection selection = (IStructuredSelection) getSite().getSelectionProvider().getSelection(); if (!selection.isEmpty()) { for (Object o : selection.toList()) { try { ((IOrderMonitor) o).cancel(); } catch (BrokerException e) { e.printStackTrace(); } } } } }; cancelAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE)); cancelAction.setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE_DISABLED)); cancelAction.setEnabled(false); columnsAction = new Action(Messages.OrdersView_ColumnsAction) { @Override public void run() { OrdersColumnsDialog dlg = new OrdersColumnsDialog(getSite().getShell()); dlg.setVisibleId(dialogSettings.getArray(K_VISIBLE_COLUMNS)); if (dlg.open() == Window.OK) { dialogSettings.put(K_VISIBLE_COLUMNS, dlg.getVisibleId()); updateViewerColumns(all, true); updateViewerColumns(pending, false); updateViewerColumns(filled, false); updateViewerColumns(canceled, false); updateViewerColumns(rejected, false); all.refresh(); pending.refresh(); filled.refresh(); canceled.refresh(); rejected.refresh(); } } }; } /* (non-Javadoc) * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) */ @Override public void createPartControl(Composite parent) { createTabFolder(parent); tabFolder.setSelection(tabFolder.getItem(0)); tabFolder.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { TableViewer viewer = (TableViewer) ((CTabItem) e.item).getControl().getData("viewer"); //$NON-NLS-1$ if (viewer != null) { selectionProvider.setSelectionProvider(viewer); } } }); selectionProvider = new ProxySelectionProvider(); selectionProvider.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { boolean enabled = false; IStructuredSelection selection = (IStructuredSelection) event.getSelection(); for (Object o : selection.toList()) { if (((IOrderMonitor) o).getStatus() != IOrderStatus.Canceled) { enabled = true; } } cancelAction.setEnabled(enabled); } }); selectionProvider.setSelectionProvider(all); getSite().setSelectionProvider(selectionProvider); MenuManager menuMgr = new MenuManager("#popupMenu", "popupMenu"); //$NON-NLS-1$ //$NON-NLS-2$ menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager menuManager) { menuManager.add(new Separator("group.new")); //$NON-NLS-1$ menuManager.add(new GroupMarker("group.goto")); //$NON-NLS-1$ menuManager.add(new Separator("group.open")); //$NON-NLS-1$ menuManager.add(new GroupMarker("group.openWith")); //$NON-NLS-1$ menuManager.add(new Separator("group.show")); //$NON-NLS-1$ menuManager.add(new Separator("group.edit")); //$NON-NLS-1$ menuManager.add(new GroupMarker("group.reorganize")); //$NON-NLS-1$ menuManager.add(new GroupMarker("group.port")); //$NON-NLS-1$ menuManager.add(new Separator("group.generate")); //$NON-NLS-1$ menuManager.add(new Separator("group.search")); //$NON-NLS-1$ menuManager.add(new Separator("group.build")); //$NON-NLS-1$ menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); menuManager.add(new Separator("group.properties")); //$NON-NLS-1$ menuManager.appendToGroup("group.build", cancelAction); //$NON-NLS-1$ } }); all.getControl().setMenu(menuMgr.createContextMenu(all.getControl())); pending.getControl().setMenu(menuMgr.createContextMenu(pending.getControl())); filled.getControl().setMenu(menuMgr.createContextMenu(filled.getControl())); canceled.getControl().setMenu(menuMgr.createContextMenu(canceled.getControl())); rejected.getControl().setMenu(menuMgr.createContextMenu(rejected.getControl())); getSite().registerContextMenu(menuMgr, getSite().getSelectionProvider()); if (UIActivator.getDefault() != null) { BundleContext context = UIActivator.getDefault().getBundle().getBundleContext(); serviceReference = context.getServiceReference(ITradingService.class.getName()); if (serviceReference != null) { service = (ITradingService) context.getService(serviceReference); all.setInput(service); pending.setInput(service); filled.setInput(service); canceled.setInput(service); rejected.setInput(service); hookListeners(service.getOrders()); service.addOrderChangeListener(orderChangedListener); } } } /* (non-Javadoc) * @see org.eclipse.ui.part.WorkbenchPart#dispose() */ @Override public void dispose() { if (service != null) { service.removeOrderChangeListener(orderChangedListener); unhookListeners(service.getOrders()); } if (serviceReference != null) { BundleContext context = UIActivator.getDefault().getBundle().getBundleContext(); context.ungetService(serviceReference); } super.dispose(); } /* (non-Javadoc) * @see org.eclipse.ui.part.WorkbenchPart#setFocus() */ @Override public void setFocus() { tabFolder.setFocus(); } protected void createTabFolder(Composite parent) { tabFolder = new CTabFolder(parent, SWT.BOTTOM); tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); CTabItem tabItem = new CTabItem(tabFolder, SWT.NONE); tabItem.setText(Messages.OrdersView_AllTab); all = createViewer(tabFolder, true); tabItem.setControl(all.getControl()); tabItem = new CTabItem(tabFolder, SWT.NONE); tabItem.setText(Messages.OrdersView_PendingTab); pending = createViewer(tabFolder, false); pending.setFilters(new ViewerFilter[] { new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { IOrderMonitor order = (IOrderMonitor) element; return order.getStatus() == IOrderStatus.PendingCancel || order.getStatus() == IOrderStatus.PendingNew; } } }); tabItem.setControl(pending.getControl()); tabItem = new CTabItem(tabFolder, SWT.NONE); tabItem.setText(Messages.OrdersView_FilledTab); filled = createViewer(tabFolder, false); filled.setFilters(new ViewerFilter[] { new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { IOrderMonitor order = (IOrderMonitor) element; return order.getStatus() == IOrderStatus.Filled; } } }); tabItem.setControl(filled.getControl()); tabItem = new CTabItem(tabFolder, SWT.NONE); tabItem.setText(Messages.OrdersView_CanceledTab); canceled = createViewer(tabFolder, false); canceled.setFilters(new ViewerFilter[] { new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { IOrderMonitor order = (IOrderMonitor) element; return order.getStatus() == IOrderStatus.Canceled || order.getStatus() == IOrderStatus.Expired; } } }); tabItem.setControl(canceled.getControl()); tabItem = new CTabItem(tabFolder, SWT.NONE); tabItem.setText(Messages.OrdersView_RejectedTab); rejected = createViewer(tabFolder, false); rejected.setFilters(new ViewerFilter[] { new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { IOrderMonitor order = (IOrderMonitor) element; return order.getStatus() == IOrderStatus.Rejected; } } }); tabItem.setControl(rejected.getControl()); } /* (non-Javadoc) * @see org.eclipse.ui.part.ViewPart#saveState(org.eclipse.ui.IMemento) */ @Override public void saveState(IMemento memento) { memento.putMemento(this.memento); super.saveState(memento); } protected TableViewer createViewer(Composite parent, boolean wrapLabelProviders) { TableViewer viewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.MULTI); viewer.getTable().setHeaderVisible(true); viewer.setContentProvider(new ArrayContentProvider() { @Override public Object[] getElements(Object inputElement) { return ((ITradingService) inputElement).getOrders(); } }); viewer.setSorter(new ViewerSorter() { @Override public int compare(Viewer viewer, Object e1, Object e2) { IOrder o1 = ((IOrderMonitor) e1).getOrder(); IOrder o2 = ((IOrderMonitor) e2).getOrder(); return o2.getDate().compareTo(o1.getDate()); } }); updateViewerColumns(viewer, wrapLabelProviders); return viewer; } IConfigurationElement getConfigurationElement(String targetID) { IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint("org.eclipsetrader.ui.viewLabelProviders"); //$NON-NLS-1$ IConfigurationElement[] configElements = extensionPoint.getConfigurationElements(); for (int i = 0; i < configElements.length; i++) { if ("viewContribution".equals(configElements[i].getName())) { //$NON-NLS-1$ configElements = configElements[i].getChildren(); for (int j = 0; j < configElements.length; j++) { String strID = configElements[j].getAttribute("id"); //$NON-NLS-1$ if (targetID.equals(strID)) { return configElements[j]; } } break; } } return null; } protected void updateViewerColumns(TableViewer viewer, boolean wrapLabelProviders) { viewer.getTable().setRedraw(false); try { TableColumn[] tableColumn = viewer.getTable().getColumns(); for (int i = 0; i < tableColumn.length; i++) { tableColumn[i].dispose(); } String[] enabledId = dialogSettings.getArray(K_VISIBLE_COLUMNS); for (int i = 0; i < enabledId.length; i++) { IConfigurationElement element = getConfigurationElement(enabledId[i]); if (element == null) { continue; } int style = SWT.LEFT; if ("right".equals(element.getAttribute("orientation"))) { style = SWT.RIGHT; } else if ("center".equals(element.getAttribute("orientation"))) { style = SWT.CENTER; } TableViewerColumn viewerColumn = new TableViewerColumn(viewer, style); viewerColumn.getColumn().setText(element.getAttribute("name")); //$NON-NLS-1$ viewerColumn.getColumn().setWidth(memento != null && memento.getString(enabledId[i]) != null ? memento.getInteger(enabledId[i]) : 64); viewerColumn.getColumn().addControlListener(columnControlListener); try { ColumnLabelProvider labelProvider = (ColumnLabelProvider) element.createExecutableExtension("class"); //$NON-NLS-1$ if (wrapLabelProviders) { labelProvider = new OrdersLabelProviderWrapper(labelProvider); } viewerColumn.setLabelProvider(labelProvider); } catch (Exception e) { Status status = new Status(IStatus.WARNING, UIActivator.PLUGIN_ID, Messages.OrdersView_ErrorCreatingLabelProvider + enabledId[i], e); UIActivator.log(status); } } } finally { viewer.getTable().setRedraw(true); } } protected void hookListeners(IOrderMonitor[] order) { IAdapterManager adapterManager = Platform.getAdapterManager(); for (int i = 0; i < order.length; i++) { PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) adapterManager.getAdapter(order[i], PropertyChangeSupport.class); if (propertyChangeSupport != null) { propertyChangeSupport.removePropertyChangeListener(propertyChangeListener); propertyChangeSupport.addPropertyChangeListener(propertyChangeListener); } } } protected void unhookListeners(IOrderMonitor[] order) { IAdapterManager adapterManager = Platform.getAdapterManager(); for (int i = 0; i < order.length; i++) { PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) adapterManager.getAdapter(order[i], PropertyChangeSupport.class); if (propertyChangeSupport != null) { propertyChangeSupport.removePropertyChangeListener(propertyChangeListener); } } } }