[#6352] Add Result.formatChart() to produce ASCII text charts
This commit is contained in:
parent
8e23952fc5
commit
bc05c60bc0
502
jOOQ/src/main/java/org/jooq/ChartFormat.java
Normal file
502
jOOQ/src/main/java/org/jooq/ChartFormat.java
Normal file
@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public final class ChartFormat {
|
||||
|
||||
public static final ChartFormat DEFAULT = new ChartFormat();
|
||||
|
||||
final Output output;
|
||||
final Type type;
|
||||
final Display display;
|
||||
final int width;
|
||||
final int height;
|
||||
final int category;
|
||||
final boolean categoryAsText;
|
||||
final int[] values;
|
||||
final char[] shades;
|
||||
final boolean showHorizontalLegend;
|
||||
final boolean showVerticalLegend;
|
||||
final String newline;
|
||||
final DecimalFormat numericFormat;
|
||||
|
||||
public ChartFormat() {
|
||||
this(
|
||||
Output.ASCII,
|
||||
Type.AREA,
|
||||
Display.STACKED,
|
||||
80,
|
||||
25,
|
||||
0,
|
||||
true,
|
||||
new int[] { 1 },
|
||||
new char[] { '█', '▓', '▒', '░' },
|
||||
true,
|
||||
true,
|
||||
"\n",
|
||||
new DecimalFormat("###,###.00")
|
||||
);
|
||||
}
|
||||
|
||||
private ChartFormat(
|
||||
Output output,
|
||||
Type type,
|
||||
Display display,
|
||||
int width,
|
||||
int height,
|
||||
int category,
|
||||
boolean categoryAsText,
|
||||
int[] values,
|
||||
char[] shades,
|
||||
boolean showHorizontalLegend,
|
||||
boolean showVerticalLegend,
|
||||
String newline,
|
||||
DecimalFormat numericFormat
|
||||
) {
|
||||
this.output = output;
|
||||
this.type = type;
|
||||
this.display = display;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.category = category;
|
||||
this.categoryAsText = categoryAsText;
|
||||
this.values = values;
|
||||
this.shades = shades;
|
||||
this.showHorizontalLegend = showHorizontalLegend;
|
||||
this.showVerticalLegend = showVerticalLegend;
|
||||
this.newline = newline;
|
||||
this.numericFormat = numericFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new output format, defaulting to {@link Output#ASCII}.
|
||||
*/
|
||||
public ChartFormat output(Output newOutput) {
|
||||
return new ChartFormat(
|
||||
newOutput,
|
||||
type,
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
category,
|
||||
categoryAsText,
|
||||
values,
|
||||
shades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The output format.
|
||||
*/
|
||||
public Output output() {
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new chart type, defaulting to {@link Area}.
|
||||
*/
|
||||
public ChartFormat type(Type newType) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
newType,
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
category,
|
||||
categoryAsText,
|
||||
values,
|
||||
shades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new display format, defaulting to {@link Display#STACKED}.
|
||||
*/
|
||||
public ChartFormat display(Display newDisplay) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
type,
|
||||
newDisplay,
|
||||
width,
|
||||
height,
|
||||
category,
|
||||
categoryAsText,
|
||||
values,
|
||||
shades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The display format.
|
||||
*/
|
||||
public Display display() {
|
||||
return display;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new chart dimensions, defaulting to <code>80 x 25</code>.
|
||||
*/
|
||||
public ChartFormat dimensions(int newWidth, int newHeight) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
type,
|
||||
display,
|
||||
newWidth,
|
||||
newHeight,
|
||||
category,
|
||||
categoryAsText,
|
||||
values,
|
||||
shades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The new chart width, defaulting to <code>80</code>.
|
||||
*/
|
||||
public ChartFormat width(int newWidth) {
|
||||
return dimensions(newWidth, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* The chart width.
|
||||
*/
|
||||
public int width() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new chart height, defaulting to <code>25</code>.
|
||||
*/
|
||||
public ChartFormat height(int newHeight) {
|
||||
return dimensions(width, newHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* The chart height.
|
||||
*/
|
||||
public int height() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new category source column number, defaulting to <code>0</code>.
|
||||
*/
|
||||
public ChartFormat category(int newCategory) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
type,
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
newCategory,
|
||||
categoryAsText,
|
||||
values,
|
||||
shades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The category source column number.
|
||||
*/
|
||||
public int category() {
|
||||
return category;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new category as text value, defaulting to <code>true</code>.
|
||||
*/
|
||||
public ChartFormat categoryAsText(boolean newCategoryAsText) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
type,
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
category,
|
||||
newCategoryAsText,
|
||||
values,
|
||||
shades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The category as text value.
|
||||
*/
|
||||
public boolean categoryAsText() {
|
||||
return categoryAsText;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new value source column numbers, defaulting to <code>{ 1 }</code>.
|
||||
*/
|
||||
public ChartFormat values(int... newValues) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
type,
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
category,
|
||||
categoryAsText,
|
||||
newValues,
|
||||
shades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The value source column numbers.
|
||||
*/
|
||||
public int[] values() {
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new column shades, defaulting to <code>{ 'X' }</code>.
|
||||
*/
|
||||
public ChartFormat shades(char... newShades) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
type,
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
category,
|
||||
categoryAsText,
|
||||
values,
|
||||
newShades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The value column shades.
|
||||
*/
|
||||
public char[] shades() {
|
||||
return shades;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to show legends, defaulting to <code>true</code>.
|
||||
*/
|
||||
public ChartFormat showLegends(boolean newShowHorizontalLegend, boolean newShowVerticalLegend) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
type,
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
category,
|
||||
categoryAsText,
|
||||
values,
|
||||
shades,
|
||||
newShowHorizontalLegend,
|
||||
newShowVerticalLegend,
|
||||
newline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to show the horizontal legend, defaulting to <code>true</code>.
|
||||
*/
|
||||
public ChartFormat showHorizontalLegend(boolean newShowHorizontalLegend) {
|
||||
return showLegends(newShowHorizontalLegend, showVerticalLegend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to show the horizontal legend.
|
||||
*/
|
||||
public boolean showHorizontalLegend() {
|
||||
return showHorizontalLegend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to show the vertical legend, defaulting to <code>true</code>.
|
||||
*/
|
||||
public ChartFormat showVerticalLegend(boolean newShowVerticalLegend) {
|
||||
return showLegends(showHorizontalLegend, newShowVerticalLegend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to show the vertical legend.
|
||||
*/
|
||||
public boolean showVerticalLegend() {
|
||||
return showVerticalLegend;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new newline character, defaulting to <code>\n</code>.
|
||||
*/
|
||||
public ChartFormat newline(String newNewline) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
type,
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
category,
|
||||
categoryAsText,
|
||||
values,
|
||||
shades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newNewline,
|
||||
numericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The newline character.
|
||||
*/
|
||||
public String newline() {
|
||||
return newline;
|
||||
}
|
||||
|
||||
/**
|
||||
* The new numeric format, defaulting to <code>###,###.00</code>.
|
||||
*/
|
||||
public ChartFormat numericFormat(DecimalFormat newNumericFormat) {
|
||||
return new ChartFormat(
|
||||
output,
|
||||
type,
|
||||
display,
|
||||
width,
|
||||
height,
|
||||
category,
|
||||
categoryAsText,
|
||||
values,
|
||||
shades,
|
||||
showHorizontalLegend,
|
||||
showVerticalLegend,
|
||||
newline,
|
||||
newNumericFormat
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The numeric format.
|
||||
*/
|
||||
public DecimalFormat numericFormat() {
|
||||
return numericFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* The chart output format.
|
||||
*/
|
||||
public enum Output {
|
||||
|
||||
/**
|
||||
* An ASCII chart.
|
||||
*/
|
||||
ASCII,
|
||||
|
||||
// /**
|
||||
// * An ANSI escape sequenced chart.
|
||||
// */
|
||||
// ANSI,
|
||||
//
|
||||
// /**
|
||||
// * An SVG chart.
|
||||
// */
|
||||
// SVG,
|
||||
|
||||
}
|
||||
|
||||
public static enum Type {
|
||||
|
||||
/**
|
||||
* An area chart.
|
||||
*/
|
||||
AREA,
|
||||
}
|
||||
|
||||
public static enum Display {
|
||||
|
||||
/**
|
||||
* The areas are located in front of one another.
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
/**
|
||||
* The areas are stacked on top of one another.
|
||||
*/
|
||||
STACKED,
|
||||
|
||||
/**
|
||||
* The areas stack up to 100%.
|
||||
*/
|
||||
HUNDRED_PERCENT_STACKED
|
||||
}
|
||||
}
|
||||
@ -630,6 +630,10 @@ public interface Result<R extends Record> extends List<R>, Attachable {
|
||||
*/
|
||||
String formatXML(XMLFormat format);
|
||||
|
||||
String formatChart();
|
||||
|
||||
String formatChart(ChartFormat format);
|
||||
|
||||
/**
|
||||
* Get this result as a set of <code>INSERT</code> statements.
|
||||
* <p>
|
||||
@ -747,6 +751,20 @@ public interface Result<R extends Record> extends List<R>, Attachable {
|
||||
*/
|
||||
void formatXML(OutputStream stream, XMLFormat format) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatChart()}, but the data is output onto an {@link OutputStream}.
|
||||
*
|
||||
* @throws IOException - an unchecked wrapper for {@link java.io.IOException}, if anything goes wrong.
|
||||
*/
|
||||
void formatChart(OutputStream stream) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatChart(ChartFormat)}, but the data is output onto an {@link OutputStream}.
|
||||
*
|
||||
* @throws IOException - an unchecked wrapper for {@link java.io.IOException}, if anything goes wrong.
|
||||
*/
|
||||
void formatChart(OutputStream stream, ChartFormat format) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatInsert()}, but the data is output onto an {@link OutputStream}.
|
||||
*
|
||||
@ -859,6 +877,20 @@ public interface Result<R extends Record> extends List<R>, Attachable {
|
||||
*/
|
||||
void formatXML(Writer writer, XMLFormat format) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatChart()}, but the data is output onto a {@link Writer}.
|
||||
*
|
||||
* @throws IOException - an unchecked wrapper for {@link java.io.IOException}, if anything goes wrong.
|
||||
*/
|
||||
void formatChart(Writer writer) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatChart(ChartFormat)}, but the data is output onto a {@link Writer}.
|
||||
*
|
||||
* @throws IOException - an unchecked wrapper for {@link java.io.IOException}, if anything goes wrong.
|
||||
*/
|
||||
void formatChart(Writer writer, ChartFormat format) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatInsert()}, but the data is output onto a {@link Writer}.
|
||||
*
|
||||
|
||||
@ -67,6 +67,7 @@ import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
@ -74,6 +75,8 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.jooq.CSVFormat;
|
||||
import org.jooq.ChartFormat;
|
||||
import org.jooq.ChartFormat.Display;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Constants;
|
||||
import org.jooq.Converter;
|
||||
@ -1222,6 +1225,207 @@ final class ResultImpl<R extends Record> implements Result<R> {
|
||||
writer.append(newline).append(format.indentString(recordLevel)).append("</record>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String formatChart() {
|
||||
StringWriter writer = new StringWriter();
|
||||
formatChart(writer);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String formatChart(ChartFormat format) {
|
||||
StringWriter writer = new StringWriter();
|
||||
formatChart(writer, format);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void formatChart(OutputStream stream) {
|
||||
formatChart(new OutputStreamWriter(stream));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void formatChart(OutputStream stream, ChartFormat format) {
|
||||
formatChart(new OutputStreamWriter(stream), format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void formatChart(Writer writer) {
|
||||
formatChart(writer, ChartFormat.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void formatChart(Writer writer, ChartFormat format) {
|
||||
try {
|
||||
Field<?> category = field(format.category());
|
||||
TreeMap<Object, Result<R>> groups = new TreeMap<Object, Result<R>>(intoGroups(format.category()));
|
||||
|
||||
if (!format.categoryAsText()) {
|
||||
if (Date.class.isAssignableFrom(category.getType())) {
|
||||
Date categoryMin = (Date) groups.firstKey();
|
||||
Date categoryMax = (Date) groups.lastKey();
|
||||
|
||||
for (Date i = categoryMin; i.before(categoryMax); i = new Date(i.getYear(), i.getMonth(), i.getDate() + 1))
|
||||
if (!groups.containsKey(i))
|
||||
groups.put(i, (Result) DSL.using(configuration).newResult(fields()));
|
||||
}
|
||||
}
|
||||
|
||||
List<?> categories = new ArrayList<Object>(groups.keySet());
|
||||
|
||||
int categoryPadding = 1;
|
||||
int categoryWidth = 0;
|
||||
for (Object o : categories)
|
||||
categoryWidth = Math.max(categoryWidth, ("" + o).length());
|
||||
|
||||
double axisMin = Double.POSITIVE_INFINITY;
|
||||
double axisMax = Double.NEGATIVE_INFINITY;
|
||||
|
||||
for (Result<R> values : groups.values()) {
|
||||
double sum = 0;
|
||||
|
||||
for (int i = 0; i < format.values().length; i++) {
|
||||
if (format.display() == Display.DEFAULT)
|
||||
sum = 0;
|
||||
|
||||
for (Record r : values)
|
||||
sum = sum + r.get(format.values()[i], double.class);
|
||||
|
||||
if (sum < axisMin)
|
||||
axisMin = sum;
|
||||
|
||||
if (sum > axisMax)
|
||||
axisMax = sum;
|
||||
}
|
||||
}
|
||||
|
||||
int verticalLegendWidth = format.showVerticalLegend()
|
||||
? Math.max(
|
||||
format.numericFormat().format(axisMin).length(),
|
||||
format.numericFormat().format(axisMax).length()
|
||||
)
|
||||
: 0;
|
||||
|
||||
int horizontalLegendHeight = format.showHorizontalLegend() ? 1 : 0;
|
||||
|
||||
int verticalBorderWidth = format.showVerticalLegend() ? 1 : 0;
|
||||
int horizontalBorderHeight = format.showHorizontalLegend() ? 1 : 0;
|
||||
|
||||
int chartHeight = format.height() - horizontalLegendHeight - horizontalBorderHeight;
|
||||
int chartWidth = format.width() - verticalLegendWidth - verticalBorderWidth;
|
||||
|
||||
double barWidth = (double) chartWidth / groups.size();
|
||||
double axisStep = (axisMax - axisMin) / (chartHeight - 1);
|
||||
|
||||
for (int y = chartHeight - 1; y >= 0; y--) {
|
||||
double axisLegend = axisMax - (axisStep * (chartHeight - 1 - y));
|
||||
double axisLegendPercent = (axisLegend - axisMin) / (axisMax - axisMin);
|
||||
|
||||
if (format.showVerticalLegend()) {
|
||||
String axisLegendString = (format.display() == Display.HUNDRED_PERCENT_STACKED)
|
||||
? format.numericFormat().format(axisLegendPercent * 100.0) + "%"
|
||||
: format.numericFormat().format(axisLegend);
|
||||
|
||||
for (int x = axisLegendString.length(); x < verticalLegendWidth; x++)
|
||||
writer.write(' ');
|
||||
|
||||
writer.write(axisLegendString);
|
||||
|
||||
for (int x = 0; x < verticalBorderWidth; x++)
|
||||
writer.write('|');
|
||||
}
|
||||
|
||||
for (int x = 0; x < chartWidth; x++) {
|
||||
int index = (int) (x / barWidth);
|
||||
|
||||
Result<R> group = groups.get(categories.get(index));
|
||||
double[] values = new double[format.values().length];
|
||||
|
||||
for (Record record : group)
|
||||
for (int i = 0; i < values.length; i++)
|
||||
values[i] = values[i] + record.get(format.values()[i], double.class);
|
||||
|
||||
if (format.display() == Display.STACKED || format.display() == Display.HUNDRED_PERCENT_STACKED)
|
||||
for (int i = 1; i < values.length; i++)
|
||||
values[i] = values[i] + values[i - 1];
|
||||
|
||||
if (format.display() == Display.HUNDRED_PERCENT_STACKED)
|
||||
for (int i = 0; i < values.length; i++)
|
||||
values[i] = values[i] / values[values.length - 1];
|
||||
|
||||
int shadeIndex = -1;
|
||||
for (int i = values.length - 1; i >= 0; i--)
|
||||
if ((format.display() == Display.HUNDRED_PERCENT_STACKED ? axisLegendPercent : axisLegend) > values[i])
|
||||
break;
|
||||
else
|
||||
shadeIndex = i;
|
||||
|
||||
if (shadeIndex == -1)
|
||||
writer.write(' ');
|
||||
else
|
||||
writer.write(format.shades()[shadeIndex % format.shades().length]);
|
||||
}
|
||||
|
||||
writer.write(format.newline());
|
||||
}
|
||||
|
||||
if (format.showHorizontalLegend()) {
|
||||
for (int y = 0; y < horizontalBorderHeight; y++) {
|
||||
if (format.showVerticalLegend()) {
|
||||
for (int x = 0; x < verticalLegendWidth; x++)
|
||||
writer.write('-');
|
||||
|
||||
for (int x = 0; x < verticalBorderWidth; x++)
|
||||
writer.write('+');
|
||||
}
|
||||
|
||||
for (int x = 0; x < chartWidth; x++)
|
||||
writer.write('-');
|
||||
|
||||
writer.write(format.newline());
|
||||
}
|
||||
|
||||
for (int y = 0; y < horizontalLegendHeight; y++) {
|
||||
if (format.showVerticalLegend()) {
|
||||
for (int x = 0; x < verticalLegendWidth; x++)
|
||||
writer.write(' ');
|
||||
|
||||
for (int x = 0; x < verticalBorderWidth; x++)
|
||||
writer.write('|');
|
||||
}
|
||||
|
||||
double rounding = 0.0;
|
||||
for (double x = 0.0; x < chartWidth;) {
|
||||
String label = "" + categories.get((int) (x / barWidth));
|
||||
int length = label.length();
|
||||
|
||||
double padding = Math.max(categoryPadding, (barWidth - length) / 2);
|
||||
|
||||
rounding = (rounding + padding - Math.floor(padding)) % 1;
|
||||
x = x + (padding + rounding);
|
||||
for (int i = 0; i < (int) (padding + rounding); i++)
|
||||
writer.write(' ');
|
||||
|
||||
x = x + length;
|
||||
if (x >= chartWidth)
|
||||
break;
|
||||
writer.write(label);
|
||||
|
||||
rounding = (rounding + padding - Math.floor(padding)) % 1;
|
||||
x = x + (padding + rounding);
|
||||
for (int i = 0; i < (int) (padding + rounding); i++)
|
||||
writer.write(' ');
|
||||
}
|
||||
|
||||
writer.write(format.newline());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (java.io.IOException e) {
|
||||
throw new IOException("Exception while writing Chart", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String formatInsert() {
|
||||
StringWriter writer = new StringWriter();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user