    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 * 横軸表示には、３つの制御機能がカスタマイズされています。
    033 *
    034 *  １．"_" ラベルのスキップ(非表示)
    035 *  ２．cutNo 属性による、ラベル文字位置指定のキーブレイク
    036 *  ３．skip 属性による、ラベルをスキップする間隔の指定
    037 *
    038 * 上記、１，２，３ の順番で優先的に処理されます。
    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         * このメソッドでは、３つの拡張機能を実現しています。
    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 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 により、ラベルを描画しない場合は、線の位置を、０ に
    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}