📄 chartitem.java
字号:
//#condition polish.usePolishGui
/*
* Created on Nov 28, 2006 at 1:34:21 PM.
*
* Copyright (c) 2006 Robert Virkus / Enough Software
*
* This file is part of J2ME Polish.
*
* J2ME Polish 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.
*
* J2ME Polish 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 J2ME Polish; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Commercial licenses are also available, please
* refer to the accompanying LICENSE.txt or visit
* http://www.j2mepolish.org for details.
*/
package de.enough.polish.ui;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import de.enough.polish.util.RgbImage;
/**
* <p>The ChartItem renders numerical integer based data in a diagram.</p>
*
* <p>Copyright Enough Software 2006</p>
* <pre>
* history
* Nov 28, 2006 - rob creation
* </pre>
* @author Robert Virkus, j2mepolish@enough.de
*/
public class ChartItem
//#if polish.LibraryBuild
//# extends FakeCustomItem
//#else
extends Item
//#endif
{
private int[][] dataSequences; // actual numerical data that should be visualized
private String[] labelsData; // labels for the each numerical data
private int dataMaximum; // maximum value in the data sequence
private int dataMinimum; // minimum value in the data sequence
private String labelY; // vertical label
private String labelX; // horizontal label
private int baseLine; // the reference point from which the data should be shown. This can be a handy trick for making growth
// seem more spectacular, for example - just show the difference between a former year and today instead of
// showing the absolute growth, for example.
private int divider; // this can be used to simulate floating point numbers with integer numbers,
// a devider of 100 can make eurocents to euros, for example (or cents to dollars)
private int[] colors; // the colors of each data sequence
private int axisColor; // the color of the x and y axis
private int scaleFactorX; // the factor in percent for scaling the diagram horizontally, is usually calculated dynamically using the available width
private int scaleFactorY; // the factor in percent for scaling the diagram vertically, is usually calculated dynamically using the max-height of the item
private Font font;
private int fontColor;
//#if polish.midp2 && polish.hasFloatingPoint
//#define tmp.rotate
//# private RgbImage rotatedLabelY;
//#endif
/**
* Creates a new ChartItem.
*
* @param label the label
* @param dataSequences the actual data that should be visualized
* @param colors the colors of each data sequence, can be overridden by the designer for most ChartItemViews
*/
public ChartItem(String label, int[][] dataSequences, int[] colors ) {
this( label, dataSequences, colors, null, null, null, 0, 0, null );
}
/**
* Creates a new ChartItem.
*
* @param label the label
* @param dataSequences the actual data that should be visualized
* @param colors the colors of each data sequence, can be overridden by the designer for most ChartItemViews
* @param style the J2ME Polish style of this item
*/
public ChartItem(String label, int[][] dataSequences, int[] colors, Style style ) {
this( label, dataSequences, colors, null, null, null, 0, 0, style );
}
/**
* Creates a new ChartItem.
*
* @param label the label
* @param dataSequences the actual data that should be visualized
* @param colors the colors of each data sequence, can be overridden by the designer for most ChartItemViews
* @param labelsData optional labels for the legend of this item
* @param labelY the optional label for the vertical axis (e.g. revenue)
* @param labelX the optional label for the horizontal axis (e.g. years)
* @param baseLine the reference point from which the data should be shown. This can be a handy trick for making growth
* seem more spectacular, for example - just show the difference between a former year and today instead of
* showing the absolute growth, for example. Set to 0 for playing it clean.
* @param divider can be used to simulate floating point numbers with integer numbers, a devider of 100 can make eurocents to euros, for example (or cents to dollars).
* A divider of 1.000.000 could show revenue in million pounds, for example.
*/
public ChartItem(String label, int[][] dataSequences, int[] colors, String[] labelsData, String labelY, String labelX, int baseLine, int divider ) {
this( label, dataSequences, colors, labelsData, labelY, labelX, baseLine, divider, null );
}
/**
* Creates a new ChartItem.
*
* @param label the label
* @param dataSequences the actual data that should be visualized
* @param colors the colors of each data sequence, can be overridden by the designer for most ChartItemViews
* @param labelsData optional labels for the legend of this item
* @param labelY the optional label for the vertical axis (e.g. revenue)
* @param labelX the optional label for the horizontal axis (e.g. years)
* @param baseLine the reference point from which the data should be shown. This can be a handy trick for making growth
* seem more spectacular, for example - just show the difference between a former year and today instead of
* showing the absolute growth, for example. Set to 0 for playing it clean.
* @param divider can be used to simulate floating point numbers with integer numbers, a devider of 100 can make eurocents to euros, for example (or cents to dollars).
* A divider of 1.000.000 could show revenue in million pounds, for example.
* @param style the J2ME Polish style of this item
*/
public ChartItem(String label, int[][] dataSequences, int[] colors, String[] labelsData, String labelY, String labelX, int baseLine, int divider, Style style ) {
super( label, LAYOUT_DEFAULT, PLAIN, style );
this.dataSequences = dataSequences;
this.labelsData = labelsData;
this.labelY = labelY;
this.labelX = labelX;
this.baseLine = baseLine;
this.divider = divider;
this.colors = colors;
if (dataSequences != null) {
setDataSequences( dataSequences );
}
}
//#ifdef polish.useDynamicStyles
//# /* (non-Javadoc)
//# * @see de.enough.polish.ui.FakeCustomItem#createCssSelector()
//# */
//# protected String createCssSelector() {
//# return "chart";
//# }
//#endif
/* (non-Javadoc)
* @see de.enough.polish.ui.FakeCustomItem#initContent(int, int)
*/
protected void initContent(int firstLineWidth, int lineWidth) {
if ( this.dataSequences == null || this.dataSequences.length == 0 || this.dataSequences[0].length == 0 ) {
this.contentHeight = 0;
this.contentWidth = 0;
return;
}
if (this.font == null && (this.labelX != null || this.labelY != null)) {
this.font = Font.getDefaultFont();
}
// horizontal / x axis initialization:
int labelWidth = 0;
if (this.labelX != null) {
labelWidth = this.font.getHeight() + this.paddingVertical;
lineWidth -= labelWidth;
}
int length = this.dataSequences[0].length - 1;
boolean isHorizontalShrink = (this.layout & LAYOUT_SHRINK) == LAYOUT_SHRINK;
//#ifdef polish.css.max-width
if (this.maximumWidth != 0 && this.maximumWidth < lineWidth ) {
lineWidth = this.maximumWidth;
}
//#endif
if (isHorizontalShrink && length <= lineWidth) {
this.contentWidth = lineWidth + labelWidth;
this.scaleFactorX = 100;
} else {
this.scaleFactorX = (lineWidth * 100) / length;
this.contentWidth = (this.scaleFactorX * length) / 100 + labelWidth;
}
// vertical / y axis initialization:
int maxHeight = 0;
//#ifdef polish.css.max-height
//# maxHeight = this.maximumHeight;
//#endif
if (maxHeight == 0) {
Screen scr = getScreen();
if (scr == null) {
maxHeight = 100;
} else {
maxHeight = scr.contentHeight - 2;
}
}
int dataRange;
if (this.dataMaximum > 0 ) {
if (this.dataMinimum > 0) {
// there are only positive values:
dataRange = this.dataMaximum - this.baseLine;
} else {
// there are positive and negative values:
dataRange = Math.abs( this.dataMaximum - this.dataMinimum );
}
} else {
// there are only negative values:
dataRange = Math.abs( this.baseLine - this.dataMinimum );
}
boolean isVerticalExpand = (this.layout & LAYOUT_VEXPAND) == LAYOUT_VEXPAND;
int labelHeight = 0;
if (this.labelX != null) {
labelHeight = this.font.getHeight() + this.paddingVertical;
maxHeight -= labelHeight;
}
if (!isVerticalExpand && dataRange <= maxHeight) {
this.scaleFactorY = 100;
this.contentHeight = dataRange + labelHeight;
} else {
this.scaleFactorY = (maxHeight * 100) / dataRange;
this.contentHeight = maxHeight + labelHeight;
}
//#if tmp.rotate
//# if (this.labelY != null && this.rotatedLabelY == null) {
//# // rotate label by 90 degrees:
//# int[] original = TextEffect.getRgbData(this.labelY, this.fontColor, this.font);
//# int height = this.font.getHeight();
//# int width = original.length / height;
//# int[] rotated = new int[ original.length ];
//# for (int col = 0; col < height; col++) {
//# for (int row = 0; row < width; row++ ) {
//# rotated[ row*height + (height - (col + 1))] =
//# original[ col*width + row];
//# }
//# }
//# this.rotatedLabelY = new RgbImage( rotated, height, true); // RotateTextEffect.rotate(this.labelY, this.fontColor, this.font, 270 );
//# }
//#endif
}
/**
* Paints the labels and the axis of this chart.
*
* @param x the left start position
* @param y the upper start position
* @param leftBorder the left border, nothing must be painted left of this position
* @param rightBorder the right border, nothing must be painted right of this position
* @param inout_params an array with 2 elements for adjusting x and y:
* <pre>
* int[] inout_params = new int[]{ x, y };
* int baseLineY = chart.paintGrid(x, y, leftBorder, rightBorder, inout_params, g);
* x = inout_params[0];
* y = inout_params[1];
* </pre>
* @param g the Graphics on which this item should be painted.
* @return the y position of the baseline
*/
public int paintGrid(int x, int y, int leftBorder, int rightBorder, int[] inout_params, Graphics g) {
int dataLength = this.dataSequences[0].length - 1;
int xAxisWidth = (dataLength*this.scaleFactorX)/100;
int yAxisHeight = (Math.abs( this.dataMaximum - this.dataMinimum ) * this.scaleFactorY) /100;
// draw axis labels:
g.setColor( this.fontColor );
g.setFont( this.font );
if (this.labelX != null) {
if (this.dataMaximum < 0) {
//#if tmp.rotate
//# g.drawString( this.labelX, x + xAxisWidth/2, y, Graphics.HCENTER | Graphics.TOP );
//#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -