org.trade.ui.chart.renderer.VolumeBarRenderer.java Source code

Java tutorial

Introduction

Here is the source code for org.trade.ui.chart.renderer.VolumeBarRenderer.java

Source

/* ===========================================================
 * TradeManager : a application to trade strategies for the Java(tm) platform
 * ===========================================================
 *
 * (C) Copyright 2011-2011, by Simon Allen and Contributors.
 *
 * Project Info:  org.trade
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 *
 * [Java is a trademark or registered trademark of Oracle, Inc.
 * in the United States and other countries.]
 *
 * (C) Copyright 2011-2011, by Simon Allen and Contributors.
 *
 * Original Author:  Simon Allen;
 * Contributor(s):   -;
 *
 * Changes
 * -------
 *
 */

package org.trade.ui.chart.renderer;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.labels.XYItemLabelGenerator;
import org.jfree.chart.labels.XYToolTipGenerator;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.chart.renderer.xy.XYItemRendererState;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RectangleEdge;
import org.trade.core.valuetype.Quantity;
import org.trade.strategy.data.VolumeDataset;
import org.trade.strategy.data.volume.VolumeItem;

/**
 */
public class VolumeBarRenderer extends XYBarRenderer {

    /**
     * 
     */
    private static final long serialVersionUID = -6586658399843459145L;
    /** The colors. */
    private Paint color = null;
    private final DateFormat TOOLTIP_DATE_FORMAT = new SimpleDateFormat("H:mma MM/dd/yy");

    /**
     * Creates a new renderer.
     * 
     */
    public VolumeBarRenderer() {
        configureToolTips();
    }

    private void configureToolTips() {
        setBaseToolTipGenerator(new XYToolTipGenerator() {
            public String generateToolTip(XYDataset dataset, int series, int item) {
                StringBuilder result = new StringBuilder("<html>");
                if (dataset instanceof VolumeDataset) {
                    VolumeDataset d = (VolumeDataset) dataset;
                    Number time = d.getX(series, item);
                    Number volume = d.getVolume(series, item);
                    result.append("<b>Volume:</b> ").append(new Quantity(volume.intValue())).append("<br/>");
                    result.append("<b>Date:</b> ").append(TOOLTIP_DATE_FORMAT.format(time)).append("<br/>");
                }
                return result.toString();
            }
        });
    }

    /**
     * Returns the paint for an item. Overrides the default behaviour inherited
     * from AbstractSeriesRenderer.
     * 
     * @param row
     *            the series.
     * @param column
     *            the category.
     * 
     * 
     * @return The item color. * @see
     *         org.jfree.chart.renderer.xy.XYItemRenderer#getItemPaint(int, int)
     */
    public Paint getItemPaint(final int row, final int column) {
        return this.color;
    }

