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 * 逆に、最上位のデータ(シリーズ=0)の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 * drawItem と同等の機能を持った、高速版メソッドです。 143 * 144 * @og.rev 4.1.1.0 (2008/02/04) 新規追加 145 * @og.rev 4.1.2.0 (2008/03/12) ラベルのアンダーライン時にItemLavelを表示しない 146 * @og.rev 5.9.24.3 (2017/09/29) overColor対応 147 * 148 * @param g2 Graphics2Dオブジェクト 149 * @param state CategoryItemRendererStateオブジェクト 150 * @param dataArea Rectangle2Dオブジェクト 151 * @param plot CategoryPlotオブジェクト 152 * @param domainAxis CategoryAxisオブジェクト 153 * @param rangeAxis ValueAxisオブジェクト 154 * @param dataset CategoryDatasetオブジェクト 155 * @param serNo シリアル番号 156 */ 157 @Override 158 public void drawItem2( final Graphics2D g2, final CategoryItemRendererState state, 159 final Rectangle2D dataArea, final CategoryPlot plot, final CategoryAxis domainAxis, 160 final ValueAxis rangeAxis, final CategoryDataset dataset, final int serNo ) { 161 162 final int clmCount = dataset.getColumnCount(); 163 final int rowCount = dataset.getRowCount(); 164 final RectangleEdge edge = plot.getRangeAxisEdge(); 165 166 final PlotOrientation orientation = plot.getOrientation(); 167 final double minBarLen = getMinimumBarLength(); 168 final double barWidth = state.getBarWidth(); 169 final boolean isDrawOutline = isDrawBarOutline() && 170 state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD ; 171 172 // 4.1.2.0 (2008/03/12) 173 HybsCategoryAxis hybsAxis = null; 174 if( domainAxis instanceof HybsCategoryAxis ) { 175 hybsAxis = (HybsCategoryAxis)domainAxis; 176 hybsAxis.setItemLabelLastVisible( isLastVisible ); // 6.0.2.5 (2014/10/31) refactoring 177 } 178 179 for( int row=0; row<rowCount; row++ ) { 180 final boolean isLabelsVisible = isSeriesItemLabelsVisible( row ); // 6.0.2.5 (2014/10/31) refactoring 181 182 for( int column=0; column<clmCount; column++ ) { 183 final Number v1Num = dataset.getValue( row,column ); 184 if( v1Num == null ) { continue; } 185 final double value = v1Num.doubleValue(); 186 187 // 書き出し開始位置をずらす。 188 final double barW0 = calculateBarW0( plot,orientation,dataArea,domainAxis,state,row,column ); 189 final double[] barL0L1 = calculateBarL0L1( value ); 190 if( barL0L1 == null ) { continue; } 191 192 final double transL0 = rangeAxis.valueToJava2D( barL0L1[0],dataArea,edge ); 193 final double transL1 = rangeAxis.valueToJava2D( barL0L1[1],dataArea,edge ); 194 final double barL0 = Math.min( transL0,transL1 ); 195 final double barLength = Math.max( Math.abs( transL1 - transL0 ),minBarLen ); 196 197 // Bar の描画 198 Rectangle2D bar = null; 199 if( orientation == PlotOrientation.HORIZONTAL ) { 200 bar = new Rectangle2D.Double( barL0,barW0,barLength,barWidth ); 201 } 202 else { 203 bar = new Rectangle2D.Double( barW0,barL0,barWidth,barLength ); 204 } 205 206 Paint itemPaint = getItemPaint( row,column ); 207 // 4.3.1.1 (2008/08/23) 変数名を t ⇒ gpt に変更 208 final GradientPaintTransformer gpt = getGradientPaintTransformer(); 209 if( gpt != null && itemPaint instanceof GradientPaint ) { 210 itemPaint = gpt.transform( (GradientPaint) itemPaint,bar ); 211 } 212 213 // 5.9.24.3 (2017/09/29) overColor対応 214 if( overColors != null ) { 215 if( dynamicOCNo >= 0 ) { 216 itemPaint = overColors.getColor( value,dataset.getValue( dynamicOCNo,column ) ); 217 } 218 else { 219 itemPaint = overColors.getColor( value ); 220 } 221 } 222 223 g2.setPaint( itemPaint ); 224 g2.fill( bar ); 225 226 // outline の描画 227 if( isDrawOutline ) { 228 final Stroke stroke = getItemOutlineStroke( row,column ); 229 final Paint paint = getItemOutlinePaint( row,column ); 230 if( stroke != null && paint != null ) { 231 g2.setStroke( stroke ); 232 g2.setPaint( paint ); 233 g2.draw( bar ); 234 } 235 } 236 237 // ItemLabel の描画 238 final CategoryItemLabelGenerator generator = getItemLabelGenerator( row,column ); 239 // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined 240// if( generator != null && isLabelsVisible ) { // 6.0.2.5 (2014/10/31) refactoring 241// // 4.1.2.0 (2008/03/12) アンダースコアの場合は、表示しない。 242// if( hybsAxis != null && hybsAxis.isViewItemLabel( column ) ) { 243 if( generator != null && isLabelsVisible // 6.0.2.5 (2014/10/31) refactoring 244 // 4.1.2.0 (2008/03/12) アンダースコアの場合は、表示しない。 245 && hybsAxis != null && hybsAxis.isViewItemLabel( column ) ) { 246 drawItemLabel( g2,dataset,row,column,plot,generator,bar, value<0.0 ); 247// } 248 } 249 // 4.3.1.0 (2008/08/09) item entity の追加 250 final EntityCollection entities = state.getEntityCollection(); 251 if( entities != null ) { 252 addItemEntity( entities, dataset, row, column, bar ); 253 } 254 } 255 } 256 } 257 258 /** 259 * この文字列と指定されたオブジェクトを比較します。 260 * 261 * 親クラスで、equals メソッドが実装されているため、警告がでます。 262 * 263 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 264 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 265 * 266 * @param object 比較するオブジェクト 267 * 268 * @return Objectが等しい場合は true、そうでない場合は false 269 */ 270 @Override 271 public boolean equals( final Object object ) { 272 // 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 273 return super.equals( object ) && hsCode == ((HybsBarRenderer)object).hsCode; 274 } 275 276 /** 277 * このオブジェクトのハッシュコードを取得します。 278 * 279 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 280 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 281 * 282 * @return ハッシュコード 283 */ 284 @Override 285 public int hashCode() { return hsCode ; } 286}