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    import java.awt.Graphics2D;
019    import java.awt.Stroke;
020    import java.awt.Paint;
021    import java.awt.geom.Rectangle2D;
022    import java.util.List;
023    import java.util.Map;
024    import java.util.HashMap;
025    import java.util.Iterator;
026    
027    import org.jfree.chart.plot.CategoryPlot;
028    import org.jfree.chart.plot.PlotRenderingInfo;
029    import org.jfree.chart.urls.CategoryURLGenerator;
030    import org.jfree.chart.axis.CategoryAxis;
031    import org.jfree.chart.axis.ValueAxis;
032    import org.jfree.chart.axis.ValueTick;
033    import org.jfree.chart.renderer.category.CategoryItemRenderer;
034    import org.jfree.chart.renderer.category.CategoryItemRendererState;
035    import org.jfree.chart.renderer.category.StackedBarRenderer;
036    import org.jfree.data.category.CategoryDataset;
037    import 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     */
053    public 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             * 少なã�?•°のグリãƒ?ƒ‰ç·?例えばã€?¼’つおき)をå?すå?合に、å?を設定しますã?
126             * "1" (初期値)ではã€?¼‘つづつ表示(つまりã?すべて表示する)しますã?
127             * "2" とするとã€?¼‘つおきにã€?3" とするとã€?¼’つおきに表示しますã?
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    }