/*
* 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.providers;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
import org.eclipsetrader.core.feed.IBook;
import org.eclipsetrader.core.feed.IBookEntry;
import org.eclipsetrader.core.instruments.ISecurity;
import org.eclipsetrader.core.markets.MarketPricingEnvironment;
import org.eclipsetrader.core.views.IDataProvider;
import org.eclipsetrader.core.views.IDataProviderFactory;
public class PressureBarFactory extends AbstractProviderFactory {
private static final int IMAGE_WIDTH = 128;
private static final int IMAGE_HEIGHT = 16;
private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;
private Color bidColor = Display.getDefault().getSystemColor(SWT.COLOR_RED);
private Color bidFillColor = new Color(Display.getDefault(), blend(bidColor.getRGB(), new RGB(0, 0, 0), 75));
private Color askColor = Display.getDefault().getSystemColor(SWT.COLOR_GREEN);
private Color askFillColor = new Color(Display.getDefault(), blend(askColor.getRGB(), new RGB(0, 0, 0), 75));
private Color backgroundColor = Display.getDefault().getSystemColor(SWT.COLOR_WHITE);
private class Data {
IBook book;
Image image;
ImageDataValue value;
}
public class DataProvider implements IDataProvider {
private MarketPricingEnvironment pricingEnvironment;
private Map<ISecurity, Data> map = new HashMap<ISecurity, Data>();
public DataProvider() {
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.views.IDataProvider#init(org.eclipse.core.runtime.IAdaptable)
*/
@Override
public void init(IAdaptable adaptable) {
ISecurity security = (ISecurity) adaptable.getAdapter(ISecurity.class);
if (!map.containsKey(security)) {
pricingEnvironment = (MarketPricingEnvironment) adaptable.getAdapter(MarketPricingEnvironment.class);
if (pricingEnvironment != null) {
pricingEnvironment.addLevel2Security(security);
}
Data data = new Data();
data.image = new Image(Display.getDefault(), IMAGE_WIDTH, IMAGE_HEIGHT);
map.put(security, data);
}
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.views.IDataProvider#dispose()
*/
@Override
public void dispose() {
for (Data data : map.values()) {
data.image.dispose();
}
map.clear();
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.views.IDataProvider#getFactory()
*/
@Override
public IDataProviderFactory getFactory() {
return PressureBarFactory.this;
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.views.IDataProvider#getValue(org.eclipse.core.runtime.IAdaptable)
*/
@Override
public IAdaptable getValue(IAdaptable adaptable) {
ISecurity security = (ISecurity) adaptable.getAdapter(ISecurity.class);
Data data = map.get(security);
if (data == null) {
return null;
}
IBook newBook = (IBook) adaptable.getAdapter(IBook.class);
if (newBook != null && !newBook.equals(data.book)) {
buildValue(newBook, data.image);
data.book = newBook;
data.value = new ImageDataValue(data.image.getImageData());
}
return data.value;
}
}
public static class ImageDataValue implements IAdaptable {
private final ImageData value;
public ImageDataValue(ImageData value) {
this.value = value;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
@Override
@SuppressWarnings({
"unchecked", "rawtypes"
})
public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(ImageData.class)) {
return value;
}
return null;
}
}
public PressureBarFactory() {
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.views.IDataProviderFactory#createProvider()
*/
@Override
public IDataProvider createProvider() {
return new DataProvider();
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.views.IDataProviderFactory#getType()
*/
@Override
@SuppressWarnings("rawtypes")
public Class[] getType() {
return new Class[] {
Image.class,
};
}
protected void buildValue(IBook book, Image image) {
int level = 0;
double currentPrice = 0.0;
double bidPressure = 0L;
for (IBookEntry entry : book.getBidProposals()) {
if (currentPrice != entry.getPrice().doubleValue()) {
currentPrice = entry.getPrice().doubleValue();
level++;
if (level > 5) {
break;
}
}
bidPressure += entry.getQuantity();
}
level = 0;
currentPrice = 0.0;
double askPressure = 0L;
for (IBookEntry entry : book.getAskProposals()) {
if (currentPrice != entry.getPrice().doubleValue()) {
currentPrice = entry.getPrice().doubleValue();
level++;
if (level > 5) {
break;
}
}
askPressure += entry.getQuantity();
}
int bidPixels = (int) (bidPressure / (bidPressure + askPressure) * IMAGE_HALF_WIDTH);
int askPixels = (int) (askPressure / (bidPressure + askPressure) * IMAGE_HALF_WIDTH);
GC gc = new GC(image);
try {
gc.setBackground(backgroundColor);
gc.fillRectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
gc.setBackground(bidFillColor);
gc.fillRectangle(IMAGE_HALF_WIDTH - bidPixels, 0, bidPixels, IMAGE_HEIGHT);
gc.setBackground(askFillColor);
gc.fillRectangle(IMAGE_HALF_WIDTH, 0, askPixels, IMAGE_HEIGHT);
gc.setLineWidth(2);
gc.setForeground(bidColor);
gc.drawLine(IMAGE_HALF_WIDTH - bidPixels - 1, 1, IMAGE_HALF_WIDTH, 1);
gc.drawLine(IMAGE_HALF_WIDTH - bidPixels - 1, 0, IMAGE_HALF_WIDTH - bidPixels, IMAGE_HEIGHT - 1);
gc.drawLine(IMAGE_HALF_WIDTH - bidPixels - 1, IMAGE_HEIGHT - 1, IMAGE_HALF_WIDTH, IMAGE_HEIGHT - 1);
gc.setForeground(askColor);
gc.drawLine(IMAGE_HALF_WIDTH, 1, IMAGE_HALF_WIDTH + askPixels, 1);
gc.drawLine(IMAGE_HALF_WIDTH + askPixels - 1, 0, IMAGE_HALF_WIDTH + askPixels - 1, IMAGE_HEIGHT - 1);
gc.drawLine(IMAGE_HALF_WIDTH, IMAGE_HEIGHT - 1, IMAGE_HALF_WIDTH + askPixels, IMAGE_HEIGHT - 1);
} finally {
gc.dispose();
}
}
private RGB blend(RGB c1, RGB c2, int ratio) {
int r = blend(c1.red, c2.red, ratio);
int g = blend(c1.green, c2.green, ratio);
int b = blend(c1.blue, c2.blue, ratio);
return new RGB(r, g, b);
}
private int blend(int v1, int v2, int ratio) {
return (ratio * v1 + (100 - ratio) * v2) / 100;
}
}