001: /**
002: * ===========================================
003: * JFreeReport : a free Java reporting library
004: * ===========================================
005: *
006: * Project Info: http://reporting.pentaho.org/
007: *
008: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
009: *
010: * This library is free software; you can redistribute it and/or modify it under the terms
011: * of the GNU Lesser General Public License as published by the Free Software Foundation;
012: * either version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015: * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: * See the GNU Lesser General Public License for more details.
017: *
018: * You should have received a copy of the GNU Lesser General Public License along with this
019: * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: *
022: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023: * in the United States and other countries.]
024: *
025: * ------------
026: * RightAlignmentProcessor.java
027: * ------------
028: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029: */package org.jfree.report.layout.process.alignment;
030:
031: import org.jfree.report.layout.model.RenderBox;
032: import org.jfree.report.layout.model.RenderNode;
033: import org.jfree.report.layout.process.layoutrules.EndSequenceElement;
034: import org.jfree.report.layout.process.layoutrules.InlineBoxSequenceElement;
035: import org.jfree.report.layout.process.layoutrules.InlineSequenceElement;
036: import org.jfree.report.layout.process.layoutrules.StartSequenceElement;
037: import org.jfree.report.layout.process.layoutrules.TextSequenceElement;
038:
039: /**
040: * Right alignment strategy. Not working yet, as this is unimplemented right now.
041: *
042: * @author Thomas Morgner
043: */
044: public class RightAlignmentProcessor extends AbstractAlignmentProcessor {
045:
046: public RightAlignmentProcessor() {
047: }
048:
049: /**
050: * Handle the next input chunk.
051: *
052: * @param start the start index
053: * @param count the number of elements in the sequence
054: * @return the index of the last element that will fit on the current line.
055: */
056: protected int handleElement(final int start, final int count) {
057: final RenderNode[] nodes = getNodes();
058: final InlineSequenceElement[] sequenceElements = getSequenceElements();
059: final long[] elementDimensions = getElementDimensions();
060: final long[] elementPositions = getElementPositions();
061:
062: // if we reached that method, then this means, that the elements may fit
063: // into the available space. (Assuming that there is no inner pagebreak;
064: // a thing we do not handle yet)
065: final int endIndex = start + count;
066: long usedWidth = 0;
067: int contentIndex = start;
068: InlineSequenceElement contentElement = null;
069: for (int i = 0; i < endIndex; i++) {
070: final InlineSequenceElement element = sequenceElements[i];
071: final RenderNode node = nodes[i];
072: usedWidth += element.getMaximumWidth(node);
073: if (element instanceof StartSequenceElement
074: || element instanceof EndSequenceElement) {
075: continue;
076: }
077: contentElement = element;
078: contentIndex = i;
079: }
080:
081: final long nextPosition = (getStartOfLine() + usedWidth);
082: final long lastPageBreak = getPageBreak(getPagebreakCount() - 1);
083: if (nextPosition > lastPageBreak) {
084: // The contents we processed so far will not fit on the current line. That's dangerous.
085: // We have to right align the content up to the element denoted with 'start'.
086:
087: // Ignore the retval, we know that it fits (or at least that it is correct some how ..)
088: rightAlign(start, sequenceElements, nodes,
089: elementPositions, elementDimensions);
090:
091: // we cross a pagebreak. Stop working on it - we bail out here.
092:
093: if (contentElement instanceof TextSequenceElement) {
094: // the element may be splittable. Test, and if so, give a hint to the
095: // outside world ..
096: setSkipIndex(endIndex);
097: setBreakableIndex(contentIndex);
098: return (start);
099: }
100:
101: // This is the first element and it still does not fit. How evil.
102: if (start == 0) {
103: if (contentElement instanceof InlineBoxSequenceElement) {
104: final RenderNode node = nodes[contentIndex];
105: if (node instanceof RenderBox) {
106: // OK, limit the size of the box to the maximum line width and
107: // revalidate it.
108: final long contentPosition = elementPositions[contentIndex];
109: final RenderBox box = (RenderBox) node;
110: final long maxWidth = (getEndOfLine() - contentPosition);
111: computeInlineBlock(box, contentPosition,
112: maxWidth);
113:
114: elementDimensions[endIndex - 1] = node
115: .getCachedWidth();
116: }
117: }
118: setSkipIndex(endIndex);
119: }
120: return (start);
121: }
122:
123: // This implementation does not handle inline-block elements correctly.
124: // but for the classic engine, this is less important, as we do not allow them anyway.
125:
126: if (rightAlign(endIndex, sequenceElements, nodes,
127: elementPositions, elementDimensions)) {
128: return endIndex;
129: }
130: return start;
131: }
132:
133: private boolean rightAlign(final int endIndex,
134: final InlineSequenceElement[] sequenceElements,
135: final RenderNode[] nodes, final long[] elementPositions,
136: final long[] elementDimensions) {
137: // iterate backwards ..
138: // The left-edge. This one is fixed; crossing this edge will be punished ..
139: final long startOfLine = getStartOfLine();
140: // the current segment.
141: int segment = getPagebreakCount() - 1;
142: long endPosition = getEndOfLine();
143: long segmentStart = getStartOfSegment(segment);
144:
145: for (int i = endIndex - 1; i >= 0; i--) {
146: final InlineSequenceElement element = sequenceElements[i];
147: final long elementWidth = element.getMaximumWidth(nodes[i]);
148: long elementStart = endPosition - elementWidth;
149: if (elementStart < startOfLine) {
150: // this element will not fit. Skip it.
151: return false;
152: }
153:
154: while (segment > 0 && elementStart < segmentStart) {
155: // the element will not fit into the current segment. Move it to the next segment.
156: elementStart = segmentStart - elementWidth;
157: segment -= 1;
158: segmentStart = getStartOfSegment(segment);
159: }
160:
161: if (elementStart < segmentStart) {
162: // the element will not fit into any of the remaining segments. So skip it.
163: return false;
164: }
165:
166: elementPositions[i] = elementStart;
167: elementDimensions[i] = elementWidth;
168: endPosition = elementStart;
169: }
170:
171: return true;
172: }
173:
174: private long getStartOfSegment(final int segment) {
175: if (segment == 0) {
176: return getStartOfLine();
177: }
178:
179: return getPageBreak(segment - 1);
180: }
181:
182: }
|