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 org.jfree.chart.renderer.category.LineAndShapeRenderer;
019    import org.jfree.chart.renderer.category.CategoryItemRendererState;
020    import org.jfree.ui.RectangleEdge;
021    
022    import java.awt.Graphics2D;
023    import java.awt.Shape;
024    import java.awt.Color;
025    import java.awt.Paint;
026    import java.awt.Stroke;
027    import java.awt.geom.Line2D;
028    import java.awt.geom.Rectangle2D;
029    import java.io.IOException;
030    import java.io.ObjectOutputStream;
031    import java.io.ObjectInputStream;
032    
033    import org.jfree.chart.axis.CategoryAxis;
034    import org.jfree.chart.axis.ValueAxis;
035    import org.jfree.chart.entity.EntityCollection;
036    import org.jfree.chart.plot.CategoryPlot;
037    import org.jfree.chart.plot.PlotOrientation;
038    import org.jfree.data.category.CategoryDataset;
039    import org.jfree.data.general.DatasetUtilities;
040    import org.jfree.data.Range;
041    import org.jfree.util.ShapeUtilities;
042    
043    import java.awt.geom.AffineTransform;
044    
045    /**
046     * HybsLineRenderer は、org.jfree.chart.renderer.category.LineAndShapeRenderer ?
047     * 拡張したカスタマイズクラスです?
048     * これは、描画に対して、予め制限を設けて、???度の向上を図って?す?
049     *
050     * @og.rev 3.8.9.2 (2007/07/28) 新規作?
051     *
052     * @version  0.9.0  2001/05/05
053     * @author   Kazuhiko Hasegawa
054     * @since    JDK1.1,
055     */
056    public class HybsLineRenderer extends LineAndShapeRenderer implements HybsDrawItem {
057            private static final long serialVersionUID = 519020100801L ;
058    
059            private transient ValueMarkOverColors overColors = null;        // 4.0.3.0 (2008/01/07) マ?カーラインでShapeを?り替える時?色??
060    
061            private Color[] shapeColors      = null;                // 4.0.3.0 (2008/01/07) ??タ毎にShapeを?り替える時?色??
062            private double  visibleLimit = Double.NEGATIVE_INFINITY;
063            private int             dynamicOCNo  = -1;                      // 4.1.1.0 (2008/02/04) 動的なマ?カーラインの基準シリーズ番号
064            private String  shapeScale       = null;                // 4.1.1.0 (2008/02/04) shapeの大きさの倍率
065            private boolean isItemLabelLastVisible = false; // 4.1.2.0 (2008/03/12)
066            private final int hsCode = Long.valueOf( System.nanoTime() ).hashCode() ;               // 4.3.1.1 (2008/08/23)
067    
068            /**
069             * Creates a renderer with both lines and shapes visible by default.
070             */
071            public HybsLineRenderer() {
072                    super(true, true);
073            }
074    
075            /**
076             * Creates a new renderer with lines and/or shapes visible.
077             *
078             * @param lines  draw lines?
079             * @param shapes  draw shapes?
080             */
081            public HybsLineRenderer( final boolean lines, final boolean shapes ) {
082                    super(lines,shapes);
083            }
084    
085            /**
086             * ??タ毎にShapeを?り替える時?色の繰返しパターンを文字?配?で?します?
087             *
088             * HybsLine でのみ使用可能です?
089             * これは、データそ?も?が?繰返し性のある場合に、その繰返し性に対応し?
090             * 形状のShape を表示させる?合に使用します?
091             * 繰返しShapeの形状は、JFreeChart のシリーズ毎?繰返し標準形状を使用します?
092             * 現在のバ?ジョンでは?0?までの繰返しに対応可能です?
093             * 繰返し色を??した????に使用されて?ます?
094             *
095             * ?文字?は、java.awt.Color クラスのstatic フィールド名で?します?
096             * BLACK , BLUE , CYAN , DARK_GRAY , GRAY , GREEN , LIGHT_GRAY ,
097             * MAGENTA , ORANGE , PINK , RED , WHITE , YELLOW , (PURPLE) が指定できます?
098             * また?#XXXXXX形式?16bitRGB表?でも指定可能です?
099             *
100             * @og.rev 4.0.3.0 (2008/01/07) 新規追?
101             *
102             * @param       colors  ??タ毎?色の繰返しパターン(??配?)
103             * @see         java.awt.Color#BLACK
104             */
105            protected void setShapeColors( final Color[] colors ) {
106                    shapeColors = colors;
107            }
108    
109            /**
110             * shapeの大きさを??定で変更しま?初期値:null)?
111             *
112             * ラインチャート?Shape(?ラフ?ポイント?マ?カー)の大きさは??常は?
113             * 自動設定されます?
114             * こ?大きさを?倍率?で、変更可能です?
115             * ??、double 型です?
116             * 初期値は、null は、スケール変更しません(自動設定?ままの大きさ)
117             *
118             * @og.rev 4.1.1.0 (2008/02/04) 新規追?
119             *
120             * @param       scale   shapeの大きさの倍率
121             */
122            protected void setShapeScale( final String scale ) {
123                    shapeScale = scale;
124            }
125    
126            /**
127             * マ?カーラインの?時?Shape色管?ラスを設定します?
128             *
129             * 動的なマ?カーラインを使用する場合?、引数のシリーズ??タ?
130             * マ?カーラインの?位閾値に相当します?これは、グラフ化されますが?
131             * Shape は自動的に削除されます?
132             * ?、最上位???タ(シリーズ??のShape は?付けます?
133             *
134             * @og.rev 4.1.0.1(2008/01/19) 新規追?
135             * @og.rev 4.1.1.0 (2008/02/04) 動的なオーバ?カラー
136             *
137             * @param       vmoc    マ?カーラインの?時?Shape色管?ラス
138             * @param       dynamicOverColorNo      動的なマ?カーラインの基準シリーズ番号
139             */
140            protected void setValueMarkOverColors( final ValueMarkOverColors vmoc,
141                                                                                    final int dynamicOverColorNo ) {
142                    overColors      = vmoc;
143                    dynamicOCNo     = dynamicOverColorNo;
144            }
145    
146            /**
147             * 表示下限値(これ以下???タは未表示)の値(double)を指定します?
148             *
149             * HybsLine でのみ使用可能です?
150             * こ?設定?以下???タは、存在しな??します?
151             * Lineを引くとき?こ???タと、存在して???タ間にラインは引かれません?
152             * 何も?しな??合?、設定しません?
153             *
154             * @og.rev 4.0.3.0 (2008/01/07) 新規追?
155             *
156             * @param       limit   表示下限値(これ以下???タは未表示)
157             */
158            protected void setVisibleLimit( final double limit ) {
159                    visibleLimit = limit;
160            }
161    
162            /**
163             * itemLabelVisible 時に、最後?値のみ表示するかど?[true:有効/false:無効]を指定します?
164             *
165             * これは、itemLabelVisible 属?に?last" と?設定?を指定した?合??
166             * ??みラベル表示します?
167             * こ?メソ?では、true が指定された場合??last" 属?が有効になったと
168             * 判断します?
169             *
170             * @og.rev 4.1.2.0 (2008/03/12) 新規追?
171             *
172             * @param       flag    ??値のみ表示するかど?[true:有効/false:無効]
173             */
174            public void setItemLabelLastVisible( final boolean flag ) {
175                    isItemLabelLastVisible = flag;
176            }
177    
178            /**
179             * drawItem と同等?機?を持った?高?版メソ?です?
180             *
181             * @og.rev 4.0.3.0 (2008/01/07) shapeColors 属?追?
182             * @og.rev 4.1.1.0 (2008/02/04) 繰返しshapeの開始番号(shapeStartNo)追?
183             * @og.rev 4.1.1.0 (2008/02/04) seriesColors 属?は、色(Paint)のみ?替えるようにする?
184             * @og.rev 4.1.1.0 (2008/02/04) ラベルブレイク機?の追?HybsCategoryAxis)
185             * @og.rev 4.1.1.0 (2008/02/04) 動的なマ?カーライン
186             * @og.rev 4.1.1.0 (2008/02/22) Stroke を設定するロジ?を追?
187             * @og.rev 4.1.2.0 (2008/03/12) ラベルのアン??ライン時にItemLavelを表示しな?
188             *
189             * @param g2                    Graphics2Dオブジェク?
190             * @param state                 CategoryItemRendererStateオブジェク?
191             * @param dataArea              Rectangle2Dオブジェク?
192             * @param plot                  CategoryPlotオブジェク?
193             * @param domainAxis    CategoryAxisオブジェク?
194             * @param rangeAxis             ValueAxisオブジェク?
195             * @param dataset               CategoryDatasetオブジェク?
196             * @param serNo                 シリアル番号
197             */
198            public void drawItem2( final Graphics2D g2, final CategoryItemRendererState state,
199                            final Rectangle2D dataArea, final CategoryPlot plot, final CategoryAxis domainAxis,
200                            final ValueAxis rangeAxis, final CategoryDataset dataset, final int serNo ) {
201    
202                    int clmCount = dataset.getColumnCount();
203                    int rowCount = dataset.getRowCount();
204                    RectangleEdge domEdge   = plot.getDomainAxisEdge();
205                    RectangleEdge rangeEdge = plot.getRangeAxisEdge();
206    
207                    boolean isShape = getBaseShapesVisible() ;
208    
209                    HybsCategoryAxis hybsAxis = null;
210                    if( domainAxis instanceof HybsCategoryAxis ) {
211                            hybsAxis = (HybsCategoryAxis)domainAxis;
212                            hybsAxis.setItemLabelLastVisible( isItemLabelLastVisible );
213                    }
214    
215                    // ??タ毎にShapeを?り替える時?色の繰返しパターン
216                    int shpCnt = ( shapeColors == null ) ? 1 : shapeColors.length;
217    
218                    // Shape の形状を指定できる。任意ではなく?表示??開始位置の??
219                    int shapeNo = 0 ;
220    
221                    // shapeの大きさの倍率
222                    AffineTransform transform = null;
223                    if( shapeScale != null ) {
224                            double scale = Double.parseDouble( shapeScale );
225                            transform = AffineTransform.getScaleInstance( scale, scale );
226                    }
227    
228                    // 4.1.1.0 (2008/02/22) Stroke を設定するロジ?を追?
229                    Stroke baseStroke = getBaseStroke();
230                    if( baseStroke != null ) { g2.setStroke( baseStroke ); }
231    
232                    // トリ?ー?row == serNo を??たいがために?回余?にループをまわす?
233                    for( int row=0; row<=rowCount; row++ ) {
234                            if( row == serNo ) { continue; }        // Mis Add 2007/07/23
235                            if( row >= rowCount ) {
236                                    if( serNo >= 0 ) {
237                                            row = serNo;
238                                            rowCount = -1;          // 終?件
239                                    }
240                                    else {
241                                            break;
242                                    }
243                            }
244    
245                            // 4.1.1.0 (2008/02/22) Stroke を設定するロジ?を追?
246                            Stroke serStroke = getSeriesStroke( row );
247                            if( serStroke != null ) { g2.setStroke( serStroke ); }
248    
249                            Paint rowPaint = lookupSeriesPaint( row );
250                            Shape rowShape = lookupSeriesShape( shapeNo );
251    
252                            // shapeの大きさの倍率
253                            if( transform != null ) {
254                                    rowShape = transform.createTransformedShape(rowShape);
255                            }
256    
257                            Paint linePaint = rowPaint ;
258                            // 4.1.1.0 (2008/02/04) 動的なマ?カーライン(row==dynamicOCNoの??タで判?
259                            boolean shapeFlag = false;
260                            if( row == dynamicOCNo ) {      // 使わな??合??1 なので、??しな??
261                                    if( overColors != null ) {
262                                            linePaint = overColors.getDynamicColor();
263                                    }
264                            }
265                            else {
266                                    // 動的なマ?カーライン使用?dynamicOCNo >= 0)は、row == 0 で、Shape を使?す?
267                                    if( isShape || row == serNo || ( dynamicOCNo >= 0 && row == 0 ) ) {
268                                            shapeFlag = true;
269                                            shapeNo++ ;             // Shape 形状の変更は、使用した場合?み
270                                    }
271                            }
272    
273                            double v0 = 0;
274                            double x0 = 0;
275                            double y0 = 0;
276    
277                            boolean isItemLabelsVisible = isSeriesItemLabelsVisible( row );
278    
279                            int clmSeq = 0;         // カラ??繰返し制御(Shape色の?表示用)
280                            for( int column=0; column<clmCount; column++ ) {
281                                    // nothing is drawn for null...
282                                    Number v1Num = dataset.getValue( row,column );
283                                    if(v1Num == null) { continue; }
284                                    double v1 = v1Num.doubleValue();
285                                    double x1 = domainAxis.getCategoryMiddle( column,clmCount,dataArea,domEdge );
286                                    double y1 = rangeAxis.valueToJava2D( v1,dataArea,rangeEdge );
287    
288                                    // Line の描画
289                                    if( column > 0 && v0 >= visibleLimit && v1 >= visibleLimit ) {
290                                            Line2D line = new Line2D.Double( x0,y0,x1,y1 );
291                                            g2.setPaint( linePaint );
292                                            g2.draw( line );
293                                    }
294    
295                                    // Shape の描画
296                                    if( shapeFlag ) {
297                                            // ラベルブレイク処?
298                                            if( hybsAxis != null && hybsAxis.isLabelBreak( column ) ) {
299                                                    clmSeq = 0;             // 初期?
300                                            }
301    
302                                            int adrs = clmSeq%shpCnt;
303                                            clmSeq++ ;
304                                            Paint paint = ( shapeColors == null ) ? rowPaint : shapeColors[adrs];
305                                            // 4.1.1.0 (2008/02/04) 動的なマ?カーライン(row==dynamicOCNoの??タで判?
306                                            if( overColors != null ) {
307                                                    if( dynamicOCNo >= 0 ) {
308                                                            paint = overColors.getColor( v1,dataset.getValue( dynamicOCNo,column ) );
309                                                    }
310                                                    else {
311                                                            paint = overColors.getColor( v1 );
312                                                    }
313                                            }
314                                            g2.setPaint(paint);
315                                            Shape shape = ShapeUtilities.createTranslatedShape( rowShape,x1,y1 );
316                                            g2.fill(shape);
317                                            g2.setPaint(rowPaint);  // 色を戻す?
318                                            // 4.3.1.0 (2008/08/09) add an item entity, if this information is being collected
319                                            EntityCollection entities = state.getEntityCollection();
320                                            if( entities != null ) {
321                                                    addItemEntity( entities, dataset, row, column, shape );
322                                            }
323                                    }
324    
325                                    // ItemLabel の描画
326                                    //   山形 0-1-0 nega=fale , x= 0 上中
327                                    //   右?0-1-2 nega=true , x=10 下右
328                                    //   谷形 1-0-1 nega=true , x= 0 下中
329                                    //   左?2-1-0 nega=fale , x=10 上右
330                                    if( isItemLabelsVisible ) {
331                                            // 4.1.2.0 (2008/03/12) アン??スコアの場合?、表示しな??
332                                            if( hybsAxis != null && hybsAxis.isViewItemLabel( column ) ) {
333                                                    double v2 = v0 ;        // 仮設???columnとnull の場?
334                                                    if( column+1 < clmCount ) {
335                                                            Number v2Num = dataset.getValue( row,column+1 );
336                                                            if( v2Num != null ) {
337                                                                    v2 = v2Num.doubleValue();
338                                                            }
339                                                    }
340                                                    boolean nega = ( v1<v2 ) ;
341                                                    double  lblx = ( nega && v0<v1 || !nega && v0>v1 ) ? x1 + 10 : x1 ;
342    
343                                                    drawItemLabel( g2,PlotOrientation.VERTICAL,dataset,row,column,lblx,y1,nega );
344                                            }
345                                    }
346    
347                                    v0 = v1;        // Lineを消す処??去の値が??
348                                    x0 = x1;
349                                    y0 = y1;
350                            }
351                    }
352            }
353    
354            /**
355             * こ???と?されたオブジェクトを比?ます?
356             *
357             * 親クラスで、equals メソ?が実?れて?ため、警告がでます?
358             *
359             * @og.rev 5.1.8.0 (2010/07/01) findbug対?
360             *
361             * @param object Object
362             *
363             * @return      Objectが等し??合? true、そ?な??合? false
364             */
365    //      @Override
366    //      public boolean equals( final Object object ) {
367    //              return super.equals( object );
368    //      }
369    
370            /**
371             * こ?オブジェクト?ハッシュコードを取得します?
372             *
373             * @og.rev 5.1.8.0 (2010/07/01) findbug対?
374             *
375             * @return      ハッシュコー?
376             */
377    //      public int hashCode() { return super.hashCode() ; }
378    
379            /**
380             * こ?オブジェクトと?されたオブジェクトを比?ます?
381             *
382             * @og.rev 4.3.1.1 (2008/08/23) 新規追?
383             * @og.rev 5.1.9.0 (2010/08/01) findbug対?
384             *
385             * @param       anObject        比?れるオブジェク?
386             *
387             * @return      ?されたオブジェクトが等し??合? true、そ?な??合? false
388             */
389            @Override
390            public boolean equals( final Object anObject ) {
391    //              return this == anObject;
392                    if( super.equals( anObject ) ) {
393                            return hsCode == ((HybsLineRenderer)anObject).hsCode;
394                    }
395                    return false;
396            }
397    
398            /**
399             * こ?オブジェクト?ハッシュコードを返します?
400             *
401             * @og.rev 4.3.1.1 (2008/08/23) 新規追?
402             * @og.rev 5.1.9.0 (2010/08/01) findbug対?
403             *
404             * @return      こ?オブジェクト?ハッシュコード?
405             */
406            @Override
407            public int hashCode() { return hsCode ; }
408    
409            /**
410             * ?された??タセ?からのアイ?をすべて表示するために、要求する?の?を返します?
411             *
412             * @param       dataset カ?リDataset
413             *
414             * @return      Rangeオブジェク?
415             */
416            @Override
417            public Range findRangeBounds( final CategoryDataset dataset ) {
418                    if( dataset instanceof HybsJDBCCategoryDataset2 ) {
419                            return ((HybsJDBCCategoryDataset2)dataset).getRange();
420                    }
421                    else {
422                            return DatasetUtilities.findRangeBounds(dataset);
423                    }
424            }
425    
426            /**
427             * シリアライズ用のカスタ?リアライズ書き込みメソ?
428             *
429             * @og.rev 4.1.0.1(2008/01/19) 新規追?
430             * @serialData
431             *
432             * @param       strm    ObjectOutputStreamオブジェク?
433             */
434            private void writeObject( final ObjectOutputStream strm ) throws IOException {
435                    strm.defaultWriteObject();
436            }
437    
438            /**
439             * シリアライズ用のカスタ?リアライズ読み込みメソ?
440             *
441             * ここでは、transient 宣?れた?変数の??初期化が?なフィールド?み設定します?
442             *
443             * @og.rev 4.1.0.1(2008/01/19) 新規追?
444             * @serialData
445             *
446             * @param       strm    ObjectInputStreamオブジェク?
447             */
448            private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
449                    strm.defaultReadObject();
450            }
451    }