/*******************************************************************************
* Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
* Copyright (c) 2011 The OpenNMS Group, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*******************************************************************************/
package org.jrobin.graph;
import java.util.ArrayList;
import java.util.List;
class LegendComposer implements RrdGraphConstants {
private RrdGraphDef gdef;
private ImageWorker worker;
private int legX, legY, legWidth;
private double interlegendSpace;
private double leading;
private double smallLeading;
private double boxSpace;
LegendComposer(RrdGraph rrdGraph, int legX, int legY, int legWidth) {
this.gdef = rrdGraph.gdef;
this.worker = rrdGraph.worker;
this.legX = legX;
this.legY = legY;
this.legWidth = legWidth;
interlegendSpace = rrdGraph.getInterlegendSpace();
leading = rrdGraph.getLeading();
smallLeading = rrdGraph.getSmallLeading();
boxSpace = rrdGraph.getBoxSpace();
}
int placeComments() {
Line line = new Line();
for (CommentText comment : gdef.comments) {
if (comment.isValidGraphElement()) {
if (!line.canAccomodate(comment)) {
line.layoutAndAdvance(false);
line.clear();
}
line.add(comment);
}
}
line.layoutAndAdvance(true);
worker.dispose();
return legY;
}
class Line {
private String lastMarker;
private double width;
private int spaceCount;
private boolean noJustification;
private List<CommentText> comments = new ArrayList<CommentText>();
Line() {
clear();
}
void clear() {
lastMarker = "";
width = 0;
spaceCount = 0;
noJustification = false;
comments.clear();
}
boolean canAccomodate(CommentText comment) {
// always accommodate if empty
if (comments.size() == 0) {
return true;
}
// cannot accommodate if the last marker was \j, \l, \r, \c, \s
if (lastMarker.equals(ALIGN_LEFT_MARKER) || lastMarker.equals(ALIGN_CENTER_MARKER) ||
lastMarker.equals(ALIGN_RIGHT_MARKER) || lastMarker.equals(ALIGN_JUSTIFIED_MARKER) ||
lastMarker.equals(VERTICAL_SPACING_MARKER)) {
return false;
}
// cannot accommodate if line would be too long
double commentWidth = getCommentWidth(comment);
if (!lastMarker.equals(GLUE_MARKER)) {
commentWidth += interlegendSpace;
}
return width + commentWidth <= legWidth;
}
void add(CommentText comment) {
double commentWidth = getCommentWidth(comment);
if (comments.size() > 0 && !lastMarker.equals(GLUE_MARKER)) {
commentWidth += interlegendSpace;
spaceCount++;
}
width += commentWidth;
lastMarker = comment.marker;
noJustification |= lastMarker.equals(NO_JUSTIFICATION_MARKER);
comments.add(comment);
}
void layoutAndAdvance(boolean isLastLine) {
if (comments.size() > 0) {
if (lastMarker.equals(ALIGN_LEFT_MARKER)) {
placeComments(legX, interlegendSpace);
}
else if (lastMarker.equals(ALIGN_RIGHT_MARKER)) {
placeComments(legX + legWidth - width, interlegendSpace);
}
else if (lastMarker.equals(ALIGN_CENTER_MARKER)) {
placeComments(legX + (legWidth - width) / 2.0, interlegendSpace);
}
else if (lastMarker.equals(ALIGN_JUSTIFIED_MARKER)) {
// anything to justify?
if (spaceCount > 0) {
placeComments(legX, (legWidth - width) / spaceCount + interlegendSpace);
}
else {
placeComments(legX, interlegendSpace);
}
}
else if (lastMarker.equals(VERTICAL_SPACING_MARKER)) {
placeComments(legX, interlegendSpace);
}
else {
// nothing specified, align with respect to '\J'
if (noJustification || isLastLine) {
placeComments(legX, interlegendSpace);
}
else {
placeComments(legX, (legWidth - width) / spaceCount + interlegendSpace);
}
}
if (lastMarker.equals(VERTICAL_SPACING_MARKER)) {
legY += smallLeading;
}
else {
legY += leading;
}
}
}
private double getCommentWidth(CommentText comment) {
double commentWidth = worker.getStringWidth(comment.resolvedText, gdef.getFont(FONTTAG_LEGEND));
if (comment instanceof LegendText) {
commentWidth += boxSpace;
}
return commentWidth;
}
private void placeComments(double xStart, double space) {
double x = xStart;
for (CommentText comment : comments) {
comment.x = (int) x;
comment.y = legY;
x += getCommentWidth(comment);
if (!comment.marker.equals(GLUE_MARKER)) {
x += space;
}
}
}
}
}