com.day.cq.graphics.chart.Axis Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
The newest version!
/*
* Copyright 1997-2004 Day Management AG
* Barfuesserplatz 6, 4001 Basel, Switzerland
* All Rights Reserved.
*
* This software is the confidential and proprietary information of
* Day Management AG, ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Day.
*/
package com.day.cq.graphics.chart;
import java.awt.Color;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.day.cq.graphics.Graph;
import com.day.image.Font;
import com.day.image.Layer;
import com.day.image.LineStyle;
/**
* @author tripod
*/
public final class Axis {
public static final int TYPE_NORMAL = 0;
public static final int TYPE_INVERT = 1;
public static final int TYPE_LOG = 2;
public static final int TYPE_LOGINV = 3;
public static final int TYPE_CATEG = 4;
public static final int TYPE_CATEGINV = 5;
public static final int NO_AXIS = '0';
public static final int X_AXIS = 'x';
public static final int Y_AXIS = 'y';
public static final int U_AXIS = 'u';
public static final int V_AXIS = 'v';
public static final int LABEL_ABOVE = 0x00; /* for label type */
public static final int LABEL_BELOW = 0x01;
public static final int LABEL_RIGHT = 0x00;
public static final int LABEL_LEFT = 0x10;
public static final int LABEL_CENTER = 0x20;
public static final int LABEL_TYPE_NUMBER = 0; /* uses labelformat with sprintf */
public static final int LABEL_TYPE_DATE = 1; /* uses labelformat with strftime */
public static final int TITLE_POS_NONE = 0;
public static final int TITLE_POS_ABOVE = 1;
public static final int TITLE_POS_BELOW = 2;
public static final int TITLE_POS_BOTH = 3;
int width;
int height;
LineStyle style;
// main ticks
int tickfrom;
int tickto;
int tickdistance; // pixels
int numticks;
LineStyle tickstyle;
// sub ticks
int subtickfrom;
int subtickto;
// Color subtickColor;
int subtickspertick;
LineStyle subtickstyle;
// labeling
Font labelfont;
Color labelcolor;
int labeldx;
int labeldy;
int labelalign;
int labelcs;
int labelwidth;
private String labelformat; // format string for sprintf
private String sublabelformat; // format string for sprintf
int labeltype;
// range
private double rangemin;
private double rangemax;
private double rangestep;
private double rangescale;
private double rangeoffset;
private boolean rangeminset;
private boolean rangemaxset;
private boolean rangestepset;
private boolean rangescaleset;
private boolean rangeoffsetset;
int rangetype; // see above ??
// title
int titlepos;
double inflate = 1;
// internal hack :-)
int[] tickpos = new int[256];
double[] ticksample = new double[256];
// the axisdrawer 'method'
private AxisDrawer axisDrawer;
private int axisType;
private Axis(Graph graph, int axisType) {
setType(axisType);
}
public static Axis getInstance(Graph graph, int type)
throws IllegalArgumentException {
return new Axis(graph, type);
}
public static Axis getInstance(Graph graph) {
return new Axis(graph, NO_AXIS);
}
public Layer draw(Graph graph, boolean doDraw) {
return (axisDrawer != null) ? axisDrawer.draw(graph, doDraw) : null;
}
private static interface AxisDrawer {
public Layer draw(Graph graph, boolean doDraw);
}
private final class XAxis implements AxisDrawer {
public Layer draw(Graph graph, boolean doDraw) {
int x, w, h, tw, stw, spt, tc, ypos, flags, num;
double pos, scale;
tw = tickto - tickfrom;
stw = subtickto - subtickfrom;
spt = subtickspertick;
w = width;
h = height;
Layer l = graph.createLayer(doDraw, w, h);
// no axis crossing so far ??
// X axis
scale = getRangescale();
ypos = (subtickto > tickto) ? subtickto : tickto;
// ignore rangetype so far
if (doDraw) {
l.setLineStyle(style);
l.drawLine(0, ypos, w - 1, ypos);
}
tc = spt;
pos = getRangemin();
num = 0;
while (num <= numticks) {
// tick ?
x = (int) ((pos + getRangeoffset()) * scale);
if (tc == spt) {
if (tw != 0 && doDraw) {
l.setLineStyle(tickstyle);
l.drawLine(x, ypos - tickfrom, x, ypos - tickto);
}
tickpos[num] = x;
// draw text
if (labelfont != null && doDraw) {
int rl = x + labeldx;
int rt = ypos - tickfrom - labeldy;
String tmp = String.format(labelformat, new Double(pos));
flags = Font.TTANTIALIASED;
if (labelalign == LABEL_CENTER) {
flags |= Font.ALIGN_CENTER;
rl -= labelwidth / 2;
}
labelfont.drawText(l, rl, rt, labelwidth, 0, tmp,
labelcolor, null, flags, labelcs, 0);
}
tc = 0;
num++;
} else {
// subtick
if (stw != 0 && doDraw) {
l.setLineStyle(subtickstyle);
l.drawLine(x, ypos - subtickfrom, x, ypos - subtickto);
}
tc++;
}
pos += getRangestep() / (spt + 1);
}
if (doDraw) {
l.setX(1);
l.setY(-ypos - 1); // ??
}
return l;
}
}
private final class YAxis implements AxisDrawer {
public Layer draw(Graph graph, boolean doDraw) {
int y, w, h, tw, stw, spt, tc, xpos, flags, num;
double pos, scale;
tw = tickto - tickfrom;
stw = subtickto - subtickfrom;
spt = subtickspertick;
w = width;
h = height;
Layer l = graph.createLayer(doDraw, w, h);
// Graphics2D ig = null;
// no axis crossing so far ??
scale = getRangescale();
xpos = w - 1 - (subtickto > tickto ? subtickto : tickto);
// ignore rangetype so far - missing style
if (doDraw) {
l.setLineStyle(style);
l.drawLine(xpos, 0, xpos, h - 1);
}
tc = spt;
pos = getRangemin();
num = 0;
while (num <= numticks) { // first one counts, too
// tick ??
y = h - 1 - (int) ((pos + getRangeoffset()) * scale);
if (tc == spt) {
//tick
tickpos[num] = y;
ticksample[num] = pos;
// draw text
if (labelfont != null && doDraw) {
int lw, ly, lh;
if (labelalign == LABEL_ABOVE) {
flags = Font.ALIGN_BOTTOM | Font.ALIGN_RIGHT | Font.TTANTIALIASED;
ly = y + labeldy;
lh = 0; // dont care
} else if (labelalign == LABEL_CENTER) {
flags = Font.ALIGN_BASE | Font.ALIGN_RIGHT | Font.TTANTIALIASED;
ly = y + labeldy;
lh = 0;
} else { // below
flags = Font.ALIGN_TOP | Font.ALIGN_RIGHT | Font.TTANTIALIASED;
ly = y + labeldy;
lh = 0; // dont care
}
//lw = xpos + labeldx;
//hack to align Y label on the right
lw = -labeldx;
String str = String.format(labelformat, new Double(pos));
labelfont.drawText(l, 0, ly, lw, lh, str,
labelcolor, null, flags, labelcs, 0);
}
if (tw != 0 && doDraw) {
l.setLineStyle(tickstyle);
l.drawLine(xpos + tickfrom, y, xpos + tickto, y);
}
tc = 0;
num++;
} else {
// subtick
if (stw != 0 && doDraw) {
l.setLineStyle(subtickstyle);
l.drawLine(xpos + subtickfrom, y, xpos + subtickto, y);
}
tc++;
}
pos += getRangestep() / (spt + 1);
}
if (doDraw) {
l.setX(-xpos);
l.setY(-h);
}
return l;
}
}
private final class VAxis implements AxisDrawer {
public Layer draw(Graph graph, boolean doDraw) {
int y, w, h, tw, stw, spt, tc, xpos, flags;
double pos, scale;
String str;
tw = tickto - tickfrom;
stw = subtickto - subtickfrom;
spt = subtickspertick;
w = width;
h = height;
Layer l = graph.createLayer(doDraw, w, h);
// Graphics2D ig = null;
// no axis crossing so far ??
int labelnum = 0;
if (doDraw) {
if (getRangescale() == 0) {
setRangescale(scale = h / (1 + getRangemax() - getRangemin()));
} else {
scale = getRangescale();
}
xpos = w - 1 - (subtickto > tickto ? subtickto : tickto);
// ignore rangetype so far
if (doDraw) {
int y1 = 0, y2 = h - 1;
if ((graph.getYAxis().titlepos & TITLE_POS_ABOVE) == TITLE_POS_ABOVE)
y1 += (int) scale;
if ((graph.getYAxis().titlepos & TITLE_POS_BELOW) == TITLE_POS_BELOW)
y2 -= (int) scale;
l.setLineStyle(style);
l.drawLine(xpos, y1, xpos, y2);
}
// draw axis
tc = spt;
labelnum = (int) (pos = getRangemin());
while (labelnum <= getRangemax()) {
y = (int) ((pos + getRangeoffset()) * scale);
if (tc == spt) {
// tick
if (labelnum >= 0) tickpos[labelnum] = y;
// draw text
if (labelfont != null) {
// default align is above/right
int vflags = Font.ALIGN_BOTTOM;
int hflags = Font.ALIGN_RIGHT;
int ll = 0, lr = xpos + labeldx, lt = 0, lb = y + labeldy;
if ((labelalign & LABEL_BELOW) != 0) {
vflags = Font.ALIGN_TOP;
lt = y + labeldy;
lb = 0;
} else if ((labelalign & LABEL_CENTER) != 0) {
vflags = Font.ALIGN_BASE;
lt = y + labeldy;
lb = 0;
}
if ((labelalign & LABEL_LEFT) != 0) {
hflags = Font.ALIGN_LEFT;
ll = xpos + labeldx;
lr = ll;
}
flags = vflags | hflags | Font.TTANTIALIASED;
if ((labelnum == getRangemin() && (graph.getYAxis().titlepos & TITLE_POS_ABOVE) != 0)
|| (labelnum == getRangemax() && (graph.getYAxis().titlepos & TITLE_POS_BELOW) != 0)) {
str = graph.getData().labels[0] != null ? graph.getData().labels[0] : "none";
} else {
str = String.format(labelformat, graph.getData().datarows[labelnum].label);
}
str = str.trim();
if (doDraw) {
labelfont.drawText(l, ll, lt, lr - ll, lt - lb, str,
labelcolor, null, flags, labelcs, 0);
}
}
if (tw != 0 && doDraw && (!(labelnum == getRangemin() && (graph.getYAxis().titlepos & TITLE_POS_ABOVE) != 0))) {
l.setLineStyle(tickstyle);
l.drawLine(xpos + tickfrom, y, xpos + tickto, y);
}
labelnum++;
tc = 0;
} else {
// subtick
if (stw != 0 && doDraw) {
l.setLineStyle(subtickstyle);
l.drawLine(xpos + subtickfrom, y, xpos + subtickto, y);
tc++;
}
}
pos += getRangestep() / (spt + 1);
}
if (doDraw) {
l.setX(-xpos);
l.setY(-h);
if ((graph.getYAxis().titlepos & TITLE_POS_BELOW) != 0) {
l.setY(l.getY() + (int) scale - 1);
}
}
}
return l;
}
}
private class UAxis implements AxisDrawer {
public Layer draw(Graph graph, boolean doDraw) {
int x, w, h, tw, stw, spt, tc, ypos, flags;
double pos, scale;
tw = tickto - tickfrom;
stw = subtickto - subtickfrom;
spt = subtickspertick;
w = width;
h = height;
int lastx = 0;
Layer l = graph.createLayer(doDraw, w, h);
// Graphics2D ig = null;
// no axis crossing so far ??
int labelnum = 0;
if (getRangescale() == 0) {
setRangescale(scale = w / (1.0 + getRangemax() - getRangemin()));
} else {
scale = getRangescale();
}
ypos = stw > tw ? stw / 2 : tw / 2;
// ignore rangetype so far
if (doDraw) {
l.setLineStyle(style);
l.drawLine(0, ypos, w - 1, ypos);
}
// draw axis
tc = spt;
labelnum = (int) (pos = getRangemin());
while (labelnum <= getRangemax()) {
// tick ??
x = (int) ((pos + getRangeoffset()) * scale);
if (tc == spt) {
if (tw != 0 && doDraw) {
l.setLineStyle(tickstyle);
l.drawLine(x, ypos - tickfrom, x, ypos - tickto);
}
// draw text
if (labelfont != null && x + labeldx >= lastx) {
int rl = x + labeldx;
int rt = ypos - tickfrom - labeldy;
String tmp = formatlabel(graph.getXAxis().labeltype,
graph.getXAxis().labelformat,
graph.getData().labels[labelnum]);
flags = Font.TTANTIALIASED;
if (labelalign == LABEL_CENTER) {
flags |= Font.ALIGN_CENTER;
rl -= labelwidth / 2;
}
if (doDraw) {
labelfont.drawText(l, rl, rt, labelwidth, 0, tmp,
labelcolor, null, flags, labelcs, 0);
lastx = rl + labelwidth;
}
}
labelnum += (int) getRangestep();
tc = 0;
} else {
// subtick
if (stw != 0 && doDraw) {
l.setLineStyle(subtickstyle);
l.drawLine(x, ypos - subtickfrom, x, ypos - subtickto);
}
tc++;
}
pos += getRangestep() / (spt + 1);
}
if (doDraw) {
l.setX(0);
l.setY(-ypos - 1); // ??
}
return l;
}
}
//---------- internal ------------------------------------------------------
/* package use */
static String formatlabel(int type, String format, String label) {
if (label == null) label = "";
if (type == LABEL_TYPE_NUMBER) {
return String.format(format, label);
} else if (type == LABEL_TYPE_DATE) {
try {
SimpleDateFormat fmt = new SimpleDateFormat();
Date date = fmt.parse(label);
return String.format(format, date);
} catch (ParseException pe) {
// log
return "";
}
} else {
// log
return "";
}
}
//---------- getter and setter for data ------------------------------------
public double getRangemin() {
return rangemin;
}
public void setRangemin(double rangemin) {
if (!rangeminset && rangemin != 0) {
this.rangemin = rangemin;
this.rangeminset = true;
}
}
public double getRangemax() {
return rangemax;
}
public void setRangemax(double rangemax) {
if (!rangemaxset && rangemax != 0) {
this.rangemax = rangemax;
this.rangemaxset = true;
}
}
public double getRangestep() {
return rangestep;
}
public void setRangestep(double rangestep) {
if (!rangestepset && rangestep != 0) {
this.rangestep = rangestep;
this.rangestepset = true;
}
}
public double getRangescale() {
return rangescale;
}
public void setRangescale(double rangescale) {
if (!rangescaleset && rangescale != 0) {
this.rangescale = rangescale;
this.rangescaleset = true;
}
}
public double getRangeoffset() {
return rangeoffset;
}
public void setRangeoffset(double rangeoffset) {
if (!rangeoffsetset && rangeoffset != 0) {
this.rangeoffset = rangeoffset;
this.rangeoffsetset = true;
}
}
public String getLabelformat() {
return labelformat;
}
public void setLabelformat(String labelformat) {
if (labelformat != null && labelformat.length() != 0) {
this.labelformat = labelformat;
}
}
public String getSublabelformat() {
return sublabelformat;
}
public void setSublabelformat(String sublabelformat) {
if (sublabelformat != null && sublabelformat.length() != 0) {
this.sublabelformat = sublabelformat;
}
}
public void setType(int type) throws IllegalArgumentException {
if (type == X_AXIS) {
this.axisDrawer = new XAxis();
} else if (type == Y_AXIS) {
this.axisDrawer = new YAxis();
} else if (type == U_AXIS) {
this.axisDrawer = new UAxis();
} else if (type == V_AXIS) {
this.axisDrawer = new VAxis();
} else if (type == NO_AXIS) {
this.axisDrawer = null;
} else {
// log
throw new IllegalArgumentException("Unknown type " + (char) type);
}
this.axisType = type;
}
public int getType() {
return axisType;
}
//--------------------------------------------------------------------------
public void setStyle(LineStyle style) {
this.style = style;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setTickfrom(int tickfrom) {
this.tickfrom = tickfrom;
}
public void setTickto(int tickto) {
this.tickto = tickto;
}
public void setTickdistance(int tickdistance) {
this.tickdistance = tickdistance;
}
public void setNumticks(int numticks) {
this.numticks = numticks;
}
public void setTickstyle(LineStyle tickstyle) {
this.tickstyle = tickstyle;
}
public void setSubtickfrom(int subtickfrom) {
this.subtickfrom = subtickfrom;
}
public void setSubtickto(int subtickto) {
this.subtickto = subtickto;
}
public void setSubtickspertick(int subtickspertick) {
this.subtickspertick = subtickspertick;
}
public void setSubtickstyle(LineStyle subtickstyle) {
this.subtickstyle = subtickstyle;
}
public void setLabelfont(Font labelfont) {
this.labelfont = labelfont;
}
public void setLabelcolor(Color labelcolor) {
this.labelcolor = labelcolor;
}
public void setLabeldx(int labeldx) {
this.labeldx = labeldx;
}
public void setLabeldy(int labeldy) {
this.labeldy = labeldy;
}
public void setLabelalign(int labelalign) {
this.labelalign = labelalign;
}
public void setLabelcs(int labelcs) {
this.labelcs = labelcs;
}
public void setLabelwidth(int labelwidth) {
this.labelwidth = labelwidth;
}
public void setLabeltype(int labeltype) {
this.labeltype = labeltype;
}
public void setRangetype(int rangetype) {
this.rangetype = rangetype;
}
public void setTitlepos(int titlepos) {
this.titlepos = titlepos;
}
public void setInflate(double inflate) {
if (!Double.isNaN(inflate) && inflate != 0) {
this.inflate = inflate;
}
}
public double getTickSample(int i) {
if (i >= 0 && i < numticks) {
return ticksample[i];
} else {
return Double.NaN;
}
}
public int getNumticks() {
return numticks;
}
}