/* * 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.text.NumberFormat; import java.util.Date; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.nebula.widgets.cdatetime.CDT; import org.eclipse.nebula.widgets.cdatetime.CDateTime; 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.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipsetrader.core.feed.IFeedIdentifier; import org.eclipsetrader.core.instruments.ISecurity; import org.eclipsetrader.core.trading.IAccount; import org.eclipsetrader.core.trading.IBroker; import org.eclipsetrader.core.trading.IOrderMonitor; import org.eclipsetrader.core.trading.IOrderRoute; import org.eclipsetrader.core.trading.IOrderSide; import org.eclipsetrader.core.trading.IOrderType; import org.eclipsetrader.core.trading.IOrderValidity; import org.eclipsetrader.core.trading.ITradingService; import org.eclipsetrader.core.trading.Order; import org.eclipsetrader.ui.Util; import org.eclipsetrader.ui.internal.UIActivator; public class OrderDialog extends TitleAreaDialog { Text symbol; Label symbolDescription; ComboViewer sideCombo; Text quantity; ComboViewer typeCombo; Text price; ComboViewer brokerCombo; ComboViewer accountCombo; ComboViewer routeCombo; ComboViewer validityCombo; CDateTime expireDate; Text orderReference; Label summaryLabel; private ISecurity security; private IBroker broker; private IAccount account; private Long position; private Double limitPrice; private IOrderSide orderSide; private ITradingService tradingService; NumberFormat numberFormat; NumberFormat priceFormat; NumberFormat totalPriceFormat; private ISelectionChangedListener orderTypeSelectionListener = new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); price.setEnabled(selection.getFirstElement() == IOrderType.Limit); updateSummary(); getButton(OK).setEnabled(isValid()); } }; public OrderDialog(Shell parentShell, ITradingService tradingService) { super(parentShell); this.tradingService = tradingService; numberFormat = NumberFormat.getInstance(); numberFormat.setMinimumFractionDigits(0); numberFormat.setMaximumFractionDigits(0); numberFormat.setGroupingUsed(true); priceFormat = NumberFormat.getInstance(); priceFormat.setMinimumFractionDigits(1); priceFormat.setMaximumFractionDigits(4); priceFormat.setGroupingUsed(true); totalPriceFormat = NumberFormat.getInstance(); totalPriceFormat.setMinimumFractionDigits(2); totalPriceFormat.setMaximumFractionDigits(2); totalPriceFormat.setGroupingUsed(true); } public void setSecurity(ISecurity security) { this.security = security; } public void setBroker(IBroker broker) { this.broker = broker; } public void setAccount(IAccount account) { this.account = account; } public void setPosition(Long position) { this.position = position; } public void setLimitPrice(Double limitPrice) { this.limitPrice = limitPrice; } public void setOrderSide(IOrderSide orderSide) { this.orderSide = orderSide; } /* (non-Javadoc) * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) */ @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(Messages.OrderDialog_Text); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.TitleAreaDialog#createContents(org.eclipse.swt.widgets.Composite) */ @Override protected Control createContents(Composite parent) { Control control = super.createContents(parent); setTitle(Messages.OrderDialog_Title); setMessage(Messages.OrderDialog_Message); getButton(OK).setEnabled(isValid()); return control; } protected boolean isValid() { if (symbol.getText().equals("")) { return false; } try { long quantity = numberFormat.parse(this.quantity.getText()).longValue(); if (quantity <= 0) { return false; } } catch (Exception e) { return false; } IOrderType orderType = (IOrderType) ((IStructuredSelection) typeCombo.getSelection()).getFirstElement(); if (orderType == IOrderType.Limit) { try { double price = priceFormat.parse(this.price.getText()).doubleValue(); if (price <= 0) { return false; } } catch (Exception e) { return false; } } return true; } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ @Override protected Control createDialogArea(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new GridLayout(2, false)); composite.setLayoutData(new GridData(GridData.FILL_BOTH)); createContractDescriptionGroup(composite); createOrderDescriptionGroup(composite); createMiscellaneousGroup(composite); createSummaryGroup(composite); setInitialParameters(); updateSummary(); addListeners(); quantity.setFocus(); return composite; } protected void createContractDescriptionGroup(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout gridLayout = new GridLayout(3, false); gridLayout.marginHeight = 0; composite.setLayout(gridLayout); composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1)); Label label = new Label(composite, SWT.NONE); label.setText(Messages.OrderDialog_SymbolLabel); symbol = new Text(composite, SWT.BORDER); symbol.setLayoutData(new GridData(convertWidthInCharsToPixels(18), SWT.DEFAULT)); symbolDescription = new Label(composite, SWT.NONE); symbolDescription.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); } protected void createOrderDescriptionGroup(Composite parent) { Group content = new Group(parent, SWT.NONE); content.setText(Messages.OrderDialog_OrderDescriptionGroup); content.setLayout(new GridLayout(2, false)); content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); Label label = new Label(content, SWT.NONE); label.setText(Messages.OrderDialog_ActionLabel); sideCombo = new ComboViewer(content, SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN); sideCombo.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); sideCombo.setContentProvider(new ArrayContentProvider()); sideCombo.setLabelProvider(new LabelProvider()); label = new Label(content, SWT.NONE); label.setText(Messages.OrderDialog_QuantityLabel); quantity = new Text(content, SWT.BORDER); quantity.setLayoutData(new GridData(convertWidthInCharsToPixels(18), SWT.DEFAULT)); ((GridData) quantity.getLayoutData()).horizontalAlignment = SWT.FILL; label = new Label(content, SWT.NONE); label.setText(Messages.OrderDialog_OrderTypeLabel); typeCombo = new ComboViewer(content, SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN); typeCombo.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); typeCombo.setContentProvider(new ArrayContentProvider()); typeCombo.setLabelProvider(new LabelProvider()); label = new Label(content, SWT.NONE); label.setText(Messages.OrderDialog_LimitPriceLabel); price = new Text(content, SWT.BORDER); price.setLayoutData(new GridData(convertWidthInCharsToPixels(18), SWT.DEFAULT)); ((GridData) price.getLayoutData()).horizontalAlignment = SWT.FILL; price.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent event) { try { double n = priceFormat.parse(((Text) event.widget).getText()).doubleValue(); ((Text) event.widget).setText(priceFormat.format(n)); } catch (Exception e) { } } }); label = new Label(content, SWT.NONE); label.setText(Messages.OrderDialog_BrokerLabel); brokerCombo = new ComboViewer(content, SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN); brokerCombo.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); brokerCombo.setContentProvider(new ArrayContentProvider()); brokerCombo.setLabelProvider(new LabelProvider() { @Override public String getText(Object element) { return ((IBroker) element).getName(); } }); brokerCombo.setSorter(new ViewerSorter()); brokerCombo.setInput(tradingService.getBrokers()); label = new Label(content, SWT.NONE); label.setText("Account"); accountCombo = new ComboViewer(content, SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN); accountCombo.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); accountCombo.setContentProvider(new ArrayContentProvider()); accountCombo.setLabelProvider(new LabelProvider() { @Override public String getText(Object element) { return ((IAccount) element).getDescription(); } }); accountCombo.setSorter(new ViewerSorter()); accountCombo.getControl().setEnabled(false); label = new Label(content, SWT.NONE); label.setText(Messages.OrderDialog_RouteLabel); routeCombo = new ComboViewer(content, SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN); routeCombo.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); routeCombo.setContentProvider(new ArrayContentProvider()); routeCombo.setLabelProvider(new LabelProvider()); routeCombo.setSorter(new ViewerSorter()); } protected void createMiscellaneousGroup(Composite parent) { Group content = new Group(parent, SWT.NONE); content.setText(Messages.OrderDialog_MiscLabel); content.setLayout(new GridLayout(2, false)); content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); Label label = new Label(content, SWT.NONE); label.setText(Messages.OrderDialog_TimeInForceLabel); validityCombo = new ComboViewer(content, SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN); validityCombo.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); validityCombo.setContentProvider(new ArrayContentProvider()); validityCombo.setLabelProvider(new LabelProvider()); label = new Label(content, SWT.NONE); label.setText(Messages.OrderDialog_ExpireLabel); expireDate = new CDateTime(content, CDT.BORDER | CDT.DATE_SHORT | CDT.DROP_DOWN | CDT.TAB_FIELDS); expireDate.setPattern(Util.getDateFormatPattern()); expireDate.setSelection(new Date()); expireDate.setEnabled(false); label = new Label(content, SWT.NONE); label.setText(Messages.OrderDialog_ReferenceLabel); orderReference = new Text(content, SWT.BORDER); orderReference.setLayoutData(new GridData(convertWidthInCharsToPixels(40), SWT.DEFAULT)); } protected void createSummaryGroup(Composite parent) { Group content = new Group(parent, SWT.NONE); content.setText(Messages.OrderDialog_SummaryGroup); content.setLayout(new GridLayout(1, false)); content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1)); summaryLabel = new Label(content, SWT.NONE); summaryLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); } void setInitialParameters() { if (security != null) { symbol.setText(getSecuritySymbol(security)); symbolDescription.setText(security.getName()); } if (position != null) { quantity.setText(numberFormat.format(position)); } if (limitPrice != null) { price.setText(priceFormat.format(limitPrice)); } if (broker != null) { IStructuredSelection selection = new StructuredSelection(broker); brokerCombo.setSelection(selection); } else { IBroker[] brokers = tradingService.getBrokers(); if (brokers.length != 0) { brokerCombo.setSelection(new StructuredSelection(brokers[0])); } } handleBrokerSelection((IStructuredSelection) brokerCombo.getSelection()); if (account != null) { accountCombo.setSelection(new StructuredSelection(account)); } if (orderSide != null) { sideCombo.setSelection(new StructuredSelection(orderSide)); } } protected void handleBrokerSelection(IStructuredSelection selection) { IBroker connector = (IBroker) selection.getFirstElement(); if (security != null) { symbol.setText(connector.getSymbolFromSecurity(security)); symbolDescription.setText(security.getName().replaceAll("&", "&&")); //$NON-NLS-1$ //$NON-NLS-2$ } IOrderSide[] sides = connector.getAllowedSides(); ISelection oldSelection = sideCombo.getSelection(); sideCombo.setInput(sides); sideCombo.setSelection(oldSelection); if (sideCombo.getSelection().isEmpty()) { sideCombo.setSelection(new StructuredSelection(sides[0])); } IOrderType[] types = connector.getAllowedTypes(); oldSelection = typeCombo.getSelection(); typeCombo.setInput(types); typeCombo.setSelection(oldSelection); if (typeCombo.getSelection().isEmpty() && types.length != 0) { typeCombo.setSelection(new StructuredSelection(types[0])); } IOrderValidity[] validities = connector.getAllowedValidity(); oldSelection = validityCombo.getSelection(); validityCombo.setInput(validities); validityCombo.setSelection(oldSelection); if (validityCombo.getSelection().isEmpty() && validities.length != 0) { validityCombo.setSelection(new StructuredSelection(validities[0])); } IOrderRoute[] routes = connector.getAllowedRoutes(); oldSelection = routeCombo.getSelection(); routeCombo.setInput(routes); routeCombo.setSelection(oldSelection); if (routeCombo.getSelection().isEmpty() && routes.length != 0) { routeCombo.setSelection(new StructuredSelection(routes[0])); } IAccount[] accounts = connector.getAccounts(); oldSelection = accountCombo.getSelection(); accountCombo.setInput(accounts); accountCombo.setSelection(oldSelection); if (accountCombo.getSelection().isEmpty() && accounts.length != 0) { accountCombo.setSelection(new StructuredSelection(accounts[0])); } accountCombo.getControl().setEnabled(accounts.length > 0); } protected String getSecuritySymbol(ISecurity security) { IFeedIdentifier identifier = security.getIdentifier(); if (identifier == null) { return null; } return identifier.getSymbol(); } void addListeners() { symbol.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { if (!brokerCombo.getSelection().isEmpty()) { IBroker connector = (IBroker) ((IStructuredSelection) brokerCombo.getSelection()).getFirstElement(); security = connector.getSecurityFromSymbol(symbol.getText()); symbolDescription.setText(security != null ? security.getName() : ""); } getButton(OK).setEnabled(isValid()); } }); quantity.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { updateSummary(); getButton(OK).setEnabled(isValid()); } }); quantity.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent event) { try { long n = numberFormat.parse(((Text) event.widget).getText()).longValue(); ((Text) event.widget).setText(numberFormat.format(n)); } catch (Exception e) { } } }); price.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { updateSummary(); getButton(OK).setEnabled(isValid()); } }); typeCombo.addSelectionChangedListener(orderTypeSelectionListener); brokerCombo.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); handleBrokerSelection(selection); getButton(OK).setEnabled(isValid()); } }); validityCombo.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); IOrderValidity validity = selection.isEmpty() ? null : (IOrderValidity) selection.getFirstElement(); expireDate.setEnabled(validity == IOrderValidity.GoodTillDate); getButton(OK).setEnabled(isValid()); } }); } protected void updateSummary() { try { long quantity = numberFormat.parse(this.quantity.getText()).longValue(); double price = 0.0; IOrderType orderType = (IOrderType) ((IStructuredSelection) typeCombo.getSelection()).getFirstElement(); if (orderType == IOrderType.Limit) { price = priceFormat.parse(this.price.getText()).doubleValue(); } else if (limitPrice != null) { price = limitPrice; } if (quantity != 0 && price != 0.0) { summaryLabel.setText(NLS.bind(Messages.OrderDialog_TotalLabel, new Object[] { totalPriceFormat.format(quantity * price) })); } else { summaryLabel.setText(""); //$NON-NLS-1$ } } catch (Exception e) { summaryLabel.setText(""); //$NON-NLS-1$ } } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#okPressed() */ @Override protected void okPressed() { try { IAccount account = (IAccount) ((IStructuredSelection) accountCombo.getSelection()).getFirstElement(); IOrderType orderType = (IOrderType) ((IStructuredSelection) typeCombo.getSelection()).getFirstElement(); Double limitPrice = orderType == IOrderType.Market ? null : priceFormat.parse(price.getText()).doubleValue(); Order order = new Order(account, orderType, (IOrderSide) ((IStructuredSelection) sideCombo.getSelection()).getFirstElement(), security, numberFormat.parse(quantity.getText()).longValue(), limitPrice); if (!routeCombo.getSelection().isEmpty()) { order.setRoute((IOrderRoute) ((IStructuredSelection) routeCombo.getSelection()).getFirstElement()); } if (!validityCombo.getSelection().isEmpty()) { IOrderValidity validity = (IOrderValidity) ((IStructuredSelection) validityCombo.getSelection()).getFirstElement(); order.setValidity(validity); if (expireDate.getEnabled()) { order.setExpire(expireDate.getSelection()); } } if (!orderReference.getText().equals("")) { order.setReference(orderReference.getText()); } IBroker connector = (IBroker) ((IStructuredSelection) brokerCombo.getSelection()).getFirstElement(); IOrderMonitor tracker = connector.prepareOrder(order); tracker.submit(); super.okPressed(); } catch (Exception e) { Status status = new Status(IStatus.ERROR, UIActivator.PLUGIN_ID, 0, Messages.OrderDialog_SubmitErrorMessage, e); UIActivator.log(status); ErrorDialog.openError(getShell(), getShell().getText(), null, status); } } }