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 = 0.0; // 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 * グラフを描画する場合の、書き出し位置を少しずらします。 058 * これは、グラフの幅に対して、比率で指定します。 059 * 0.0(初期値)の場合は、初期描画位置である、CategoryAnchor.Middle と 060 * 同じ箇所から、書き出されます。 061 * 1.0 の場合、中心から、グラフ幅の半分が加算され、END位置に寄ります。 062 * 同様に、-1.0 の場合は、グラフ幅の半分が減算され、START 位置になります。 063 * つまり、中心から、グラフ幅の半分単位で、前方/後方にずらす事が出来ます。 064 * 書き出し位置 = 中心(Middle) + (domainMargin)*幅/2 065 * 初期値は、0.0(真ん中:MIDDLE)です。 066 * 067 * @og.rev 4.1.1.0 (2008/02/14) 新規追加 068 * 069 * @param margin グラフの書き出し位置の調整比率 070 */ 071 public void setDomainMargin( final double margin ) { 072 domainMargin = margin; 073 } 074 075 /** 076 * Draws a stacked bar for a specific item. 077 * 078 * @param g2 the graphics device. 079 * @param state the renderer state. 080 * @param dataArea the plot area. 081 * @param plot the plot. 082 * @param domainAxis the domain (category) axis. 083 * @param rangeAxis the range (value) axis. 084 * @param dataset the data. 085 * @param row the row index (zero-based). 086 * @param column the column index (zero-based). 087 * @param pass the pass index. 088 */ 089 @Override 090 public void drawItem( final Graphics2D g2, 091 final CategoryItemRendererState state, 092 final Rectangle2D dataArea, 093 final CategoryPlot plot, 094 final CategoryAxis domainAxis, 095 final ValueAxis rangeAxis, 096 final CategoryDataset dataset, 097 final int row, 098 final int column, 099 final int pass) { 100 101 // nothing is drawn for null values... 102 Number dataValue = dataset.getValue(row, column); 103 if (dataValue == null) { 104 return; 105 } 106 107 double value = dataValue.doubleValue(); 108 double total = 0.0; // only needed if calculating percentages 109 if (getRenderAsPercentages()) { 110 total = DataUtilities.calculateColumnTotal(dataset, column); 111 value = value / total; 112 } 113 114 PlotOrientation orientation = plot.getOrientation(); 115 116 double barW0 = domainAxis.getCategoryStart(column, getColumnCount(), 117 dataArea, plot.getDomainAxisEdge()) 118 + domainMargin * state.getBarWidth() / 2.0; 119 120 double positiveBase = getBase(); 121 double negativeBase = positiveBase; 122 123 // 4.3.1.1 (2008/08/23) 変数名が短いので変更(v ⇒ nm , d ⇒ vd ) 124 for (int i = 0; i < row; i++) { 125 Number nm = dataset.getValue(i, column); 126 if (nm != null) { 127 double vd = nm.doubleValue(); 128 if (getRenderAsPercentages()) { 129 vd = vd / total; 130 } 131 if (vd > 0) { 132 positiveBase = positiveBase + vd; 133 } 134 else { 135 negativeBase = negativeBase + vd; 136 } 137 } 138 } 139 140 double translatedBase; 141 double translatedValue; 142 RectangleEdge location = plot.getRangeAxisEdge(); 143 if (value >= 0.0) { 144 translatedBase = rangeAxis.valueToJava2D(positiveBase, dataArea, 145 location); 146 translatedValue = rangeAxis.valueToJava2D(positiveBase + value, 147 dataArea, location); 148 } 149 else { 150 translatedBase = rangeAxis.valueToJava2D(negativeBase, dataArea, 151 location); 152 translatedValue = rangeAxis.valueToJava2D(negativeBase + value, 153 dataArea, location); 154 } 155 double barL0 = Math.min(translatedBase, translatedValue); 156 double barLength = Math.max(Math.abs(translatedValue - translatedBase), 157 getMinimumBarLength()); 158 159 Rectangle2D bar = null; 160 if (orientation == PlotOrientation.HORIZONTAL) { 161 bar = new Rectangle2D.Double(barL0, barW0, barLength, 162 state.getBarWidth()); 163 } 164 else { 165 bar = new Rectangle2D.Double(barW0, barL0, state.getBarWidth(), 166 barLength); 167 } 168 if (pass == 0) { 169 Paint itemPaint = getItemPaint(row, column); 170 // 4.3.1.1 (2008/08/23) 変数名を t ⇒ gpt に変更 171 GradientPaintTransformer gpt = getGradientPaintTransformer(); 172 if (gpt != null && itemPaint instanceof GradientPaint) { 173 itemPaint = gpt.transform((GradientPaint) itemPaint, bar); 174 } 175 g2.setPaint(itemPaint); 176 g2.fill(bar); 177 if (isDrawBarOutline() 178 && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { 179 g2.setStroke(getItemOutlineStroke(row, column)); 180 g2.setPaint(getItemOutlinePaint(row, column)); 181 g2.draw(bar); 182 } 183 184 // add an item entity, if this information is being collected 185 EntityCollection entities = state.getEntityCollection(); 186 if (entities != null) { 187 addItemEntity(entities, dataset, row, column, bar); 188 } 189 } 190 else if (pass == 1) { 191 CategoryItemLabelGenerator generator = getItemLabelGenerator(row,column); 192 if (generator != null && isItemLabelVisible(row, column)) { 193 drawItemLabel(g2, dataset, row, column, plot, generator, bar,(value < 0.0)); 194 } 195 } 196 } 197 198 /** 199 * この文字列と指定されたオブジェクトを比較します。 200 * 201 * 親クラスで、equals メソッドが実装されているため、警告がでます。 202 * 203 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 204 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 205 * 206 * @param object 比較するオブジェクト 207 * 208 * @return Objectが等しい場合は true、そうでない場合は false 209 */ 210 @Override 211 public boolean equals( final Object object ) { 212 if( super.equals( object ) ) { 213 return hsCode == ((HybsStackedBarRenderer)object).hsCode; 214 } 215 return false; 216 } 217 218 /** 219 * このオブジェクトのハッシュコードを取得します。 220 * 221 * @og.rev 5.1.8.0 (2010/07/01) findbug対応 222 * @og.rev 5.1.9.0 (2010/08/01) findbug対応 223 * 224 * @return ハッシュコード 225 */ 226 @Override 227 public int hashCode() { return hsCode ; } 228}