    /**
     * Draws the visual representation of a single data item.
     * 
     * @param g2
     *            the graphics device.
     * @param state
     *            the renderer state.
     * @param dataArea
     *            the area within which the plot is being drawn.
     * @param info
     *            collects information about the drawing.
     * @param plot
     *            the plot (can be used to obtain standard color information
     *            etc).
     * @param domainAxis
     *            the domain axis.
     * @param rangeAxis
     *            the range axis.
     * @param dataset
     *            the dataset.
     * @param series
     *            the series index (zero-based).
     * @param item
     *            the item index (zero-based).
     * @param crosshairState
     *            crosshair information for the plot (<code>null</code>
     *            permitted).
     * @param pass
     *            the pass index.
     * @see org.jfree.chart.renderer.xy.XYItemRenderer#drawItem(Graphics2D,
     *      XYItemRendererState, Rectangle2D, PlotRenderingInfo, XYPlot,
     *      ValueAxis, ValueAxis, XYDataset, int, int, CrosshairState, int)
     */
    public void drawItem(Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info,
            XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item,
            CrosshairState crosshairState, int pass) {

        if (!getItemVisible(series, item)) {
            return;
        }

        VolumeDataset volumeDataset = (VolumeDataset) dataset;
        VolumeItem volumeItem = (VolumeItem) volumeDataset.getSeries(series).getDataItem(item);

        if (volumeItem.isSide()) {
            this.color = Color.GREEN;
        } else {
            this.color = Color.RED;
        }

        double value0;
        double value1;
        if (this.getUseYInterval()) {
            value0 = volumeDataset.getStartYValue(series, item);
            value1 = volumeDataset.getEndYValue(series, item);
        } else {
            value0 = this.getBase();
            value1 = volumeDataset.getYValue(series, item);
        }
        if (Double.isNaN(value0) || Double.isNaN(value1)) {
            return;
        }
        if (value0 <= value1) {
            if (!rangeAxis.getRange().intersects(value0, value1)) {
                return;
            }
        } else {
            if (!rangeAxis.getRange().intersects(value1, value0)) {
                return;
            }
        }

        double translatedValue0 = rangeAxis.valueToJava2D(value0, dataArea, plot.getRangeAxisEdge());
        double translatedValue1 = rangeAxis.valueToJava2D(value1, dataArea, plot.getRangeAxisEdge());
        double bottom = Math.min(translatedValue0, translatedValue1);
        double top = Math.max(translatedValue0, translatedValue1);

        double startX = volumeItem.getPeriod().getFirstMillisecond();
        if (Double.isNaN(startX)) {
            return;
        }
        double endX = volumeItem.getPeriod().getLastMillisecond();
        if (Double.isNaN(endX)) {
            return;
        }

        if (startX <= endX) {
            if (!domainAxis.getRange().intersects(startX, endX)) {
                return;
            }
        } else {
            if (!domainAxis.getRange().intersects(endX, startX)) {
                return;
            }
        }

        // is there an alignment adjustment to be made?
        if (this.getBarAlignmentFactor() >= 0.0 && this.getBarAlignmentFactor() <= 1.0) {
            double x = volumeDataset.getXValue(series, item);
            double interval = endX - startX;
            startX = x - interval * this.getBarAlignmentFactor();
            endX = startX + interval;
        }

        RectangleEdge location = plot.getDomainAxisEdge();
        double translatedStartX = domainAxis.valueToJava2D(startX, dataArea, location);
        double translatedEndX = domainAxis.valueToJava2D(endX, dataArea, location);

        double translatedWidth = Math.max(1, Math.abs(translatedEndX - translatedStartX));

        RectangleEdge domainEdge = plot.getDomainAxisEdge();
        double xx = domainAxis.valueToJava2D(startX, dataArea, domainEdge);

        if (getMargin() > 0.0) {
            double cut = translatedWidth * getMargin();
            translatedWidth = translatedWidth - cut;
        }

        Rectangle2D bar = null;
        PlotOrientation orientation = plot.getOrientation();
        if (orientation == PlotOrientation.HORIZONTAL) {
            // clip left and right bounds to data area
            bottom = Math.max(bottom, dataArea.getMinX());
            top = Math.min(top, dataArea.getMaxX());
            bar = new Rectangle2D.Double(bottom, xx, top - bottom, translatedWidth);
        } else if (orientation == PlotOrientation.VERTICAL) {
            // clip top and bottom bounds to data area
            bottom = Math.max(bottom, dataArea.getMinY());
            top = Math.min(top, dataArea.getMaxY());
            bar = new Rectangle2D.Double(xx - (translatedWidth / 2), bottom, translatedWidth, top - bottom);
        }

        boolean positive = (value1 > 0.0);
        boolean inverted = rangeAxis.isInverted();
        RectangleEdge barBase;
        if (orientation == PlotOrientation.HORIZONTAL) {
            if (positive && inverted || !positive && !inverted) {
                barBase = RectangleEdge.RIGHT;
            } else {
                barBase = RectangleEdge.LEFT;
            }
        } else {
            if (positive && !inverted || !positive && inverted) {
                barBase = RectangleEdge.BOTTOM;
            } else {
                barBase = RectangleEdge.TOP;
            }
        }
        if (getShadowsVisible()) {
            this.getBarPainter().paintBarShadow(g2, this, series, item, bar, barBase, !this.getUseYInterval());
        }
        this.getBarPainter().paintBar(g2, this, series, item, bar, barBase);

        if (isItemLabelVisible(series, item)) {
            XYItemLabelGenerator generator = getItemLabelGenerator(series, item);
            drawItemLabel(g2, dataset, series, item, plot, generator, bar, value1 < 0.0);
        }

        // update the cross hair point
        double x1 = dataset.getXValue(series, item);
        double y1 = dataset.getYValue(series, item);
        double transX1 = domainAxis.valueToJava2D(x1, dataArea, location);
        double transY1 = rangeAxis.valueToJava2D(y1, dataArea, plot.getRangeAxisEdge());
        int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
        int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
        updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex, rangeAxisIndex, transX1, transY1,
                plot.getOrientation());

        EntityCollection entities = state.getEntityCollection();
        // add an entity for the item...
        if (entities != null) {
            String tip = null;
            XYToolTipGenerator generator = getToolTipGenerator(series, item);
            if (generator != null) {
                tip = generator.generateToolTip(dataset, series, item);
            }
            XYItemEntity entity = new XYItemEntity(bar, dataset, series, item, tip, null);

            entities.add(entity);
        }
    }
}