/*
* This file is part of jHaushalt.
* jHaushalt is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* jHaushalt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with jHaushalt; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* (C)opyright 2002-2010 Dr. Lars H. Hahn
*/
package haushalt.auswertung.bloecke;
import haushalt.daten.Euro;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
/**
* @author Dr. Lars H. Hahn
* @version 2.5/2007.06.26
*/
/*
* 2007.06.26 Erweiterung: Anzeigen des Betrags der Durchschnittswerte
* 2006.02.03 BugFix: Farbwahl auch für Durchschnitt gültig
* 2006.02.02 Betrag immer oberhalb der X-Achse
*/
public class BalkenBlock extends AbstractGraphikBlock {
private Color farbePos = Color.blue;
private Color farbeNeg = Color.red;
private final Euro[] einnahmen;
private final Euro[] ausgaben;
private final String[] zeitraumNamen;
private final int anzahl;
private Euro schnittEinnahmen = null;
private Euro schnittAusgaben = null;
private Euro grWert = new Euro();
public BalkenBlock(final String[] zeitraumNamen, final Euro[] einnahmen, final Euro[] ausgaben,
final boolean durchschnitt) {
this.zeitraumNamen = zeitraumNamen;
this.einnahmen = einnahmen;
this.ausgaben = ausgaben;
this.anzahl = zeitraumNamen.length;
final Euro summeEinnahmen = new Euro();
final Euro summeAusgaben = new Euro();
for (int i = 0; i < this.anzahl; i++) {
if (this.grWert.compareTo(einnahmen[i]) < 0) {
this.grWert = einnahmen[i];
}
if (this.grWert.compareTo(ausgaben[i]) < 0) {
this.grWert = ausgaben[i];
}
summeEinnahmen.sum(einnahmen[i]);
summeAusgaben.sum(ausgaben[i]);
}
if (durchschnitt) {
this.schnittEinnahmen = summeEinnahmen.durch(this.anzahl);
this.schnittAusgaben = summeAusgaben.durch(this.anzahl);
}
}
@Override
protected int getHoehe(final int breite) {
// enspricht dem Standard-Bildschirmverhältnis 4:3
return (int) (breite * 0.75 + 0.5);
}
@Override
public int paint(final Graphics g, final int xStart, final int yStart, final int breite) {
final Graphics2D g2 = (Graphics2D) g;
g2.setFont(getFont()); // WICHTIG: Font setzen vor der Definition der
// FontMetrics
final FontMetrics fontMetrics = g2.getFontMetrics();
final int breiteYAchse = fontMetrics.stringWidth("" + this.grWert) + 5;
final int rand = getAbsRand(breite);
final int hoehe = getHoehe(breite);
final int textHoehe = fontMetrics.getHeight();
final int graphikBreite = breite - breiteYAchse - 2 * rand;
final int intervallBreite = graphikBreite / this.anzahl;
final int balkenBreite = intervallBreite * 6 / 15;
final int xEinnahmen = intervallBreite * 2 / 15;
final int xEinnahmenText = intervallBreite * 5 / 15 - textHoehe / 2;
final int xAusgaben = intervallBreite * 9 / 15;
final int xAusgabenText = intervallBreite * 12 / 15 - textHoehe / 2;
final int yBalken = hoehe - textHoehe + yStart;
final int maxBalkenHoehe = hoehe - 2 * textHoehe;
// 9 graue horizontale Linien zeichnen:
int y;
int x = xStart + rand + breiteYAchse;
for (int i = 0; i <= 8; i++) {
final double faktor = i / 8.0D;
final Euro euro = new Euro(this.grWert.toDouble() * faktor);
y = yBalken - (int) (maxBalkenHoehe * faktor);
g2.setPaint(Color.gray);
g2.drawLine(x, y, x + graphikBreite, y);
g2.setPaint(Color.black);
g2.drawString("" + euro, x - fontMetrics.stringWidth("" + euro) - 3, y);
}
// Durchschnittliche Einnahmen und Ausgaben als Linien einzeichnen:
if (this.schnittAusgaben != null) {
y = yBalken - (int) (maxBalkenHoehe * this.schnittEinnahmen.toDouble() / this.grWert.toDouble());
g2.setPaint(this.farbePos);
g2.drawRect(x, y, graphikBreite, 1);
g2.drawString("" + this.schnittEinnahmen, x - fontMetrics.stringWidth("" + this.schnittEinnahmen) - 3, y);
y = yBalken - (int) (maxBalkenHoehe * this.schnittAusgaben.toDouble() / this.grWert.toDouble());
g2.setPaint(this.farbeNeg);
g2.drawRect(x, y, graphikBreite, 1);
g2.drawString("" + this.schnittAusgaben, x - fontMetrics.stringWidth("" + this.schnittAusgaben) - 3, y);
}
final GradientPaint verlaufPos = new GradientPaint(0, yBalken, this.farbePos, 0, yStart, Color.lightGray);
final GradientPaint verlaufNeg = new GradientPaint(0, yBalken, this.farbeNeg, 0, yStart, Color.lightGray);
for (int i = 0; i < this.anzahl; i++) {
final int hoeheEinnahmen = (int) (maxBalkenHoehe * this.einnahmen[i].toDouble() / this.grWert.toDouble());
g2.setPaint(verlaufPos);
g2.fill(new Rectangle2D.Double(x + xEinnahmen, yBalken - hoeheEinnahmen, balkenBreite, hoeheEinnahmen));
final int hoeheAusgaben = (int) (maxBalkenHoehe * this.ausgaben[i].toDouble() / this.grWert.toDouble());
g2.setPaint(verlaufNeg);
g2.fill(new Rectangle2D.Double(x + xAusgaben, yBalken - hoeheAusgaben, balkenBreite, hoeheAusgaben));
g2.setPaint(Color.black);
g2.drawString(this.zeitraumNamen[i], x + xEinnahmen, hoehe + yStart - 5);
final AffineTransform oldAt = g2.getTransform();
if (hoeheEinnahmen > fontMetrics.stringWidth("" + this.einnahmen[i])) {
// Prima! Der Balken ist hoch genug für den Text
g2.translate(x + xEinnahmenText, yBalken - hoeheEinnahmen + 5);
}
else {
// Pech! Der Text ragt über den Balken hinaus, ist aber sichtbar
g2.translate(x + xEinnahmenText, yBalken - fontMetrics.stringWidth("" + this.einnahmen[i]) - 5);
}
g2.rotate(Math.toRadians(90));
g2.drawString("" + this.einnahmen[i], 0, 0);
g2.setTransform(oldAt);
if (hoeheAusgaben > fontMetrics.stringWidth("" + this.ausgaben[i])) {
// Prima! Der Balken ist hoch genug für den Text
g2.translate(x + xAusgabenText, yBalken - hoeheAusgaben + 5);
}
else {
// Pech! Der Text ragt über den Balken hinaus, ist aber sichtbar
g2.translate(x + xAusgabenText, yBalken - fontMetrics.stringWidth("" + this.ausgaben[i]) - 5);
}
g2.rotate(Math.toRadians(90));
g2.drawString("" + this.ausgaben[i], 0, 0);
g2.setTransform(oldAt);
x += intervallBreite;
}
return hoehe;
}
public void setFarbeEinnahmen(final Color farbe) {
this.farbePos = farbe;
}
public void setFarbeAusgaben(final Color farbe) {
this.farbeNeg = farbe;
}
}