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 * 少ない数のグリッド線(例えば、2つおき)を出す場合に、値を設定します。 126 * "1" (初期値)では、1つづつ表示(つまり、すべて表示する)します。 127 * "2" とすると、1つおきに、"3" とすると、2つおきに表示します。 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}