/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.trader.client; import java.util.List; import org.apache.openjpa.trader.client.event.ServiceEvent; import org.apache.openjpa.trader.domain.Ask; import org.apache.openjpa.trader.domain.Match; import org.apache.openjpa.trader.domain.Tradable; import org.apache.openjpa.trader.domain.Trade; import org.apache.openjpa.trader.domain.Trader; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.DockPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.RadioButton; /** * A popup presents a list of matching Tradables and lets the user select one of them * to commit a trade. * * @author Pinaki Poddar * */ public class MatchWindow extends PopupPanel { private final OpenTrader session; public MatchWindow(final OpenTrader session, final Tradable tradable, final List<Match> matches) { super(false, true); this.session = session; setAnimationEnabled(true); DockPanel panel = new DockPanel(); panel.setHorizontalAlignment(DockPanel.ALIGN_CENTER); final HTML header = new HTML(); final boolean ask = (tradable instanceof Ask); String txt = (matches.isEmpty() ? "No" : ""+matches.size()) + " matching "+ (ask ? "Bid" : "Ask") + " for " + toString(tradable) + "<br>"; header.setHTML(txt); header.addStyleName("table-caption"); Button close = new Button(matches.isEmpty() ? "OK" : "Cancel"); close.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { hide(); } }); FlexTable body = new FlexTable(); final RadioButton[] buttons = new RadioButton[matches.size()]; if (!matches.isEmpty()) { for (int i = 0; i < matches.size(); i++) { Match match = matches.get(i); Tradable t2 = ask ? match.getBid() : match.getAsk(); Trader cpty = ask ? match.getBid().getBuyer() : match.getAsk().getSeller(); buttons[i] = new RadioButton("matches"); buttons[i].setValue(i == 0); body.setWidget(i, 0, buttons[i]); body.setWidget(i, 1, FormatUtil.formatPrice(t2.getPrice())); body.setWidget(i, 2, FormatUtil.formatVolume(t2.getVolume())); body.setText(i, 3, " by " + cpty.getName()); } Button act = new Button(ask ? "Sell" : "Buy"); act.setFocus(true); body.setWidget(matches.size()+1, 1, act); act.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { for (int i = 0; i < buttons.length; i++) { if (buttons[i].getValue()) { Match match = matches.get(i); Tradable t = ask ? match.getAsk() : match.getBid(); session.getService().trade(match, new TradeCallback(t)); hide(true); } } } }); body.setWidget(matches.size()+1, 2, close); } else { body.setWidget(0,0, new HTML("<p>Open a new browser page and login with a different Trader name<br>" + "to create a matching " + (ask ? "Bid" : "Ask") + "<p>")); close.setFocus(true); body.setWidget(1, 0, close); body.getFlexCellFormatter().setAlignment(1,0, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE); } panel.add(header, DockPanel.NORTH); panel.add(body, DockPanel.CENTER); setWidget(panel); } String toString(Tradable t) { return "" + t.getVolume() + " of " + t.getStock().getSymbol() + " at price " + FormatUtil.priceFormat.format(t.getPrice()); } /** * --------------------------------------------------------------------------------- * Asynchronous RPC service callbacks * --------------------------------------------------------------------------------- */ /** * Commits a Trade and notifies the listeners to {@link ServiceEvent.TradableRemoved * remove} the {@link Tradable tradable} and newly {@link ServiceEvent.TradeCommitted committed} * {@link Trade trade}. * <br> * This is an example of a callback that has a input state (the tradable entity). On completion * of the asynchronous RPC, this function will notify the listeners with the newly commited trade * which is the result of the callback invocation, as well as the input tradable entity. */ public class TradeCallback implements AsyncCallback<Trade> { private final Tradable tradable; public TradeCallback(Tradable m) { tradable = m; } public void onFailure(Throwable caught) { session.handleError(caught); } public void onSuccess(Trade trade) { session.fireEvent(new ServiceEvent.TradableRemoved(tradable)); session.fireEvent(new ServiceEvent.TradeCommitted(trade)); } } }