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 018 019import java.util.List; 020import java.util.ArrayList; 021import java.awt.Graphics2D; 022import java.awt.geom.Rectangle2D; 023import org.jfree.ui.RectangleEdge; 024import org.jfree.text.TextBlock; 025import org.jfree.chart.axis.AxisState; 026import org.jfree.chart.axis.CategoryAxis; 027import org.jfree.chart.axis.CategoryAnchor; 028 029/** 030 * HybsCategoryAxis は、CategoryAxis クラスを継承した、横軸管理クラスです。 031 * 横軸ラベルの表示制御を、主に行っています。 032 * 横軸表示には、3つの制御機能がカスタマイズされています。 033 * 034 * 1."_" ラベルのスキップ(非表示) 035 * 2.cutNo 属性による、ラベル文字位置指定のキーブレイク 036 * 3.skip 属性による、ラベルをスキップする間隔の指定 037 * 038 * 上記、1,2,3 の順番で優先的に処理されます。 039 * 040 * @version 0.9.0 2007/06/21 041 * @author Kazuhiko Hasegawa 042 * @since JDK1.1, 043 */ 044public class HybsCategoryAxis extends CategoryAxis { 045 private static final long serialVersionUID = 519020100801L; 046 047 private static final TextBlock NULL_LABEL = new TextBlock() ; 048 049 // 4.1.2.0 (2008/03/12) 新規追加 050 private enum LabelVisible { TRUE(true) , FALSE(false) , UNDER(true) ; 051 private final boolean flag ; 052 LabelVisible( boolean flag ) { this.flag = flag; } 053 public boolean booleanValue() { return flag; } 054 }; 055 056 /** For serialization. */ 057 private int skip = 1; // skip数 058 private int count = 0; // skip 時の現在位置のカウント 059 060 private transient List<LabelVisible> labelBreak = null; 061 private int cutNo = -1; // 4.1.1.0 (2008/02/04) ラベルブレイクのsubstring 位置 062 private String breakKey = null; // 4.1.1.0 (2008/02/04) ラベルブレイクの前回キー 063 private boolean isItemLabelLastVisible = false; // 4.1.2.0 (2008/03/12) 064 private final int hsCode = Long.valueOf( System.nanoTime() ).hashCode() ; // 5.1.9.0 (2010/08/01) equals,hashCode 065 066 /** 067 * 引数を指定して作成する コンストラクター 068 * 069 * skip(ラベルの表示間隔) = 1 , cutNo(ラベルブレイクのsubstring 位置) = -1 で初期化します。 070 * 071 * @param label ラベル 072 */ 073 public HybsCategoryAxis( final String label ) { 074 this( label,1,-1 ); 075 } 076 077 /** 078 * 引数を指定して作成する コンストラクター 079 * 080 * @og.rev 4.1.1.0 (2008/02/04) cutNo 新規追加 081 * 082 * @param label ラベル 083 * @param skip ラベルの表示間隔 084 * @param cutNo ラベルブレイクのsubstring 位置 085 */ 086 protected HybsCategoryAxis( final String label,final int skip,final int cutNo ) { 087 super( label ); 088 this.skip = skip ; 089 this.cutNo = cutNo ; 090 } 091 092 /** 093 * itemLabelVisible 時に、最後の値のみ表示するかどうか[true/false]を指定します。 094 * 095 * これは、itemLabelVisible 属性に、"last" という設定値を指定した場合は、 096 * 最後のみラベル表示します。 097 * このメソッドでは、true が指定された場合は、"last" 属性が有効になったと 098 * 判断します。 099 * 100 * @og.rev 4.1.2.0 (2008/03/12) 新規追加 101 * 102 * @param flag 最後の値のみ表示するかどうか[true/false] 103 */ 104 protected void setItemLabelLastVisible( final boolean flag ) { 105 isItemLabelLastVisible = flag; 106 } 107 108 /** 109 * 軸を引く場合、使用することができるチックの一時的リストを作成します。 110 * 111 * @og.rev 4.1.1.0 (2008/02/04) labelBreak 新規追加 112 * 113 * @param g2 Graphics2Dオブジェクト(フォント測定に使用) 114 * @param state AxisStateオブジェクト 115 * @param dataArea インサイドエリアを示すRectangle2Dオブジェクト 116 * @param edge ロケーションを指定するRectangleEdgeオブジェクト 117 * 118 * @return チックのリスト 119 */ 120 @Override 121 public List<?> refreshTicks( final Graphics2D g2, 122 final AxisState state, 123 final Rectangle2D dataArea, 124 final RectangleEdge edge) { 125 count = 0; 126 labelBreak = new ArrayList<LabelVisible>(); 127 128 return super.refreshTicks( g2, state, dataArea, edge); 129 } 130 131 /** 132 * TextBlock オブジェクトを作成します。 133 * 134 * このメソッドでは、3つの拡張機能を実現しています。 135 * 1."_" ラベルのスキップ(非表示) 136 * 2.cutNo 属性による、ラベル文字位置指定のキーブレイク 137 * 3.skip 属性による、ラベルをスキップする間隔の指定 138 * cutNo が指定された場合は、skip 処理は行われません。また、 139 * その場合のラベルは、cutNoで指定された先頭文字列のみ表示されます。 140 * 文字列が、cutNoで指定された数より小さい場合は、そのまま使用されます。 141 * 142 * @og.rev 4.1.1.0 (2008/02/04) cutNo,labelBreak 追加 143 * @og.rev 4.1.2.0 (2008/03/12) LabelVisible.UNDER 処理を追加 144 * @og.rev 4.3.1.1 (2008/08/23) lbl の null参照はずしの対応 145 * 146 * @param category カテゴリ名 147 * @param width 幅 148 * @param edge 表示範囲を示すRectangleEdgeオブジェクト 149 * @param g2 Graphics2Dオブジェクト 150 * 151 * @return TextBlockオブジェクト 152 */ 153 @SuppressWarnings("rawtypes") 154 protected TextBlock createLabel( final Comparable category, final float width, 155 final RectangleEdge edge, final Graphics2D g2) { 156 TextBlock label = null ; 157 String lbl = null; 158// if( category != null && category instanceof String ) { 159 if( category instanceof String ) { // 4.3.1.1 (2008/08/23) instanceof チェックは、nullチェック不要 160 lbl = (String)category; 161 if( lbl.startsWith( "_" ) ) { 162 label = NULL_LABEL; 163 } 164 } 165 166// if( lbl.startsWith( "_" ) ) { 167// label = NULL_LABEL; 168// } 169// else if( cutNo > 0 && lbl != null ) { 170 if( cutNo > 0 && lbl != null ) { 171 if( lbl.length() >= cutNo ) { 172 lbl = lbl.substring( 0,cutNo ); 173 } 174 175 if( ! lbl.equals( breakKey ) ) { 176 label = super.createLabel( lbl, width, edge, g2); 177 breakKey = lbl ; 178 } 179 } 180 else { 181 if( count % skip == 0 ) { 182 label = super.createLabel( category, width, edge, g2); 183 } 184 count++; 185 } 186 187 if( label == null ) { 188 label = NULL_LABEL; 189 labelBreak.add( LabelVisible.FALSE ); 190 } 191 else if( label.equals( NULL_LABEL ) ) { 192 labelBreak.add( LabelVisible.UNDER ); 193 } 194 else { 195 labelBreak.add( LabelVisible.TRUE ); 196 } 197 198 return label; 199 } 200 201 /** 202 * ラベルブレイクするかどうかを返します。 203 * 204 * skip または、cutNo によるラベルの間引き処理で、指定のCategoryAxis 205 * に対するカラム番号を指定する事で、判定値を返します。 206 * 処理が、Label の作成済みかどうかに依存する為、その判定を先に行います。 207 * 208 * @og.rev 4.1.1.0 (2008/02/04) 新規追加 209 * 210 * @param column カラム番号 211 * 212 * @return ラベルブレイクするかどうか(true:する) 213 */ 214 protected boolean isLabelBreak( final int column ) { 215 return labelBreak == null || 216 labelBreak.size() <= column || 217 labelBreak.get( column ).booleanValue() ; 218 } 219 220 /** 221 * ITEM ラベル(各データの設定値の説明用の値)を表示するかどうかを返します。 222 * 223 * ラベルの先頭に、アンダースコアがついたラベルは、ラベルの表示と 224 * ItemLabel の表示を抑止します。(false) 225 * それ以外のラベルは、表示する(true) を返します。 226 * 処理が、Label の作成済みかどうかに依存する為、その判定を先に行います。 227 * 228 * @og.rev 4.1.2.0 (2008/03/12) 新規追加 229 * 230 * @param column カラム番号 231 * 232 * @return ITEMラベルを表示するかどうか(true:する) 233 */ 234 protected boolean isViewItemLabel( final int column ) { 235 boolean flag = labelBreak == null || 236 labelBreak.size() <= column || 237 labelBreak.get( column ) != LabelVisible.UNDER ; 238 239 if( flag && isItemLabelLastVisible && labelBreak.size() -1 != column ) { 240 flag = false; 241 } 242 243 return flag; 244 } 245 246 /** 247 * ドメイン(横軸)のカテゴリ単位のライン(縦線)の描画位置を返します。 248 * 249 * この位置は、labelBreak が存在しないか、または、ブレークするときのみ 250 * 値を返します。これにより、ライン(縦線)の位置を、グラフの中心から 251 * ずらす事が可能になります。 252 * また、labelBreak により、ラベルを描画しない場合は、線の位置を、0 に 253 * 設定する事で、画面から見えなくします。 254 * 255 * @param anchor CategoryAnchorオブジェクト 256 * @param category カテゴリ番号 257 * @param categoryCount カテゴリ数 258 * @param area 範囲を表すRectangle2Dオブジェクト 259 * @param edge ロケーションを指定するRectangleEdgeオブジェクト 260 * 261 * @return ライン(縦線)の描画位置 262 */ 263 @Override 264 public double getCategoryJava2DCoordinate( final CategoryAnchor anchor, 265 final int category, 266 final int categoryCount, 267 final Rectangle2D area, 268 final RectangleEdge edge) { 269 270 final double result ; 271 272 // labelBreak が存在しないか、または、ブレークするときのみ値を返す。 273 if( isLabelBreak( category ) ) { 274 result = super.getCategoryJava2DCoordinate( 275 anchor,category,categoryCount,area,edge 276 ) ; 277 } 278 else { 279 result = 0; 280 } 281 return result ; 282 } 283 284 /** 285 * この文字列と指定されたオブジェクトを比較します。 286 * 287 * 親クラスで、equals メソッドが実装されているため、警告がでます。 288 * 289 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 290 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 291 * 292 * @param object 比較するオブジェクト 293 * 294 * @return Objectが等しい場合は true、そうでない場合は false 295 */ 296 @Override 297 public boolean equals( final Object object ) { 298// return super.equals( object ); 299 if( super.equals( object ) ) { 300 return hsCode == ((HybsCategoryAxis)object).hsCode; 301 } 302 return false; 303 } 304 305 /** 306 * このオブジェクトのハッシュコードを取得します。 307 * 308 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 309 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 310 * 311 * @return ハッシュコード 312 */ 313// public int hashCode() { return super.hashCode() ; } 314 @Override 315 public int hashCode() { return hsCode ; } 316 317 /** 318 * Tests this axis for equality with an arbitrary object. 319 * 320 * @og.rev 4.1.0.1(2008/01/19) 新規追加 321 * @og.rev 5.1.8.0 (2010/07/01) 廃止 322 * 323 * @param obj the object (<code>null</code> permitted). 324 * 325 * @return A boolean. 326 */ 327// public boolean equals( final Object obj ) { 328// if( obj == null ) { 329// return false; 330// } 331// if( obj == this ) { 332// return true; 333// } 334// if( !(obj instanceof HybsCategoryAxis) ) { 335// return false; 336// } 337// if( !super.equals(obj) ) { 338// return false; 339// } 340// HybsCategoryAxis that = (HybsCategoryAxis) obj; 341// if( that.count != count || that.skip != skip || that.cutNo != cutNo ) { 342// return false; 343// } 344// 345// return true; 346// } 347 348 /** 349 * Returns a hash code for this object. 350 * 351 * @og.rev 4.1.0.1(2008/01/19) 新規追加 352 * @og.rev 5.1.8.0 (2010/07/01) 廃止 353 * 354 * @return A hash code. 355 */ 356// public int hashCode() { 357// return ( getLabel() + ":" + count + ":" + skip + ":" + cutNo ).hashCode(); 358// } 359}