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 instanceof String ) { // 4.3.1.1 (2008/08/23) instanceof チェックは、nullチェック不要 159 lbl = (String)category; 160 if( lbl.startsWith( "_" ) ) { 161 label = NULL_LABEL; 162 } 163 } 164 165 if( cutNo > 0 && lbl != null ) { 166 if( lbl.length() >= cutNo ) { 167 lbl = lbl.substring( 0,cutNo ); 168 } 169 170 if( ! lbl.equals( breakKey ) ) { 171 label = super.createLabel( lbl, width, edge, g2); 172 breakKey = lbl ; 173 } 174 } 175 else { 176 if( count % skip == 0 ) { 177 label = super.createLabel( category, width, edge, g2); 178 } 179 count++; 180 } 181 182 if( label == null ) { 183 label = NULL_LABEL; 184 labelBreak.add( LabelVisible.FALSE ); 185 } 186 else if( label.equals( NULL_LABEL ) ) { 187 labelBreak.add( LabelVisible.UNDER ); 188 } 189 else { 190 labelBreak.add( LabelVisible.TRUE ); 191 } 192 193 return label; 194 } 195 196 /** 197 * ラベルブレイクするかどうかを返します。 198 * 199 * skip または、cutNo によるラベルの間引き処理で、指定のCategoryAxis 200 * に対するカラム番号を指定する事で、判定値を返します。 201 * 処理が、Label の作成済みかどうかに依存する為、その判定を先に行います。 202 * 203 * @og.rev 4.1.1.0 (2008/02/04) 新規追加 204 * 205 * @param column カラム番号 206 * 207 * @return ラベルブレイクするかどうか(true:する) 208 */ 209 protected boolean isLabelBreak( final int column ) { 210 return labelBreak == null || 211 labelBreak.size() <= column || 212 labelBreak.get( column ).booleanValue() ; 213 } 214 215 /** 216 * ITEM ラベル(各データの設定値の説明用の値)を表示するかどうかを返します。 217 * 218 * ラベルの先頭に、アンダースコアがついたラベルは、ラベルの表示と 219 * ItemLabel の表示を抑止します。(false) 220 * それ以外のラベルは、表示する(true) を返します。 221 * 処理が、Label の作成済みかどうかに依存する為、その判定を先に行います。 222 * 223 * @og.rev 4.1.2.0 (2008/03/12) 新規追加 224 * 225 * @param column カラム番号 226 * 227 * @return ITEMラベルを表示するかどうか(true:する) 228 */ 229 protected boolean isViewItemLabel( final int column ) { 230 boolean flag = labelBreak == null || 231 labelBreak.size() <= column || 232 labelBreak.get( column ) != LabelVisible.UNDER ; 233 234 if( flag && isItemLabelLastVisible && labelBreak.size() -1 != column ) { 235 flag = false; 236 } 237 238 return flag; 239 } 240 241 /** 242 * ドメイン(横軸)のカテゴリ単位のライン(縦線)の描画位置を返します。 243 * 244 * この位置は、labelBreak が存在しないか、または、ブレークするときのみ 245 * 値を返します。これにより、ライン(縦線)の位置を、グラフの中心から 246 * ずらす事が可能になります。 247 * また、labelBreak により、ラベルを描画しない場合は、線の位置を、0 に 248 * 設定する事で、画面から見えなくします。 249 * 250 * @param anchor CategoryAnchorオブジェクト 251 * @param category カテゴリ番号 252 * @param categoryCount カテゴリ数 253 * @param area 範囲を表すRectangle2Dオブジェクト 254 * @param edge ロケーションを指定するRectangleEdgeオブジェクト 255 * 256 * @return ライン(縦線)の描画位置 257 */ 258 @Override 259 public double getCategoryJava2DCoordinate( final CategoryAnchor anchor, 260 final int category, 261 final int categoryCount, 262 final Rectangle2D area, 263 final RectangleEdge edge) { 264 265 final double result ; 266 267 // labelBreak が存在しないか、または、ブレークするときのみ値を返す。 268 if( isLabelBreak( category ) ) { 269 result = super.getCategoryJava2DCoordinate( 270 anchor,category,categoryCount,area,edge 271 ) ; 272 } 273 else { 274 result = 0; 275 } 276 return result ; 277 } 278 279 /** 280 * この文字列と指定されたオブジェクトを比較します。 281 * 282 * 親クラスで、equals メソッドが実装されているため、警告がでます。 283 * 284 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 285 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 286 * 287 * @param object 比較するオブジェクト 288 * 289 * @return Objectが等しい場合は true、そうでない場合は false 290 */ 291 @Override 292 public boolean equals( final Object object ) { 293 if( super.equals( object ) ) { 294 return hsCode == ((HybsCategoryAxis)object).hsCode; 295 } 296 return false; 297 } 298 299 /** 300 * このオブジェクトのハッシュコードを取得します。 301 * 302 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 303 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 304 * 305 * @return ハッシュコード 306 */ 307 @Override 308 public int hashCode() { return hsCode ; } 309}