    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.io;
    017
    018import java.awt.GradientPaint;
    019import java.awt.Graphics2D;
    020import java.awt.Paint;
    021import java.awt.geom.Rectangle2D;
    022
    023import org.jfree.chart.entity.EntityCollection;
    024import org.jfree.chart.renderer.category.StackedBarRenderer;
    025import org.jfree.chart.renderer.category.CategoryItemRendererState;
    026import org.jfree.chart.axis.CategoryAxis;
    027import org.jfree.chart.axis.ValueAxis;
    028import org.jfree.chart.labels.CategoryItemLabelGenerator;
    029import org.jfree.chart.plot.CategoryPlot;
    030import org.jfree.chart.plot.PlotOrientation;
    031import org.jfree.data.category.CategoryDataset;
    032import org.jfree.ui.GradientPaintTransformer;
    033import org.jfree.ui.RectangleEdge;
    034import org.jfree.data.DataUtilities;
    035
    036/**
    037 * HybsStackedBarRenderer は、org.jfree.chart.renderer.category.StackedBarRenderer を
    038 * 拡張したカスタマイズクラスです。
    039 * これは、グラフの書き出し位置の調整比率(domainMargin)を設定できます。
    040 *
    041 * @og.rev 4.1.1.0 (2008/02/16) 新規作成
    042 *
    043 * @version  0.9.0      2001/05/05
    044 * @author       Kazuhiko Hasegawa
    045 * @since        JDK1.1,
    046 */
    047public class HybsStackedBarRenderer extends StackedBarRenderer  {
    048        private static final long serialVersionUID = 519020100801L ;
    049
    050        private double  domainMargin    = 0.0;          // 4.1.1.0 (2008/02/14) グラフの書き出し位置の調整比率
    051
    052        private final int hsCode = Long.valueOf( System.nanoTime() ).hashCode() ;       // 5.1.9.0 (2010/08/01) equals,hashCode
    053
    054        /**
    055         * グラフの書き出し位置の調整比率を指定します。
    056         *
    057         * グラフを描画する場合の、書き出し位置を少しずらします。
    058         * これは、グラフの幅に対して、比率で指定します。
    059         * 0.0(初期値)の場合は、初期描画位置である、CategoryAnchor.Middle と
    060         * 同じ箇所から、書き出されます。
    061         * 1.0 の場合、中心から、グラフ幅の半分が加算され、END位置に寄ります。
    062         * 同様に、-1.0 の場合は、グラフ幅の半分が減算され、START 位置になります。
    063         * つまり、中心から、グラフ幅の半分単位で、前方/後方にずらす事が出来ます。
    064         *   書き出し位置 ＝ 中心(Middle) + (domainMargin)＊幅/２
    065         * 初期値は、0.0(真ん中:MIDDLE)です。
    066         *
    067         * @og.rev 4.1.1.0 (2008/02/14) 新規追加
    068         *
    069         * @param       margin  グラフの書き出し位置の調整比率
    070         */
    071        public void setDomainMargin( final double margin ) {
    072                domainMargin = margin;
    073        }
    074
    075        /**
    076         * Draws a stacked bar for a specific item.
    077         *
    078         * @param g2  the graphics device.
    079         * @param state  the renderer state.
    080         * @param dataArea      the plot area.
    081         * @param plot  the plot.
    082         * @param domainAxis  the domain (category) axis.
    083         * @param rangeAxis  the range (value) axis.
    084         * @param dataset  the data.
    085         * @param row  the row index (zero-based).
    086         * @param column  the column index (zero-based).
    087         * @param pass  the pass index.
    088         */
    089        @Override
    090        public void drawItem( final Graphics2D g2,
    091                                                  final CategoryItemRendererState state,
    092                                                  final Rectangle2D dataArea,
    093                                                  final CategoryPlot plot,
    094                                                  final CategoryAxis domainAxis,
    095                                                  final ValueAxis rangeAxis,
    096                                                  final CategoryDataset dataset,
    097                                                  final int row,
    098                                                  final int column,
    099                                                  final int pass) {
    100
    101                // nothing is drawn for null values...
    102                Number dataValue = dataset.getValue(row, column);
    103                if (dataValue == null) {
    104                        return;
    105                }
    106
    107                double value = dataValue.doubleValue();
    108                double total = 0.0;  // only needed if calculating percentages
    109                if (getRenderAsPercentages()) {
    110                        total = DataUtilities.calculateColumnTotal(dataset, column);
    111                        value = value / total;
    112                }
    113
    114                PlotOrientation orientation = plot.getOrientation();
    115
    116                double barW0 = domainAxis.getCategoryStart(column, getColumnCount(),
    117                                dataArea, plot.getDomainAxisEdge())
    118                                + domainMargin * state.getBarWidth() / 2.0;
    119
    120                double positiveBase = getBase();
    121                double negativeBase = positiveBase;
    122
    123                // 4.3.1.1 (2008/08/23) 変数名が短いので変更(v ⇒ nm , d ⇒ vd )
    124                for (int i = 0; i < row; i++) {
    125                        Number nm = dataset.getValue(i, column);
    126                        if (nm != null) {
    127                                double vd = nm.doubleValue();
    128                                if (getRenderAsPercentages()) {
    129                                        vd = vd / total;
    130                                }
    131                                if (vd > 0) {
    132                                        positiveBase = positiveBase + vd;
    133                                }
    134                                else {
    135                                        negativeBase = negativeBase + vd;
    136                                }
    137                        }
    138                }
    139
    140                double translatedBase;
    141                double translatedValue;
    142                RectangleEdge location = plot.getRangeAxisEdge();
    143                if (value >= 0.0) {
    144                        translatedBase = rangeAxis.valueToJava2D(positiveBase, dataArea,
    145                                        location);
    146                        translatedValue = rangeAxis.valueToJava2D(positiveBase + value,
    147                                        dataArea, location);
    148                }
    149                else {
    150                        translatedBase = rangeAxis.valueToJava2D(negativeBase, dataArea,
    151                                        location);
    152                        translatedValue = rangeAxis.valueToJava2D(negativeBase + value,
    153                                        dataArea, location);
    154                }
    155                double barL0 = Math.min(translatedBase, translatedValue);
    156                double barLength = Math.max(Math.abs(translatedValue - translatedBase),
    157                                getMinimumBarLength());
    158
    159                Rectangle2D bar = null;
    160                if (orientation == PlotOrientation.HORIZONTAL) {
    161                        bar = new Rectangle2D.Double(barL0, barW0, barLength,
    162                                        state.getBarWidth());
    163                }
    164                else {
    165                        bar = new Rectangle2D.Double(barW0, barL0, state.getBarWidth(),
    166                                        barLength);
    167                }
    168                if (pass == 0) {
    169                        Paint itemPaint = getItemPaint(row, column);
    170                        // 4.3.1.1 (2008/08/23) 変数名を t ⇒ gpt に変更
    171                        GradientPaintTransformer gpt = getGradientPaintTransformer();
    172                        if (gpt != null && itemPaint instanceof GradientPaint) {
    173                                itemPaint = gpt.transform((GradientPaint) itemPaint, bar);
    174                        }
    175                        g2.setPaint(itemPaint);
    176                        g2.fill(bar);
    177                        if (isDrawBarOutline()
    178                                        && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
    179                                g2.setStroke(getItemOutlineStroke(row, column));
    180                                g2.setPaint(getItemOutlinePaint(row, column));
    181                                g2.draw(bar);
    182                        }
    183
    184                        // add an item entity, if this information is being collected
    185                        EntityCollection entities = state.getEntityCollection();
    186                        if (entities != null) {
    187                                addItemEntity(entities, dataset, row, column, bar);
    188                        }
    189                }
    190                else if (pass == 1) {
    191                        CategoryItemLabelGenerator generator = getItemLabelGenerator(row,column);
    192                        if (generator != null && isItemLabelVisible(row, column)) {
    193                                drawItemLabel(g2, dataset, row, column, plot, generator, bar,(value < 0.0));
    194                        }
    195                }
    196        }
    197
    198        /**
    199         * この文字列と指定されたオブジェクトを比較します。
    200         *
    201         * 親クラスで、equals メソッドが実装されているため、警告がでます。
    202         *
    203         * @og.rev 5.1.8.0 (2010/07/01) findbug対応
    204         * @og.rev 5.1.9.0 (2010/08/01) findbug対応
    205         *
    206         * @param       object  比較するオブジェクト
    207         *
    208         * @return      Objectが等しい場合は true、そうでない場合は false
    209         */
    210        @Override
    211        public boolean equals( final Object object ) {
    212                if( super.equals( object ) ) {
    213                        return hsCode == ((HybsStackedBarRenderer)object).hsCode;
    214                }
    215                return false;
    216        }
    217
    218        /**
    219         * このオブジェクトのハッシュコードを取得します。
    220         *
    221         * @og.rev 5.1.8.0 (2010/07/01) findbug対応
    222         * @og.rev 5.1.9.0 (2010/08/01) findbug対応
    223         *
    224         * @return      ハッシュコード
    225         */
    226        @Override
    227        public int hashCode() { return hsCode ; }
    228}