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     */
016    package org.opengion.hayabusa.io;
017    
018    
019    import java.util.List;
020    import java.util.ArrayList;
021    import java.awt.Graphics2D;
022    import java.awt.geom.Rectangle2D;
023    import org.jfree.ui.RectangleEdge;
024    import org.jfree.text.TextBlock;
025    import org.jfree.chart.axis.AxisState;
026    import org.jfree.chart.axis.CategoryAxis;
027    import org.jfree.chart.axis.CategoryAnchor;
028    
029    /**
030     * HybsCategoryAxis は、CategoryAxis クラスを継承した、横軸管?ラスです?
031     * 横軸ラベルの表示制御を?主に行って?す?
032     * 横軸表示には?つの制御機?がカスタマイズされて?す?
033     *
034     *  ??_" ラベルのスキ??(非表示)
035     *  ?.cutNo 属?による、ラベル?位置??キーブレイク
036     *  ?.skip 属?による、ラベルをスキ??する間隔の??
037     *
038     * 上記??,2,?の?で優先的に処?れます?
039     *
040     * @version  0.9.0      2007/06/21
041     * @author       Kazuhiko Hasegawa
042     * @since        JDK1.1,
043     */
044    public 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             * こ?メソ?では?つの拡張機?を実現して?す?
135             *  ??_" ラベルのスキ??(非表示)
136             *  ?.cutNo 属?による、ラベル?位置??キーブレイク
137             *  ?.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 により、ラベルを描画しな??合?、線?位置を???に
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    }