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 018import java.awt.GradientPaint; 019import java.awt.Graphics2D; 020import java.awt.Paint; 021import java.awt.geom.Rectangle2D; 022 023import org.jfree.chart.entity.EntityCollection; 024import org.jfree.chart.renderer.category.StackedBarRenderer; 025import org.jfree.chart.renderer.category.CategoryItemRendererState; 026import org.jfree.chart.axis.CategoryAxis; 027import org.jfree.chart.axis.ValueAxis; 028import org.jfree.chart.labels.CategoryItemLabelGenerator; 029import org.jfree.chart.plot.CategoryPlot; 030import org.jfree.chart.plot.PlotOrientation; 031import org.jfree.data.category.CategoryDataset; 032import org.jfree.ui.GradientPaintTransformer; 033import org.jfree.ui.RectangleEdge; 034import org.jfree.data.DataUtilities; 035 036/** 037 * HybsStackedBarRenderer は、org.jfree.chart.renderer.category.StackedBarRenderer を 038 * 拡張したカスタマイズクラスです。 039 * これは、グラフの書き出し位置の調整比率(domainMargin)を設定できます。 040 * 041 * @og.rev 4.1.1.0 (2008/02/16) 新規作成 042 * 043 * @version 0.9.0 2001/05/05 044 * @author Kazuhiko Hasegawa 045 * @since JDK1.1, 046 */ 047public class HybsStackedBarRenderer extends StackedBarRenderer { 048 private static final long serialVersionUID = 519020100801L ; 049 050 private double domainMargin ; // 4.1.1.0 (2008/02/14) グラフの書き出し位置の調整比率 051 052 private final int hsCode = Long.valueOf( System.nanoTime() ).hashCode() ; // 5.1.9.0 (2010/08/01) equals,hashCode 053 054 /** 055 * デフォルトコンストラクター 056 * 057 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 058 */ 059 public HybsStackedBarRenderer() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 060 061 /** 062 * グラフの書き出し位置の調整比率を指定します。 063 * 064 * グラフを描画する場合の、書き出し位置を少しずらします。 065 * これは、グラフの幅に対して、比率で指定します。 066 * 0.0(初期値)の場合は、初期描画位置である、CategoryAnchor.Middle と 067 * 同じ箇所から、書き出されます。 068 * 1.0 の場合、中心から、グラフ幅の半分が加算され、END位置に寄ります。 069 * 同様に、-1.0 の場合は、グラフ幅の半分が減算され、START 位置になります。 070 * つまり、中心から、グラフ幅の半分単位で、前方/後方にずらす事が出来ます。 071 * 書き出し位置 = 中心(Middle) + (domainMargin)*幅/2 072 * 初期値は、0.0(真ん中:MIDDLE)です。 073 * (独自メソッド) 074 * 075 * @og.rev 4.1.1.0 (2008/02/14) 新規追加 076 * 077 * @param margin グラフの書き出し位置の調整比率 078 */ 079 public void setDomainMargin( final double margin ) { 080 domainMargin = margin; 081 } 082 083 /** 084 * StackedBarRenderer の drawItem メソッドのオーバーライドしています。 085 * 086 * Draws a stacked bar for a specific item. 087 * 088 * @param g2 the graphics device. 089 * @param state the renderer state. 090 * @param dataArea the plot area. 091 * @param plot the plot. 092 * @param domainAxis the domain (category) axis. 093 * @param rangeAxis the range (value) axis. 094 * @param dataset the data. 095 * @param row the row index (zero-based). 096 * @param column the column index (zero-based). 097 * @param pass the pass index. 098 */ 099 @Override 100 public void drawItem( final Graphics2D g2, 101 final CategoryItemRendererState state, 102 final Rectangle2D dataArea, 103 final CategoryPlot plot, 104 final CategoryAxis domainAxis, 105 final ValueAxis rangeAxis, 106 final CategoryDataset dataset, 107 final int row, 108 final int column, 109 final int pass) { 110 111 // nothing is drawn for null values... 112 final Number dataValue = dataset.getValue(row, column); 113 if( dataValue == null ) { 114 return; 115 } 116 117 double value = dataValue.doubleValue(); 118 double total = 0.0; // only needed if calculating percentages 119 if( getRenderAsPercentages() ) { 120 total = DataUtilities.calculateColumnTotal(dataset, column); 121 value = value / total; 122 } 123 124 final PlotOrientation orientation = plot.getOrientation(); 125 126 final double barW0 = domainAxis.getCategoryStart(column, getColumnCount(), 127 dataArea, plot.getDomainAxisEdge()) 128 + domainMargin * state.getBarWidth() / 2.0; 129 130 double positiveBase = getBase(); 131 double negativeBase = positiveBase; 132 133 // 4.3.1.1 (2008/08/23) 変数名が短いので変更(v ⇒ nm , d ⇒ vd ) 134 for( int i=0; i<row; i++ ) { 135 final Number nm = dataset.getValue(i, column); 136 if( nm != null ) { 137 double vd = nm.doubleValue(); 138 if( getRenderAsPercentages() ) { 139 vd = vd / total; 140 } 141 if( vd > 0 ) { 142 positiveBase = positiveBase + vd; 143 } 144 else { 145 negativeBase = negativeBase + vd; 146 } 147 } 148 } 149 150 double translatedBase; 151 double translatedValue; 152 final RectangleEdge location = plot.getRangeAxisEdge(); 153 if( value >= 0.0 ) { 154 translatedBase = rangeAxis.valueToJava2D(positiveBase, dataArea, 155 location); 156 translatedValue = rangeAxis.valueToJava2D(positiveBase + value, 157 dataArea, location); 158 } 159 else { 160 translatedBase = rangeAxis.valueToJava2D(negativeBase, dataArea, 161 location); 162 translatedValue = rangeAxis.valueToJava2D(negativeBase + value, 163 dataArea, location); 164 } 165 final double barL0 = Math.min(translatedBase, translatedValue); 166 final double barLength = Math.max(Math.abs(translatedValue - translatedBase), 167 getMinimumBarLength()); 168 169 Rectangle2D bar = null; 170 if( orientation == PlotOrientation.HORIZONTAL ) { 171 bar = new Rectangle2D.Double(barL0, barW0, barLength, 172 state.getBarWidth()); 173 } 174 else { 175 bar = new Rectangle2D.Double(barW0, barL0, state.getBarWidth(), 176 barLength); 177 } 178 if( pass == 0 ) { 179 Paint itemPaint = getItemPaint(row, column); 180 // 4.3.1.1 (2008/08/23) 変数名を t ⇒ gpt に変更 181 final GradientPaintTransformer gpt = getGradientPaintTransformer(); 182 if( gpt != null && itemPaint instanceof GradientPaint ) { 183 itemPaint = gpt.transform((GradientPaint) itemPaint, bar); 184 } 185 g2.setPaint(itemPaint); 186 g2.fill(bar); 187 if( isDrawBarOutline() 188 && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { 189 g2.setStroke(getItemOutlineStroke(row, column)); 190 g2.setPaint(getItemOutlinePaint(row, column)); 191 g2.draw(bar); 192 } 193 194 // add an item entity, if this information is being collected 195 final EntityCollection entities = state.getEntityCollection(); 196 if( entities != null) { 197 addItemEntity(entities, dataset, row, column, bar); 198 } 199 } 200 else if( pass == 1 ) { 201 final CategoryItemLabelGenerator generator = getItemLabelGenerator(row,column); 202 if( generator != null && isItemLabelVisible(row, column) ) { 203 drawItemLabel( g2, dataset, row, column, plot, generator, bar,value<0.0 ); // 6.9.7.0 (2018/05/14) PMD Useless parentheses. 204 } 205 } 206 } 207 208 /** 209 * この文字列と指定されたオブジェクトを比較します。 210 * 211 * 親クラスで、equals メソッドが実装されているため、警告がでます。 212 * 213 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 214 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 215 * 216 * @param object 比較するオブジェクト 217 * 218 * @return Objectが等しい場合は true、そうでない場合は false 219 */ 220 @Override 221 public boolean equals( final Object object ) { 222 // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method 223 return super.equals( object ) && hsCode == ((HybsStackedBarRenderer)object).hsCode; 224 } 225 226 /** 227 * このオブジェクトのハッシュコードを取得します。 228 * 229 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 230 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 231 * 232 * @return ハッシュコード 233 */ 234 @Override 235 public int hashCode() { return hsCode ; } 236}