    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.Stroke;
    022import java.awt.geom.Rectangle2D;
    023import java.awt.Color;
    024
    025import org.jfree.chart.renderer.category.BarRenderer;
    026import org.jfree.chart.renderer.category.CategoryItemRendererState;
    027import org.jfree.chart.axis.CategoryAxis;
    028import org.jfree.chart.axis.ValueAxis;
    029import org.jfree.chart.labels.CategoryItemLabelGenerator;
    030import org.jfree.chart.plot.CategoryPlot;
    031import org.jfree.chart.plot.PlotOrientation;
    032import org.jfree.chart.entity.EntityCollection;
    033import org.jfree.data.category.CategoryDataset;
    034import org.jfree.ui.GradientPaintTransformer;
    035import org.jfree.ui.RectangleEdge;
    036
    037/**
    038 * HybsBarRenderer は、org.jfree.chart.renderer.category.BarRenderer を
    039 * 拡張したカスタマイズクラスです。
    040 * これは、描画に対して、予め制限を設けて、処理速度の向上を図っています。
    041 *
    042 * @og.rev 4.1.1.0 (2008/02/04) 新規作成
    043 *
    044 * @version  0.9.0      2001/05/05
    045 * @author       Kazuhiko Hasegawa
    046 * @since        JDK1.1,
    047 */
    048public class HybsBarRenderer extends BarRenderer implements HybsDrawItem {
    049        private static final long serialVersionUID = 602120140926L ;
    050
    051        private transient ValueMarkOverColors overColors ;      // 5.9.24.3 (2017/09/29) マーカーラインでShapeを切り替える時の色指定
    052        private int             dynamicOCNo  = -1;                                      // 4.1.1.0 (2008/02/04) 動的なマーカーラインの基準シリーズ番号
    053
    054        private boolean isLastVisible                   ;                       // 4.1.2.0 (2008/03/12) 6.0.2.5 (2014/10/31) refactoring
    055        private Color[] categoryColor                   ;                       // 6.0.2.1 (2014/09/26) categoryカラー配列
    056        private final int hsCode = Long.valueOf( System.nanoTime() ).hashCode() ;       // 5.1.9.0 (2010/08/01) equals,hashCode
    057
    058        /**
    059         * デフォルトコンストラクター
    060         *
    061         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    062         */
    063        public HybsBarRenderer() { super(); }           // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    064
    065        /**
    066         * itemLabelVisible 時に、最後の値のみ表示するかどうか[true:有効/false:無効]を指定します。
    067         *
    068         * これは、itemLabelVisible 属性に、"last" という設定値を指定した場合は、
    069         * 最後のみラベル表示します。
    070         * このメソッドでは、true が指定された場合は、"last" 属性が有効になったと
    071         * 判断します。
    072         * (独自メソッド。HybsDrawItem より継承)
    073         *
    074         * @og.rev 4.1.2.0 (2008/03/12) 新規追加
    075         *
    076         * @param       flag    最後の値のみ表示するかどうか[true:有効/false:無効]
    077         */
    078        @Override
    079        public void setItemLabelLastVisible( final boolean flag ) {
    080                isLastVisible = flag;                                   // 6.0.2.5 (2014/10/31) refactoring
    081        }
    082
    083        /**
    084         * マーカーラインの超過時のShape色管理クラスを設定します。
    085         *
    086         * 動的なマーカーラインを使用する場合は、引数のシリーズデータが
    087         * マーカーラインの最下位閾値に相当します。これは、グラフ化されますが、
    088         * Shape は自動的に削除されます。
    089         * 逆に、最上位のデータ(シリーズ＝０)のShape は必ず付けます。
    090         *
    091         * @og.rev 4.1.0.1(2008/01/19) 新規追加
    092         *
    093         * @param       vmoc    マーカーラインの超過時のShape色管理クラス
    094         * @param       dynamicOverColorNo      動的なマーカーラインの基準シリーズ番号
    095         */
    096        protected void setValueMarkOverColors( final ValueMarkOverColors vmoc,
    097                                                                                final int dynamicOverColorNo ) {
    098                overColors      = vmoc;
    099                dynamicOCNo     = dynamicOverColorNo;
    100        }
    101
    102        /**
    103         * categoryカラー配列を設定します。
    104         *
    105         * これは、HybsJDBCCategoryDataset クラスで、カテゴリカラーを指定した場合に、
    106         * そこから取り出した値をセットすることで、Hybs***Renderer に設定して使います。
    107         * Hybs***Renderer 側では、このカラー配列を使用して、getItemPaint(int,int) を
    108         * オーバーライドして使います。
    109         * (独自メソッド。HybsDrawItem より継承)
    110         *
    111         * @og.rev 6.0.2.1 (2014/09/26) 新規追加
    112         *
    113         * @param       cateColor       categoryカラー配列(可変長引数)
    114         */
    115        @Override
    116        public void setCategoryColor( final Color... cateColor ) {
    117                // 6.0.2.5 (2014/10/31) refactoring
    118                if( cateColor != null ) { categoryColor = cateColor.clone(); }          // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
    119        }
    120
    121        /**
    122         * カテゴリ違いのColorオブジェクトを返します。
    123         *
    124         * Returns the paint used to color data items as they are drawn.
    125         * <p>
    126         * The default implementation passes control to the
    127         * <code>lookupSeriesPaint()</code> method. You can override this method
    128         * if you require different behaviour.
    129         *
    130         * @param row  the row (or series) index (zero-based).
    131         * @param column  the column (or category) index (zero-based).
    132         *
    133         * @return カテゴリ違いのColorオブジェクト
    134         */
    135        @Override
    136        public Paint getItemPaint( final int row, final int column ) {
    137                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
    138                return categoryColor == null ? super.getItemPaint( row,column ) : categoryColor[column];
    139
    140        }
    141
    142        /**
    143         * drawItem と同等の機能を持った、高速版メソッドです。
    144         *
    145         * @og.rev 4.1.1.0 (2008/02/04) 新規追加
    146         * @og.rev 4.1.2.0 (2008/03/12) ラベルのアンダーライン時にItemLavelを表示しない
    147         * @og.rev 5.9.24.3 (2017/09/29) overColor対応
    148         *
    149         * @param g2                    Graphics2Dオブジェクト
    150         * @param state                 CategoryItemRendererStateオブジェクト
    151         * @param dataArea              Rectangle2Dオブジェクト
    152         * @param plot                  CategoryPlotオブジェクト
    153         * @param domainAxis    CategoryAxisオブジェクト
    154         * @param rangeAxis             ValueAxisオブジェクト
    155         * @param dataset               CategoryDatasetオブジェクト
    156         * @param serNo                 シリアル番号
    157         */
    158        @Override
    159        public void drawItem2( final Graphics2D g2, final CategoryItemRendererState state,
    160                        final Rectangle2D dataArea, final CategoryPlot plot, final CategoryAxis domainAxis,
    161                        final ValueAxis rangeAxis, final CategoryDataset dataset, final int serNo ) {
    162
    163                final int clmCount = dataset.getColumnCount();
    164                final int rowCount = dataset.getRowCount();
    165                final RectangleEdge edge = plot.getRangeAxisEdge();
    166
    167                final PlotOrientation orientation = plot.getOrientation();
    168                final double minBarLen = getMinimumBarLength();
    169                final double barWidth  = state.getBarWidth();
    170                final boolean isDrawOutline = isDrawBarOutline() &&
    171                                                                        state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD ;
    172
    173                // 4.1.2.0 (2008/03/12)
    174                HybsCategoryAxis hybsAxis = null;
    175                if( domainAxis instanceof HybsCategoryAxis ) {
    176                        hybsAxis = (HybsCategoryAxis)domainAxis;
    177                        hybsAxis.setItemLabelLastVisible( isLastVisible );                              // 6.0.2.5 (2014/10/31) refactoring
    178                }
    179
    180                for( int row=0; row<rowCount; row++ ) {
    181                        final boolean isLabelsVisible = isSeriesItemLabelsVisible( row );               // 6.0.2.5 (2014/10/31) refactoring
    182
    183                        for( int column=0; column<clmCount; column++ ) {
    184                                final Number v1Num = dataset.getValue( row,column );
    185                                if( v1Num == null ) { continue; }
    186                                final double value = v1Num.doubleValue();
    187
    188                                // 書き出し開始位置をずらす。
    189                                final double barW0 = calculateBarW0( plot,orientation,dataArea,domainAxis,state,row,column );
    190                                final double[] barL0L1 = calculateBarL0L1( value );
    191                                if( barL0L1 == null ) { continue; }
    192
    193                                final double transL0 = rangeAxis.valueToJava2D( barL0L1[0],dataArea,edge );
    194                                final double transL1 = rangeAxis.valueToJava2D( barL0L1[1],dataArea,edge );
    195                                final double barL0 = Math.min( transL0,transL1 );
    196                                final double barLength = Math.max( Math.abs( transL1 - transL0 ),minBarLen );
    197
    198                                // Bar の描画
    199                                Rectangle2D bar = null;
    200                                if( orientation == PlotOrientation.HORIZONTAL ) {
    201                                        bar = new Rectangle2D.Double( barL0,barW0,barLength,barWidth );
    202                                }
    203                                else {
    204                                        bar = new Rectangle2D.Double( barW0,barL0,barWidth,barLength );
    205                                }
    206
    207                                Paint itemPaint = getItemPaint( row,column );
    208                                // 4.3.1.1 (2008/08/23) 変数名を t ⇒ gpt に変更
    209                                final GradientPaintTransformer gpt = getGradientPaintTransformer();
    210                                if( gpt != null && itemPaint instanceof GradientPaint ) {
    211                                        itemPaint = gpt.transform( (GradientPaint) itemPaint,bar );
    212                                }
    213
    214                                // 5.9.24.3 (2017/09/29) overColor対応
    215                                if( overColors != null ) {
    216                                        if( dynamicOCNo >= 0 ) {
    217                                                itemPaint = overColors.getColor( value,dataset.getValue( dynamicOCNo,column ) );
    218                                        }
    219                                        else {
    220                                                itemPaint = overColors.getColor( value );
    221                                        }
    222                                }
    223
    224                                g2.setPaint( itemPaint );
    225                                g2.fill( bar );
    226
    227                                // outline の描画
    228                                if( isDrawOutline ) {
    229                                        final Stroke stroke = getItemOutlineStroke( row,column );
    230                                        final Paint paint = getItemOutlinePaint( row,column );
    231                                        if( stroke != null && paint != null ) {
    232                                                g2.setStroke( stroke );
    233                                                g2.setPaint( paint );
    234                                                g2.draw( bar );
    235                                        }
    236                                }
    237
    238                                // ItemLabel の描画
    239                                final CategoryItemLabelGenerator generator = getItemLabelGenerator( row,column );
    240                                // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined
    241//                              if( generator != null && isLabelsVisible ) {            // 6.0.2.5 (2014/10/31) refactoring
    242//                                      // 4.1.2.0 (2008/03/12) アンダースコアの場合は、表示しない。
    243//                                      if( hybsAxis != null && hybsAxis.isViewItemLabel( column ) ) {
    244                                if( generator != null && isLabelsVisible                        // 6.0.2.5 (2014/10/31) refactoring
    245                                        // 4.1.2.0 (2008/03/12) アンダースコアの場合は、表示しない。
    246                                        && hybsAxis != null && hybsAxis.isViewItemLabel( column ) ) {
    247                                                drawItemLabel( g2,dataset,row,column,plot,generator,bar, value<0.0 );
    248//                                      }
    249                                }
    250                                // 4.3.1.0 (2008/08/09) item entity の追加
    251                                final EntityCollection entities = state.getEntityCollection();
    252                                if( entities != null ) {
    253                                        addItemEntity( entities, dataset, row, column, bar );
    254                                }
    255                        }
    256                }
    257        }
    258
    259        /**
    260         * この文字列と指定されたオブジェクトを比較します。
    261         *
    262         * 親クラスで、equals メソッドが実装されているため、警告がでます。
    263         *
    264         * @og.rev 5.1.8.0 (2010/07/01) findbug対応
    265         * @og.rev 5.1.9.0 (2010/08/01) findbug対応
    266         *
    267         * @param       object  比較するオブジェクト
    268         *
    269         * @return      Objectが等しい場合は true、そうでない場合は false
    270         */
    271        @Override
    272        public boolean equals( final Object object ) {
    273                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
    274                return super.equals( object ) && hsCode == ((HybsBarRenderer)object).hsCode;
    275
    276        }
    277
    278        /**
    279         * このオブジェクトのハッシュコードを取得します。
    280         *
    281         * @og.rev 5.1.8.0 (2010/07/01) findbug対応
    282         * @og.rev 5.1.9.0 (2010/08/01) findbug対応
    283         *
    284         * @return      ハッシュコード
    285         */
    286        @Override
    287        public int hashCode() { return hsCode ; }
    288}