    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.Graphics2D;
    019import java.awt.Stroke;
    020import java.awt.Paint;
    021import java.awt.geom.Rectangle2D;
    022import java.util.List;
    023import java.util.Map;
    024import java.util.HashMap;
    025import java.util.Iterator;
    026
    027import org.jfree.chart.plot.CategoryPlot;
    028import org.jfree.chart.plot.PlotRenderingInfo;
    029import org.jfree.chart.urls.CategoryURLGenerator;
    030import org.jfree.chart.axis.CategoryAxis;
    031import org.jfree.chart.axis.ValueAxis;
    032import org.jfree.chart.axis.ValueTick;
    033import org.jfree.chart.renderer.category.CategoryItemRenderer;
    034import org.jfree.chart.renderer.category.CategoryItemRendererState;
    035import org.jfree.chart.renderer.category.StackedBarRenderer;
    036import org.jfree.data.category.CategoryDataset;
    037import org.jfree.data.general.DatasetUtilities;
    038
    039/**
    040 * HybsCategoryPlot は、CategoryPlot を拡張したカスタマイズクラスです。
    041 * これは、シリーズの表示色を変更する箇所で、描画順により、きれいに表示されない
    042 * 現象への対応案です。
    043 * 描画順を、最も最後に行うように、修正しています。
    044 *
    045 * renders each data item using a {@link CategoryItemRenderer}.
    046 *
    047 * @og.rev 3.8.9.2 (2007/07/28) 新規作成
    048 *
    049 * @version  0.9.0  2001/05/05
    050 * @author   Kazuhiko Hasegawa
    051 * @since    JDK1.1,
    052 */
    053public class HybsCategoryPlot extends CategoryPlot {
    054        private static final long serialVersionUID = 519020100801L ;
    055
    056        private final Map<Integer,Double> barWidths = new HashMap<Integer,Double>();        // 4.3.1.1 (2008/08/23) final化
    057        private int             serNo     = -1;
    058//      private boolean isNotify  = false;
    059        private int             rangeSkip = 1;                  // 4.1.1.0 (2008/02/04) 縦軸のグリッドをスキップする間隔
    060        private final int hsCode = Long.valueOf( System.nanoTime() ).hashCode() ;       // 5.1.9.0 (2010/08/01) equals,hashCode
    061
    062        /**
    063         * デフォルトコンストラクター
    064         * シリーズ番号を、初期化しておきます。
    065         *
    066         **/
    067        public HybsCategoryPlot() {
    068                // 4.3.4.4 (2009/01/01)
    069                this( -1 );
    070        }
    071
    072        /**
    073         * シリーズ番号 を、指定して、オブジェクトを作成するコンストラクター
    074         *
    075         * @param       serNo   ピックアップするシリーズ番号
    076         **/
    077        protected HybsCategoryPlot( final int serNo ) {
    078                // 4.3.4.4 (2009/01/01)
    079//              super();
    080                this.serNo = serNo;
    081        }
    082
    083        /**
    084         * ピックアップするシリーズ番号を設定します。
    085         *
    086         * @og.rev 4.1.1.0 (2008/02/04) データの値(itemText)表示の継承
    087         *
    088         * @param       newSerNo        ピックアップするシリーズ番号
    089         **/
    090        protected void setSeriesPikup( final int newSerNo ) {
    091                int oldSerNo = serNo ;
    092                serNo = newSerNo;
    093                CategoryItemRenderer rend = getRenderer();
    094                CategoryURLGenerator urlGen = rend.getSeriesItemURLGenerator( oldSerNo );
    095                if( urlGen != null ) {
    096                        rend.setSeriesItemURLGenerator( oldSerNo,null );
    097                        rend.setSeriesItemURLGenerator( serNo   ,urlGen );
    098                }
    099
    100                // 4.1.1.0 (2008/02/04) データの値(itemText)表示の継承
    101                if( rend.isSeriesItemLabelsVisible( oldSerNo ) ) {
    102                        rend.setSeriesItemLabelsVisible( oldSerNo,false );
    103                        rend.setSeriesItemLabelsVisible( serNo   ,true  );
    104                }
    105        }
    106
    107        /**
    108         * Notifyを設定します。
    109         *
    110         * @og.rev 5.1.4.0 (2010/03/01) 継承元の Plot クラスに public で追加された対応
    111         * @og.rev 5.1.8.0 (2010/07/01) 実質的に使用されていないので、削除
    112         *
    113         * @param   isNotify boolean
    114         **/
    115//      protected void setNotify( final boolean isNotify ) {
    116//      public void setNotify( final boolean isNotify ) {
    117//              this.isNotify = isNotify;
    118//      }
    119
    120        /**
    121         * 縦軸のグリッド線(水平線)をスキップする間隔を指定します。
    122         *
    123         * 縦軸のグリッド線を表示する際に、スキップする間隔を指定します。
    124         * 通常は、ラベルと同じだけのグリッド線が掛かれますが、ラベルよりも
    125         * 少ない数のグリッド線(例えば、２つおき)を出す場合に、値を設定します。
    126         * "1" (初期値)では、１つづつ表示(つまり、すべて表示する)します。
    127         * "2" とすると、１つおきに、"3" とすると、２つおきに表示します。
    128         * 初期値は、"1" (すべて表示)です。
    129         * なお、先頭から表示を開始します。
    130         *
    131         * @og.rev 4.1.1.0 (2008/02/04) 新規追加
    132         *
    133         * @param       rngSkip 縦軸のグリッド線(水平線)をスキップする間隔
    134         */
    135        protected void setRangeSkip( final int rngSkip ) {
    136                rangeSkip = rngSkip;
    137        }
    138
    139        /**
    140         * BarChart のバーの幅を直接指定します。
    141         * 通常は、maxBarWidth や itemMargin で比率指定しますが、
    142         * ここでは、CategoryItemRendererState オブジェクトに直接設定する為の
    143         * データセット単位のマップを作成します。
    144         *
    145         * @param       index   データセット番号
    146         * @param       width   バーの幅
    147         **/
    148        protected void setBarWidth( final int index,final Double width ) {
    149                barWidths.put( index,width );
    150        }
    151
    152        /**
    153         * Draws a representation of a dataset within the dataArea region using the
    154         * appropriate renderer.
    155         *
    156         * @param g2  the graphics device.
    157         * @param dataArea      the region in which the data is to be drawn.
    158         * @param index  the dataset and renderer index.
    159         * @param info  an optional object for collection dimension information.
    160         *
    161         * @return      描画するデータが見つかった場合は、true
    162         */
    163        public boolean render( final Graphics2D g2, final Rectangle2D dataArea, final int index,
    164                                                  final PlotRenderingInfo info ) {
    165                boolean foundData = false;
    166                CategoryDataset currentDataset = getDataset(index);
    167                CategoryItemRenderer renderer = getRenderer(index);
    168                // 4.3.1.0 (2008/08/19) 軸とデータセットのマッピング
    169                this.mapDatasetToRangeAxis( index, index );
    170
    171                CategoryAxis domainAxis = null ;
    172                if( renderer instanceof StackedBarRenderer ) {
    173                        domainAxis = getDomainAxis(index);
    174                }
    175                else {
    176                        domainAxis = getDomainAxisForDataset(index);
    177                }
    178
    179                ValueAxis rangeAxis = getRangeAxis(index);
    180                boolean hasData = !DatasetUtilities.isEmptyOrNull(currentDataset);
    181                if(hasData && renderer != null) {
    182                        foundData = true;
    183                        CategoryItemRendererState state = renderer.initialise(g2, dataArea,
    184                                        this, index, info);
    185
    186                        // 4.0.3.0 (2008/01/07) 棒グラフのバー幅指定
    187                        Double bwidth = barWidths.get( index );
    188                        if( bwidth != null ) { state.setBarWidth( bwidth.doubleValue() ); }
    189
    190                        if( renderer instanceof HybsDrawItem ) {
    191                                ((HybsDrawItem)renderer).drawItem2(g2, state, dataArea, this,
    192                                                domainAxis, rangeAxis, currentDataset , serNo );
    193                        }
    194                        else {
    195                                int columnCount = currentDataset.getColumnCount();
    196                                int rowCount = currentDataset.getRowCount();
    197                                int passCount = renderer.getPassCount();
    198                                for( int pass=0; pass<passCount; pass++ ) {
    199                                        for( int column=0; column<columnCount; column++ ) {
    200                                                for( int row=0; row<rowCount; row++ ) {
    201                                                        if( row == serNo ) { continue; }        // Mis Add 2007/07/23
    202                                                        renderer.drawItem(g2, state, dataArea, this,
    203                                                                        domainAxis, rangeAxis, currentDataset,
    204                                                                        row, column, pass);
    205                                                }
    206                                                // 指定のシリーズと一致する場合は、最後に描画する。 Mis Add 2007/07/23
    207                                                if( serNo >= 0 ) {
    208                                                        renderer.drawItem(g2, state, dataArea, this,
    209                                                                        domainAxis, rangeAxis, currentDataset,
    210                                                                        serNo, column, pass);
    211                                                }
    212                                        }
    213                                }
    214                        }
    215                }
    216                return foundData;
    217        }
    218
    219        /**
    220         * Draws the gridlines for the plot.
    221         *
    222         * @param g2  the graphics device.
    223         * @param dataArea      the area inside the axes.
    224         * @param ticks  the ticks.
    225         *
    226         * @see #drawDomainGridlines(Graphics2D, Rectangle2D)
    227         */
    228        @SuppressWarnings("rawtypes")
    229        protected void drawRangeGridlines( final Graphics2D g2, final Rectangle2D dataArea,
    230                                                                           final List ticks ) {
    231                // draw the range grid lines, if any...
    232
    233                if (isRangeGridlinesVisible()) {
    234                        Stroke gridStroke = getRangeGridlineStroke();
    235                        Paint gridPaint = getRangeGridlinePaint();
    236                        if ((gridStroke != null) && (gridPaint != null)) {
    237                                ValueAxis axis = getRangeAxis();
    238                                CategoryItemRenderer renderer1 = getRenderer();
    239                                if (axis != null && renderer1 != null) {
    240                                        Iterator<?> iterator = ticks.iterator();
    241                                        int cnt = 0;
    242                                        while (iterator.hasNext()) {
    243                                                ValueTick tick = (ValueTick) iterator.next();
    244                                                if( cnt % rangeSkip == 0 ) {
    245                                                        renderer1.drawRangeGridline(g2, this,
    246                                                                                axis, dataArea, tick.getValue());
    247                                                }
    248                                                cnt++ ;
    249                                        }
    250                                }
    251                        }
    252                }
    253        }
    254
    255        /**
    256         * この文字列と指定されたオブジェクトを比較します。
    257         *
    258         * 親クラスで、equals メソッドが実装されているため、警告がでます。
    259         *
    260         * @og.rev 5.1.8.0 (2010/07/01) findbug対応
    261         * @og.rev 5.1.9.0 (2010/08/01) findbug対応
    262         *
    263         * @param       object  比較するオブジェクト
    264         *
    265         * @return      Objectが等しい場合は true、そうでない場合は false
    266         */
    267        @Override
    268        public boolean equals( final Object object ) {
    269                if( super.equals( object ) ) {
    270                        return hsCode == ((HybsCategoryPlot)object).hsCode;
    271                }
    272                return false;
    273        }
    274
    275        /**
    276         * このオブジェクトのハッシュコードを取得します。
    277         *
    278         * @og.rev 5.1.8.0 (2010/07/01) findbug対応
    279         * @og.rev 5.1.9.0 (2010/08/01) findbug対応
    280         *
    281         * @return      ハッシュコード
    282         */
    283//      public int hashCode() { return super.hashCode() ; }
    284        @Override
    285        public int hashCode() { return hsCode ; }
    286
    287        /**
    288         * このオブジェクトと指定されたオブジェクトを比較します。
    289         *
    290         * @og.rev 4.0.0.0 (2007/11/28) 新規追加
    291         * @og.rev 5.1.4.0 (2010/03/01) 削除します。
    292         *
    293         * @param anObject Object 比較されるオブジェクト
    294         *
    295         * @return      指定されたオブジェクトが等しい場合は true、そうでない場合は false
    296         */
    297//      public boolean equals( final Object anObject ) {
    298//              if( super.equals( anObject ) ) {
    299//                      HybsCategoryPlot other = ((HybsCategoryPlot)anObject);
    300////                    if( other.serNo == serNo && other.isNotify == isNotify ) {
    301//                      if( other.serNo == serNo ) {
    302//                              return true;
    303//                      }
    304//              }
    305//              return false;
    306//      }
    307
    308        /**
    309         * このオブジェクトのハッシュコードを返します。
    310         *
    311         * @og.rev 4.0.0.0 (2007/11/28) 新規追加
    312         * @og.rev 5.1.4.0 (2010/03/01) 削除します。
    313         *
    314         * @return      このオブジェクトのハッシュコード値
    315         */
    316//      public int hashCode() {
    317////            return super.hashCode() + serNo + Boolean.valueOf( isNotify ).hashCode() ;
    318//              return super.hashCode() + serNo ;
    319//      }
    320}