    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        // 4.3.4.4 (2009/01/01)
    055//      /**
    056//       * Creates a new bar renderer with default settings.
    057//       */
    058//      public HybsStackedBarRenderer() {
    059//              super();
    060//      }
    061
    062        /**
    063         * グラフの書き出し位置の調整比率を指定します。
    064         *
    065         * グラフを描画する場合の、書き出し位置を少しずらします。
    066         * これは、グラフの幅に対して、比率で指定します。
    067         * 0.0(初期値)の場合は、初期描画位置である、CategoryAnchor.Middle と
    068         * 同じ箇所から、書き出されます。
    069         * 1.0 の場合、中心から、グラフ幅の半分が加算され、END位置に寄ります。
    070         * 同様に、-1.0 の場合は、グラフ幅の半分が減算され、START 位置になります。
    071         * つまり、中心から、グラフ幅の半分単位で、前方/後方にずらす事が出来ます。
    072         *   書き出し位置 ＝ 中心(Middle) + (domainMargin)＊幅/２
    073         * 初期値は、0.0(真ん中:MIDDLE)です。
    074         *
    075         * @og.rev 4.1.1.0 (2008/02/14) 新規追加
    076         *
    077         * @param       margin  グラフの書き出し位置の調整比率
    078         */
    079        public void setDomainMargin( final double margin ) {
    080                domainMargin = margin;
    081        }
    082
    083        /**
    084         * Draws a stacked bar for a specific item.
    085         *
    086         * @param g2  the graphics device.
    087         * @param state  the renderer state.
    088         * @param dataArea      the plot area.
    089         * @param plot  the plot.
    090         * @param domainAxis  the domain (category) axis.
    091         * @param rangeAxis  the range (value) axis.
    092         * @param dataset  the data.
    093         * @param row  the row index (zero-based).
    094         * @param column  the column index (zero-based).
    095         * @param pass  the pass index.
    096         */
    097        @Override
    098        public void drawItem( final Graphics2D g2,
    099                                                  final CategoryItemRendererState state,
    100                                                  final Rectangle2D dataArea,
    101                                                  final CategoryPlot plot,
    102                                                  final CategoryAxis domainAxis,
    103                                                  final ValueAxis rangeAxis,
    104                                                  final CategoryDataset dataset,
    105                                                  final int row,
    106                                                  final int column,
    107                                                  final int pass) {
    108
    109                // nothing is drawn for null values...
    110                Number dataValue = dataset.getValue(row, column);
    111                if (dataValue == null) {
    112                        return;
    113                }
    114
    115                double value = dataValue.doubleValue();
    116                double total = 0.0;  // only needed if calculating percentages
    117                if (getRenderAsPercentages()) {
    118                        total = DataUtilities.calculateColumnTotal(dataset, column);
    119                        value = value / total;
    120                }
    121
    122                PlotOrientation orientation = plot.getOrientation();
    123
    124                double barW0 = domainAxis.getCategoryStart(column, getColumnCount(),
    125                                dataArea, plot.getDomainAxisEdge())
    126                                + domainMargin * state.getBarWidth() / 2.0;
    127
    128                double positiveBase = getBase();
    129                double negativeBase = positiveBase;
    130
    131                // 4.3.1.1 (2008/08/23) 変数名が短いので変更(v ⇒ nm , d ⇒ vd )
    132                for (int i = 0; i < row; i++) {
    133                        Number nm = dataset.getValue(i, column);
    134                        if (nm != null) {
    135                                double vd = nm.doubleValue();
    136                                if (getRenderAsPercentages()) {
    137                                        vd = vd / total;
    138                                }
    139                                if (vd > 0) {
    140                                        positiveBase = positiveBase + vd;
    141                                }
    142                                else {
    143                                        negativeBase = negativeBase + vd;
    144                                }
    145                        }
    146                }
    147
    148                double translatedBase;
    149                double translatedValue;
    150                RectangleEdge location = plot.getRangeAxisEdge();
    151                if (value >= 0.0) {
    152                        translatedBase = rangeAxis.valueToJava2D(positiveBase, dataArea,
    153                                        location);
    154                        translatedValue = rangeAxis.valueToJava2D(positiveBase + value,
    155                                        dataArea, location);
    156                }
    157                else {
    158                        translatedBase = rangeAxis.valueToJava2D(negativeBase, dataArea,
    159                                        location);
    160                        translatedValue = rangeAxis.valueToJava2D(negativeBase + value,
    161                                        dataArea, location);
    162                }
    163                double barL0 = Math.min(translatedBase, translatedValue);
    164                double barLength = Math.max(Math.abs(translatedValue - translatedBase),
    165                                getMinimumBarLength());
    166
    167                Rectangle2D bar = null;
    168                if (orientation == PlotOrientation.HORIZONTAL) {
    169                        bar = new Rectangle2D.Double(barL0, barW0, barLength,
    170                                        state.getBarWidth());
    171                }
    172                else {
    173                        bar = new Rectangle2D.Double(barW0, barL0, state.getBarWidth(),
    174                                        barLength);
    175                }
    176                if (pass == 0) {
    177                        Paint itemPaint = getItemPaint(row, column);
    178                        // 4.3.1.1 (2008/08/23) 変数名を t ⇒ gpt に変更
    179                        GradientPaintTransformer gpt = getGradientPaintTransformer();
    180                        if (gpt != null && itemPaint instanceof GradientPaint) {
    181                                itemPaint = gpt.transform((GradientPaint) itemPaint, bar);
    182                        }
    183                        g2.setPaint(itemPaint);
    184                        g2.fill(bar);
    185                        if (isDrawBarOutline()
    186                                        && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
    187                                g2.setStroke(getItemOutlineStroke(row, column));
    188                                g2.setPaint(getItemOutlinePaint(row, column));
    189                                g2.draw(bar);
    190                        }
    191
    192                        // add an item entity, if this information is being collected
    193                        EntityCollection entities = state.getEntityCollection();
    194                        if (entities != null) {
    195                                addItemEntity(entities, dataset, row, column, bar);
    196                        }
    197                }
    198                else if (pass == 1) {
    199                        CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
    200                                        column);
    201                        if (generator != null && isItemLabelVisible(row, column)) {
    202                                drawItemLabel(g2, dataset, row, column, plot, generator, bar,
    203                                                (value < 0.0));
    204                        }
    205                }
    206        }
    207
    208        /**
    209         * この文字列と指定されたオブジェクトを比較します。
    210         *
    211         * 親クラスで、equals メソッドが実装されているため、警告がでます。
    212         *
    213         * @og.rev 5.1.8.0 (2010/07/01) findbug対応
    214         * @og.rev 5.1.9.0 (2010/08/01) findbug対応
    215         *
    216         * @param       object  比較するオブジェクト
    217         *
    218         * @return      Objectが等しい場合は true、そうでない場合は false
    219         */
    220        @Override
    221        public boolean equals( final Object object ) {
    222//              return super.equals( object );
    223                if( super.equals( object ) ) {
    224                        return hsCode == ((HybsStackedBarRenderer)object).hsCode;
    225                }
    226                return false;
    227        }
    228
    229        /**
    230         * このオブジェクトのハッシュコードを取得します。
    231         *
    232         * @og.rev 5.1.8.0 (2010/07/01) findbug対応
    233         * @og.rev 5.1.9.0 (2010/08/01) findbug対応
    234         *
    235         * @return      ハッシュコード
    236         */
    237//      public int hashCode() { return super.hashCode() ; }
    238        @Override
    239        public int hashCode() { return hsCode ; }
    240
    241        /**
    242         * このオブジェクトと指定されたオブジェクトを比較します。
    243         *
    244         * @og.rev 4.3.1.1 (2008/08/23) 新規追加
    245         * @og.rev 5.1.8.0 (2010/07/01) 廃止
    246         *
    247         * @param anObject Object 比較されるオブジェクト
    248         *
    249         * @return      指定されたオブジェクトが等しい場合は true、そうでない場合は false
    250         */
    251//      public boolean equals( final Object anObject ) {
    252//              if( super.equals( anObject ) ) {
    253//                      HybsStackedBarRenderer other = ((HybsStackedBarRenderer)anObject);
    254////                    return ( domainMargin == other.domainMargin );
    255//                      return Double.compare( domainMargin,other.domainMargin ) == 0 ;
    256//              }
    257//              return false;
    258//      }
    259
    260        /**
    261         * このオブジェクトのハッシュコードを返します。
    262         *
    263         * @og.rev 4.3.1.1 (2008/08/23) 新規追加
    264         * @og.rev 5.1.8.0 (2010/07/01) 廃止
    265         *
    266         * @return      このオブジェクトのハッシュコード値
    267         */
    268//      public int hashCode() {
    269//              return super.hashCode() ^ Double.valueOf( domainMargin ).hashCode() ;
    270//      }
    271}