org.eclipsetrader.ui.internal.views.Level2View.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipsetrader.ui.internal.views.Level2View.java

Source

/*
 * 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.views;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.ViewPart;
import org.eclipsetrader.core.feed.IBook;
import org.eclipsetrader.core.feed.IBookEntry;
import org.eclipsetrader.core.feed.IFeedConnector;
import org.eclipsetrader.core.feed.IFeedConnector2;
import org.eclipsetrader.core.feed.IFeedIdentifier;
import org.eclipsetrader.core.feed.IFeedService;
import org.eclipsetrader.core.feed.IFeedSubscription2;
import org.eclipsetrader.core.feed.ILastClose;
import org.eclipsetrader.core.feed.ISubscriptionListener;
import org.eclipsetrader.core.feed.ITodayOHL;
import org.eclipsetrader.core.feed.ITrade;
import org.eclipsetrader.core.feed.QuoteDelta;
import org.eclipsetrader.core.feed.QuoteEvent;
import org.eclipsetrader.core.instruments.ISecurity;
import org.eclipsetrader.core.internal.CoreActivator;
import org.eclipsetrader.core.markets.IMarket;
import org.eclipsetrader.core.markets.IMarketService;
import org.eclipsetrader.core.trading.IBroker;
import org.eclipsetrader.core.trading.ITradingService;
import org.eclipsetrader.ui.SelectionProvider;
import org.eclipsetrader.ui.UIConstants;
import org.eclipsetrader.ui.internal.UIActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

public class Level2View extends ViewPart {

    public static final String VIEW_ID = "org.eclipsetrader.ui.views.level2"; //$NON-NLS-1$
    private static final String VIEW_TITLE_TOOLTIP = Messages.Level2View_LevelII;

    private IMarketService marketService;
    private IFeedService feedService;

    private Text symbol;
    private Label activeConnector;

    private Composite summaryGroup;
    private Label time;
    private Label volume;
    private Label last;
    private Label high;
    private Label change;
    private Label low;
    private PressureBar pressureBar;
    private Table table;

    private DateFormat timeFormatter = DateFormat.getTimeInstance(SimpleDateFormat.MEDIUM);
    private NumberFormat numberFormatter = NumberFormat.getInstance();
    private NumberFormat priceFormatter = NumberFormat.getInstance();
    private NumberFormat percentageFormatter = NumberFormat.getInstance();

    private IMemento memento;
    private IFeedConnector2 connector;
    private IFeedSubscription2 subscription;
    private ITrade lastTrade;
    private ILastClose lastClose;
    private IBook lastBook;
    private IBook nextBook;

    private Action showMarketMakerAction;
    private Action hideSummaryAction;

    private ISubscriptionListener subscriptionListener = new ISubscriptionListener() {

        @Override
        public void quoteUpdate(QuoteEvent event) {
            onQuoteUpdate(event);
        }
    };

    private SelectionAdapter connectionSelectionListener = new SelectionAdapter() {

        @Override
        public void widgetSelected(SelectionEvent e) {
            if (e.widget.getData() instanceof IFeedConnector2) {
                IFeedConnector2 newConnector = (IFeedConnector2) e.widget.getData();
                onChangeConnector(newConnector);
            }
        }
    };

    private Runnable bookUpdateRunnable = new Runnable() {

        @Override
        public void run() {
            if (table == null || table.isDisposed()) {
                return;
            }
            if (lastBook != nextBook) {
                onBookUpdate(lastBook = nextBook);
            }
            Display.getDefault().timerExec(100, bookUpdateRunnable);
        }
    };

    public Level2View() {
        numberFormatter.setGroupingUsed(true);
        numberFormatter.setMinimumIntegerDigits(1);
        numberFormatter.setMinimumFractionDigits(0);
        numberFormatter.setMaximumFractionDigits(0);

        priceFormatter.setGroupingUsed(true);
        priceFormatter.setMinimumIntegerDigits(1);
        priceFormatter.setMinimumFractionDigits(2);
        priceFormatter.setMaximumFractionDigits(4);

        percentageFormatter.setGroupingUsed(true);
        percentageFormatter.setMinimumIntegerDigits(1);
        percentageFormatter.setMinimumFractionDigits(2);
        percentageFormatter.setMaximumFractionDigits(2);
    }

    /* (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);
        this.memento = memento;

        BundleContext context = CoreActivator.getDefault().getBundle().getBundleContext();

        ServiceReference<IMarketService> marketServiceReference = context.getServiceReference(IMarketService.class);
        marketService = context.getService(marketServiceReference);

        ServiceReference<IFeedService> feedServiceReference = context.getServiceReference(IFeedService.class);
        feedService = context.getService(feedServiceReference);

        showMarketMakerAction = new Action("Show Market Maker", IAction.AS_CHECK_BOX) { //$NON-NLS-1$

            @Override
            public void run() {
                updateViewer();
                if (lastBook != null) {
                    onBookUpdate(lastBook);
                }
            }
        };

        hideSummaryAction = new Action("Hide Summary", IAction.AS_CHECK_BOX) { //$NON-NLS-1$

            @Override
            public void run() {
                summaryGroup.setVisible(!isChecked());
                ((GridData) summaryGroup.getLayoutData()).exclude = isChecked();
                summaryGroup.getParent().layout();
            }
        };

        if (memento != null) {
            hideSummaryAction.setChecked("true".equals(memento.getString("hide-summary"))); //$NON-NLS-1$ //$NON-NLS-2$
        }

        IActionBars actionBars = site.getActionBars();

        IMenuManager menuManager = actionBars.getMenuManager();
        menuManager.add(showMarketMakerAction);
        menuManager.add(new Separator());
        menuManager.add(hideSummaryAction);

        actionBars.updateActionBars();

        site.setSelectionProvider(new SelectionProvider());
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
     */
    @Override
    public void createPartControl(Composite parent) {
        Composite content = new Composite(parent, SWT.NONE);
        GridLayout gridLayout = new GridLayout(1, false);
        gridLayout.marginWidth = gridLayout.marginHeight = 0;
        gridLayout.verticalSpacing = 0;
        content.setLayout(gridLayout);

        GC gc = new GC(content);
        gc.setFont(JFaceResources.getDialogFont());
        FontMetrics fontMetrics = gc.getFontMetrics();
        gc.dispose();

        Composite group = new Composite(content, SWT.NONE);
        group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        group.setLayout(new GridLayout(4, false));

        Label label = new Label(group, SWT.NONE);
        label.setText(Messages.Level2View_Symbol);
        symbol = new Text(group, SWT.BORDER);
        symbol.setLayoutData(new GridData(Dialog.convertWidthInCharsToPixels(fontMetrics, 15), SWT.DEFAULT));
        symbol.addFocusListener(new FocusAdapter() {

            @Override
            public void focusLost(FocusEvent e) {
                onSetSymbol();
            }
        });
        symbol.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                onSetSymbol();
            }
        });

        final ImageHyperlink connectorButton = new ImageHyperlink(group, SWT.NONE);
        connectorButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
        connectorButton.setImage(UIActivator.getDefault().getImageRegistry().get(UIConstants.TOOLBAR_ARROW_RIGHT));
        connectorButton.setToolTipText(Messages.Level2View_SelectDataSource);
        connectorButton.addHyperlinkListener(new IHyperlinkListener() {

            private Menu dropDownMenu;

            @Override
            public void linkActivated(HyperlinkEvent e) {
                if (dropDownMenu != null) {
                    dropDownMenu.dispose();
                }

                dropDownMenu = new Menu(connectorButton);
                List<IFeedConnector> c = Arrays.asList(feedService.getConnectors());
                Collections.sort(c, new Comparator<IFeedConnector>() {

                    @Override
                    public int compare(IFeedConnector o1, IFeedConnector o2) {
                        return o1.getName().compareTo(o2.getName());
                    }
                });
                for (IFeedConnector connector : c) {
                    if (connector instanceof IFeedConnector2) {
                        MenuItem menuItem = new MenuItem(dropDownMenu, SWT.CHECK);
                        menuItem.setText(connector.getName());
                        menuItem.setData(connector);
                        menuItem.setSelection(Level2View.this.connector == connector);
                        menuItem.addSelectionListener(connectionSelectionListener);
                    }
                }
                dropDownMenu.setVisible(true);
            }

            @Override
            public void linkEntered(HyperlinkEvent e) {
            }

            @Override
            public void linkExited(HyperlinkEvent e) {
            }
        });

        activeConnector = new Label(group, SWT.NONE);
        activeConnector.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        summaryGroup = createSummary(content);
        if (hideSummaryAction != null) {
            summaryGroup.setVisible(!hideSummaryAction.isChecked());
            ((GridData) summaryGroup.getLayoutData()).exclude = hideSummaryAction.isChecked();
        }

        pressureBar = new PressureBar(content, SWT.NONE);
        GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
        gridData.heightHint = 16;
        pressureBar.getControl().setLayoutData(gridData);

        createBookViewer(content);

        if (memento != null) {
            String s = memento.getString("symbol"); //$NON-NLS-1$
            if (s != null) {
                symbol.setText(s);
                ISecurity security = getSecurityFromSymbol(s);
                if (security != null) {
                    getSite().getSelectionProvider().setSelection(new StructuredSelection(security));
                    setPartName(security.getName());
                    setTitleToolTip(NLS.bind(VIEW_TITLE_TOOLTIP, new Object[] { security.getName() }));
                }
            }

            String id = memento.getString("connector"); //$NON-NLS-1$
            if (id != null) {
                IFeedConnector connector = feedService.getConnector(id);
                if (connector == null) {
                    connector = CoreActivator.getDefault().getDefaultConnector();
                }
                if (connector instanceof IFeedConnector2) {
                    this.connector = (IFeedConnector2) connector;
                    activeConnector.setText(this.connector.getName());
                }
            }

            if (s != null && connector != null) {
                subscription = this.connector.subscribeLevel2(s);

                subscription.addSubscriptionListener(subscriptionListener);

                lastClose = subscription.getLastClose();
                lastTrade = subscription.getTrade();
                update(subscription.getTodayOHL());
                update();
            }
        }

        Display.getDefault().timerExec(100, bookUpdateRunnable);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.ViewPart#saveState(org.eclipse.ui.IMemento)
     */
    @Override
    public void saveState(IMemento memento) {
        memento.putString("symbol", symbol.getText()); //$NON-NLS-1$
        if (connector != null) {
            memento.putString("connector", connector.getId()); //$NON-NLS-1$
        }
        if (hideSummaryAction.isChecked()) {
            memento.putString("hide-summary", "true"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        super.saveState(memento);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
     */
    @Override
    public void setFocus() {
        symbol.setFocus();
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#dispose()
     */
    @Override
    public void dispose() {
        if (subscription != null) {
            subscription.removeSubscriptionListener(subscriptionListener);
            subscription.dispose();
        }

        BundleContext context = CoreActivator.getDefault().getBundle().getBundleContext();

        ServiceReference<IMarketService> marketServiceReference = context.getServiceReference(IMarketService.class);
        context.ungetService(marketServiceReference);
        ServiceReference<IFeedService> feedServiceReference = context.getServiceReference(IFeedService.class);
        context.ungetService(feedServiceReference);

        super.dispose();
    }

    protected void createBookViewer(Composite parent) {
        Composite content = new Composite(parent, SWT.NONE);
        content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        TableColumnLayout tableLayout = new TableColumnLayout();
        content.setLayout(tableLayout);

        table = new Table(content, SWT.MULTI | SWT.FULL_SELECTION | SWT.NO_FOCUS | SWT.V_SCROLL);
        table.setHeaderVisible(true);
        table.setLinesVisible(false);

        table.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                table.deselectAll();
            }
        });

        ICommandService commandService = (ICommandService) getSite().getService(ICommandService.class);
        IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class);
        new Level2QuickTradeDecorator(table, commandService, handlerService);

        updateViewer();
    }

    protected void updateViewer() {
        TableColumnLayout tableLayout = (TableColumnLayout) table.getParent().getLayout();

        int columnIndex = 0;
        TableColumn tableColumn;

        if (showMarketMakerAction.isChecked()) {
            tableColumn = columnIndex < table.getColumnCount() ? table.getColumn(columnIndex)
                    : new TableColumn(table, SWT.CENTER);
            tableColumn.setText(Messages.Level2View_MM);
            tableLayout.setColumnData(tableColumn, new ColumnWeightData(5));
            columnIndex++;
        }

        tableColumn = columnIndex < table.getColumnCount() ? table.getColumn(columnIndex)
                : new TableColumn(table, SWT.CENTER);
        tableColumn.setText(Messages.Level2View_Number);
        tableLayout.setColumnData(tableColumn, new ColumnWeightData(showMarketMakerAction.isChecked() ? 5 : 6));
        columnIndex++;

        tableColumn = columnIndex < table.getColumnCount() ? table.getColumn(columnIndex)
                : new TableColumn(table, SWT.CENTER);
        tableColumn.setText(Messages.Level2View_Qty);
        tableLayout.setColumnData(tableColumn, new ColumnWeightData(showMarketMakerAction.isChecked() ? 22 : 24));
        columnIndex++;

        tableColumn = columnIndex < table.getColumnCount() ? table.getColumn(columnIndex)
                : new TableColumn(table, SWT.CENTER);
        tableColumn.setText(Messages.Level2View_Bid);
        tableLayout.setColumnData(tableColumn, new ColumnWeightData(showMarketMakerAction.isChecked() ? 18 : 20));
        columnIndex++;

        tableColumn = columnIndex < table.getColumnCount() ? table.getColumn(columnIndex)
                : new TableColumn(table, SWT.CENTER);
        tableColumn.setText(Messages.Level2View_Ask);
        tableLayout.setColumnData(tableColumn, new ColumnWeightData(showMarketMakerAction.isChecked() ? 18 : 20));
        columnIndex++;

        tableColumn = columnIndex < table.getColumnCount() ? table.getColumn(columnIndex)
                : new TableColumn(table, SWT.CENTER);
        tableColumn.setText(Messages.Level2View_Qty);
        tableLayout.setColumnData(tableColumn, new ColumnWeightData(showMarketMakerAction.isChecked() ? 21 : 24));
        columnIndex++;

        tableColumn = columnIndex < table.getColumnCount() ? table.getColumn(columnIndex)
                : new TableColumn(table, SWT.CENTER);
        tableColumn.setText(Messages.Level2View_Number);
        tableLayout.setColumnData(tableColumn, new ColumnWeightData(showMarketMakerAction.isChecked() ? 5 : 6));
        columnIndex++;

        if (showMarketMakerAction.isChecked()) {
            tableColumn = columnIndex < table.getColumnCount() ? table.getColumn(columnIndex)
                    : new TableColumn(table, SWT.CENTER);
            tableColumn.setText(Messages.Level2View_MM);
            tableLayout.setColumnData(tableColumn, new ColumnWeightData(5));
            columnIndex++;
        }

        while (table.getColumnCount() > columnIndex) {
            table.getColumn(table.getColumnCount() - 1).dispose();
        }

        table.getParent().layout();
    }

    protected Composite createSummary(Composite parent) {
        Composite content = new Composite(parent, SWT.NONE);
        content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        GridLayout gridLayout = new GridLayout(4, false);
        gridLayout.horizontalSpacing = gridLayout.horizontalSpacing * 2;
        content.setLayout(gridLayout);

        Label label = new Label(content, SWT.SEPARATOR | SWT.HORIZONTAL);
        label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 4, 1));

        label = new Label(content, SWT.NONE);
        label.setText(Messages.Level2View_Time);
        time = new Label(content, SWT.RIGHT);
        time.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        label = new Label(content, SWT.NONE);
        label.setText(Messages.Level2View_Volume);
        volume = new Label(content, SWT.RIGHT);
        volume.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        label = new Label(content, SWT.NONE);
        label.setText(Messages.Level2View_LastPrice);
        last = new Label(content, SWT.RIGHT);
        last.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        label = new Label(content, SWT.NONE);
        label.setText(Messages.Level2View_High);
        high = new Label(content, SWT.RIGHT);
        high.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        label = new Label(content, SWT.NONE);
        label.setText(Messages.Level2View_Change);
        change = new Label(content, SWT.RIGHT);
        change.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        label = new Label(content, SWT.NONE);
        label.setText(Messages.Level2View_Low);
        low = new Label(content, SWT.RIGHT);
        low.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        return content;
    }

    protected void updateBid(TableItem tableItem, IBookEntry entry) {
        int columnIndex = 0;

        if (entry != null) {
            if (showMarketMakerAction.isChecked()) {
                String s = entry.getMarketMaker() != null ? entry.getMarketMaker() : ""; //$NON-NLS-1$
                if (!s.equals(tableItem.getText(columnIndex))) {
                    tableItem.setText(columnIndex, s);
                }
                columnIndex++;
            }

            String s = numberFormatter.format(entry.getProposals());
            if (!s.equals(tableItem.getText(columnIndex))) {
                tableItem.setText(columnIndex, s);
            }
            columnIndex++;

            s = numberFormatter.format(entry.getQuantity());
            if (!s.equals(tableItem.getText(columnIndex))) {
                tableItem.setText(columnIndex, s);
            }
            columnIndex++;

            s = priceFormatter.format(entry.getPrice());
            if (!s.equals(tableItem.getText(columnIndex))) {
                tableItem.setText(columnIndex, s);
            }
            columnIndex++;
        } else {
            if (showMarketMakerAction.isChecked()) {
                tableItem.setText(columnIndex, ""); //$NON-NLS-1$
                tableItem.setBackground(columnIndex++, null);
            }

            tableItem.setText(columnIndex, ""); //$NON-NLS-1$
            tableItem.setBackground(columnIndex++, null);

            tableItem.setText(columnIndex, ""); //$NON-NLS-1$
            tableItem.setBackground(columnIndex++, null);

            tableItem.setText(columnIndex, ""); //$NON-NLS-1$
            tableItem.setBackground(columnIndex++, null);
        }

        tableItem.setData("bid", entry); //$NON-NLS-1$
    }

    protected void updateAsk(TableItem tableItem, IBookEntry entry) {
        int columnIndex = tableItem.getParent().getColumnCount() - 1;

        if (entry != null) {
            if (showMarketMakerAction.isChecked()) {
                String s = entry.getMarketMaker() != null ? entry.getMarketMaker() : ""; //$NON-NLS-1$
                if (!s.equals(tableItem.getText(columnIndex))) {
                    tableItem.setText(columnIndex, s);
                }
                columnIndex--;
            }

            String s = numberFormatter.format(entry.getProposals());
            if (!s.equals(tableItem.getText(columnIndex))) {
                tableItem.setText(columnIndex, s);
            }
            columnIndex--;

            s = numberFormatter.format(entry.getQuantity());
            if (!s.equals(tableItem.getText(columnIndex))) {
                tableItem.setText(columnIndex, s);
            }
            columnIndex--;

            s = priceFormatter.format(entry.getPrice());
            if (!s.equals(tableItem.getText(columnIndex))) {
                tableItem.setText(columnIndex, s);
            }
            columnIndex--;
        } else {
            if (showMarketMakerAction.isChecked()) {
                tableItem.setText(columnIndex, ""); //$NON-NLS-1$
                tableItem.setBackground(columnIndex--, null);
            }

            tableItem.setText(columnIndex, ""); //$NON-NLS-1$
            tableItem.setBackground(columnIndex--, null);

            tableItem.setText(columnIndex, ""); //$NON-NLS-1$
            tableItem.setBackground(columnIndex--, null);

            tableItem.setText(columnIndex, ""); //$NON-NLS-1$
            tableItem.setBackground(columnIndex--, null);
        }

        tableItem.setData("ask", entry); //$NON-NLS-1$
    }

    protected void onBookUpdate(IBook book) {
        IBookEntry[] bidEntries = book.getBidProposals();
        IBookEntry[] askEntries = book.getAskProposals();
        int rows = Math.max(bidEntries.length, askEntries.length);

        table.setRedraw(false);
        boolean doLayout = rows != table.getItemCount();
        try {
            for (int rowIndex = 0; rowIndex < rows; rowIndex++) {
                TableItem tableItem = rowIndex < table.getItemCount() ? table.getItem(rowIndex)
                        : new TableItem(table, SWT.NONE);
                updateBid(tableItem, rowIndex < bidEntries.length ? bidEntries[rowIndex] : null);
                updateAsk(tableItem, rowIndex < askEntries.length ? askEntries[rowIndex] : null);
            }
            while (table.getItemCount() > rows) {
                table.getItem(table.getItemCount() - 1).dispose();
            }
        } finally {
            table.setRedraw(true);
        }

        if (doLayout) {
            table.layout();
            table.getParent().layout();
            table.layout();
            table.getParent().layout();
        }

        long[] leftWeights = new long[Math.min(bidEntries.length, 5)];
        for (int i = 0; i < leftWeights.length; i++) {
            leftWeights[i] = bidEntries[i] != null && bidEntries[i].getQuantity() != null
                    ? bidEntries[i].getQuantity()
                    : 0;
        }

        long[] rightWeights = new long[Math.min(askEntries.length, 5)];
        for (int i = 0; i < rightWeights.length; i++) {
            rightWeights[i] = askEntries[i] != null && askEntries[i].getQuantity() != null
                    ? askEntries[i].getQuantity()
                    : 0;
        }

        pressureBar.setWeights(leftWeights, rightWeights);
    }

    protected void onSetSymbol() {
        if (subscription != null && subscription.getSymbol().equals(symbol.getText())) {
            return;
        }

        if (connector != null) {
            if (subscription != null) {
                subscription.removeSubscriptionListener(subscriptionListener);
                subscription.dispose();
            }

            subscription = connector.subscribeLevel2(symbol.getText());
            subscription.addSubscriptionListener(subscriptionListener);

            lastClose = subscription.getLastClose();
            lastTrade = subscription.getTrade();
            update(subscription.getTodayOHL());

            update();

            IBook book = subscription.getBook();
            if (book != null) {
                onBookUpdate(book);
            }

            ISecurity security = getSecurityFromSymbol(symbol.getText());
            if (security != null) {
                getSite().getSelectionProvider().setSelection(new StructuredSelection(security));
                setPartName(security.getName());
                setTitleToolTip(NLS.bind(VIEW_TITLE_TOOLTIP, new Object[] { security.getName() }));
            }
        }
    }

    protected void onChangeConnector(IFeedConnector2 newConnector) {
        if (newConnector != connector) {
            if (connector != null && subscription != null) {
                subscription.removeSubscriptionListener(subscriptionListener);
                subscription.dispose();
                subscription = null;
            }

            connector = newConnector;
            activeConnector.setText(connector != null ? connector.getName() : ""); //$NON-NLS-1$

            if (connector != null && !symbol.getText().equals("")) { //$NON-NLS-1$
                subscription = connector.subscribeLevel2(symbol.getText());
                subscription.addSubscriptionListener(subscriptionListener);

                lastClose = subscription.getLastClose();
                lastTrade = subscription.getTrade();
                update(subscription.getTodayOHL());

                update();

                IBook book = subscription.getBook();
                if (book != null) {
                    onBookUpdate(book);
                }
            }
        }
    }

    public void setSecurity(ISecurity security) {
        IFeedConnector connector = null;

        IMarket[] market = marketService.getMarkets();
        for (int i = 0; i < market.length; i++) {
            if (market[i].hasMember(security)) {
                connector = market[i].getLiveFeedConnector();
                break;
            }
        }

        if (connector == null) {
            connector = CoreActivator.getDefault().getDefaultConnector();
        }

        if (connector instanceof IFeedConnector2) {
            this.connector = (IFeedConnector2) connector;
        }

        if (this.connector != null) {
            activeConnector.setText(this.connector.getName());

            if (subscription != null) {
                subscription.removeSubscriptionListener(subscriptionListener);
                subscription.dispose();
            }

            IFeedIdentifier feedIdentifier = (IFeedIdentifier) security.getAdapter(IFeedIdentifier.class);
            if (feedIdentifier != null) {
                subscription = this.connector.subscribeLevel2(feedIdentifier);

                subscription.addSubscriptionListener(subscriptionListener);

                symbol.setText(subscription.getSymbol());

                lastClose = subscription.getLastClose();
                lastTrade = subscription.getTrade();
                update(subscription.getTodayOHL());

                update();

                IBook book = subscription.getBook();
                if (book != null) {
                    onBookUpdate(book);
                }
            }
        }

        getSite().getSelectionProvider().setSelection(new StructuredSelection(security));
    }

    protected void onQuoteUpdate(final QuoteEvent event) {
        Display.getDefault().asyncExec(new Runnable() {

            @Override
            public void run() {
                if (table.isDisposed()) {
                    return;
                }

                QuoteDelta[] delta = event.getDelta();
                for (int i = 0; i < delta.length; i++) {
                    if (delta[i].getNewValue() instanceof IBook) {
                        nextBook = (IBook) delta[i].getNewValue();
                    }
                    if (delta[i].getNewValue() instanceof ITrade) {
                        lastTrade = (ITrade) delta[i].getNewValue();
                        update();
                    }
                    if (delta[i].getNewValue() instanceof ITodayOHL) {
                        ITodayOHL todayOHL = (ITodayOHL) delta[i].getNewValue();
                        update(todayOHL);
                    }
                    if (delta[i].getNewValue() instanceof ILastClose) {
                        lastClose = (ILastClose) delta[i].getNewValue();
                        update();
                    }
                }
            }
        });
    }

    protected void update() {
        time.setText(
                lastTrade != null && lastTrade.getTime() != null ? timeFormatter.format(lastTrade.getTime()) : ""); //$NON-NLS-1$
        last.setText(lastTrade != null && lastTrade.getPrice() != null ? priceFormatter.format(lastTrade.getPrice())
                : ""); //$NON-NLS-1$
        volume.setText(
                lastTrade != null && lastTrade.getVolume() != null ? numberFormatter.format(lastTrade.getVolume())
                        : ""); //$NON-NLS-1$

        if (lastTrade != null && lastClose != null && lastClose.getPrice() != null
                && lastTrade.getPrice() != null) {
            double changePercent = (lastTrade.getPrice() - lastClose.getPrice()) / lastClose.getPrice() * 100.0;
            change.setText(NLS.bind("{0}{1}%", new Object[] { //$NON-NLS-1$
                    changePercent < 0 ? "-" : changePercent > 0 ? "+" : "", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                    percentageFormatter.format(Math.abs(changePercent)), }));
        } else {
            change.setText(""); //$NON-NLS-1$
        }
    }

    protected void update(ITodayOHL todayOHL) {
        high.setText(
                todayOHL != null && todayOHL.getHigh() != null ? priceFormatter.format(todayOHL.getHigh()) : ""); //$NON-NLS-1$
        low.setText(todayOHL != null && todayOHL.getLow() != null ? priceFormatter.format(todayOHL.getLow()) : ""); //$NON-NLS-1$
    }

    protected ISecurity getSecurityFromSymbol(String symbol) {
        ISecurity security = null;

        BundleContext context = UIActivator.getDefault().getBundle().getBundleContext();
        ServiceReference serviceReference = context.getServiceReference(ITradingService.class.getName());
        if (serviceReference != null) {
            ITradingService service = (ITradingService) context.getService(serviceReference);
            IBroker[] broker = service.getBrokers();
            for (int i = 0; i < broker.length; i++) {
                security = broker[i].getSecurityFromSymbol(symbol);
                if (security != null) {
                    break;
                }
            }

            context.ungetService(serviceReference);
        }

        return security;
    }
}