package org.apache.fop.fo.pagination;
// FOP
-import org.apache.fop.fo.*;
-import org.apache.fop.fo.properties.*;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.Title;
import org.apache.fop.fo.flow.Flow;
import org.apache.fop.fo.flow.StaticContent;
import org.apache.fop.layout.PageMaster;
/**
* Map of flows to their flow name (flow-name, Flow)
*/
- private HashMap _flowMap;
+ private HashMap flowMap;
// according to communication from Paul Grosso (XSL-List,
// 001228, Number 406), confusion in spec section 6.4.5 about
*/
private Title titleFO;
-
+ /**
+ * Create a page sequence FO node.
+ *
+ * @param parent the parent FO node
+ */
public PageSequence(FONode parent) {
super(parent);
}
+ /**
+ * Handle the attributes for this xml element.
+ * For the page sequence this gets all the appropriate properties
+ * for dealing with the page sequence.
+ *
+ * @param attlist the attribute list
+ * @throws FOPException if there is an error with the properties
+ */
public void handleAttrs(Attributes attlist) throws FOPException {
super.handleAttrs(attlist);
if (parent.getName().equals("fo:root")) {
this.root = (Root)parent;
// this.root.addPageSequence(this);
- }
- else {
+ } else {
throw new FOPException("page-sequence must be child of root, not "
+ parent.getName());
}
// best time to run some checks on LayoutMasterSet
layoutMasterSet.checkRegionNames();
- _flowMap = new HashMap();
+ flowMap = new HashMap();
// we are now on the first page of the page sequence
thisIsFirstPage = true;
this.layoutMasterSet.getPageSequenceMaster(masterName);
if (this.pageSequenceMaster == null) {
throw new FOPException("master-reference '" + masterName
- + "' for fo:page-sequence matches no simple-page-master or page-sequence-master");
+ + "' for fo:page-sequence matches no"
+ + " simple-page-master or page-sequence-master");
}
}
* generate that page.
*/
// private void addFlow(Flow flow) throws FOPException {
-// if (_flowMap.containsKey(flow.getFlowName())) {
+// if (flowMap.containsKey(flow.getFlowName())) {
// throw new FOPException("flow-names must be unique within an fo:page-sequence");
// }
// if (!this.layoutMasterSet.regionNameExists(flow.getFlowName())) {
// + flow.getFlowName()
// + "' doesn't exist in the layout-master-set.");
// }
-// _flowMap.put(flow.getFlowName(), flow);
+// flowMap.put(flow.getFlowName(), flow);
// //setIsFlowSet(true);
// }
* Validate the child being added and initialize internal variables.
* XSL content model for page-sequence:
* <pre>(title?,static-content*,flow)</pre>
- * Note: title isn't currently implemented.
+ *
* @param child The flow object child to be added to the PageSequence.
*/
public void addChild(FONode child) {
try {
String childName = child.getName();
if (childName.equals("fo:title")) {
- if (this._flowMap.size()>0) {
+ if (this.flowMap.size() > 0) {
getLogger().warn("fo:title should be first in page-sequence");
} else {
this.titleFO = (Title)child;
} else {
this.mainFlow = (Flow)child;
String flowName = this.mainFlow.getFlowName();
- if (_flowMap.containsKey(flowName)) {
+ if (flowMap.containsKey(flowName)) {
throw new FOPException("flow-name "
+ flowName
+ " is not unique within an fo:page-sequence");
}
// Don't add main flow to the flow map
// addFlow(mainFlow);
- if(!sequenceStarted) {
+ if (!sequenceStarted) {
structHandler.startPageSequence(this, titleFO, layoutMasterSet);
sequenceStarted = true;
}
}
} else if (childName.equals("fo:static-content")) {
if (this.mainFlow != null) {
- throw new FOPException(childName +
- " must precede fo:flow; ignoring");
+ throw new FOPException(childName
+ + " must precede fo:flow; ignoring");
}
String flowName = ((StaticContent)child).getFlowName();
- if (_flowMap.containsKey(flowName)) {
+ if (flowMap.containsKey(flowName)) {
throw new FOPException("flow-name " + flowName
+ " is not unique within an fo:page-sequence");
}
getLogger().error("region-name '" + flowName
+ "' doesn't exist in the layout-master-set.");
}
- _flowMap.put(flowName, child);
+ flowMap.put(flowName, child);
// addFlow((Flow)child);
- if(!sequenceStarted) {
+ if (!sequenceStarted) {
structHandler.startPageSequence(this, titleFO, layoutMasterSet);
sequenceStarted = true;
}
} else {
// Ignore it!
- getLogger().warn("FO '" + childName +
- "' not a legal page-sequence child.");
+ getLogger().warn("FO '" + childName
+ + "' not a legal page-sequence child.");
return;
}
} catch (FOPException fopex) {
- getLogger().error("Error in PageSequence.addChild(): " +
- fopex.getMessage(), fopex);
+ getLogger().error("Error in PageSequence.addChild(): "
+ + fopex.getMessage(), fopex);
}
}
+ /**
+ * Signal end of this xml element.
+ * This passes the end page sequence to the structure handler
+ * so it can act upon that.
+ */
public void end() {
try {
this.structHandler.endPageSequence(this);
} catch (FOPException fopex) {
- getLogger().error("Error in PageSequence.end(): " +
- fopex.getMessage(), fopex);
+ getLogger().error("Error in PageSequence.end(): "
+ + fopex.getMessage(), fopex);
}
}
/**
* Runs the formatting of this page sequence into the given area tree
+ *
+ * @param areaTree the area tree to format this page sequence into
+ * @throws FOPException if there is an error formatting the contents
*/
public void format(AreaTree areaTree) throws FOPException {
// Make a new PageLayoutManager and a FlowLayoutManager
// Initialize if already used?
// this.layoutMasterSet.resetPageMasters();
- if (pageSequenceMaster != null ) {
+ if (pageSequenceMaster != null) {
pageSequenceMaster.reset();
}
this.root.setRunningPageNumberCounter(this.currentPageNumber);
}
+ /**
+ * Initialize the current page number for the start of the page sequence.
+ */
private void initPageNumber() {
this.currentPageNumber = this.root.getRunningPageNumberCounter() + 1;
* Called by PageLayoutManager when it needs a new page on which to
* place content. The PageSequence manages the page number (odd/even),
* but the PLM tells it if the page is blank or is the last page.
+ *
+ * @param pageNumber the page number to create page for
* @param bIsBlank If true, use a master for a blank page.
+ * @param firstPage true if this is the first page
* @param bIsLast If true, use the master for the last page in the sequence.
+ * @return the page viewport created for the page number
+ * @throws FOPException if there is an error creating page
*/
- public PageViewport createPage(int pageNumber, boolean bIsBlank, boolean bIsLast)
- throws FOPException {
+ public PageViewport createPage(int pageNumber, boolean bIsBlank,
+ boolean firstPage, boolean bIsLast)
+ throws FOPException {
if (this.pageSequenceMaster != null) {
this.currentSimplePageMaster = this.pageSequenceMaster
.getNextSimplePageMaster(((pageNumber % 2) == 1),
- thisIsFirstPage,
+ firstPage,
bIsBlank);
}
Region body = currentSimplePageMaster.getRegion(Region.BODY);
* (e.g. forced even or odd break)
* @return a Page layout object based on the page master selected
* from the params
- * TODO: modify the other methods to use even/odd flag and bIsLast
+ * @todo modify the other methods to use even/odd flag and bIsLast
*/
// private PageViewport makePage(int firstAvailPageNumber,
// boolean isFirstPage, boolean bIsLast,
// this.layoutMasterSet.getSimplePageMaster(pageSequenceName);
// if (simpleMaster == null) {
// throw new FOPException("'master-reference' for 'fo:page-sequence'"
-// + "matches no 'simple-page-master' or 'page-sequence-master'");
+// + "matches no 'simple-page-master'"
+// + " or 'page-sequence-master'");
// }
// currentPageMasterName = pageSequenceName;
// private boolean flowsAreIncomplete() {
// boolean isIncomplete = false;
-// for (Iterator e = _flowMap.values().iterator(); e.hasNext(); ) {
+// for (Iterator e = flowMap.values().iterator(); e.hasNext(); ) {
// Flow flow = (Flow)e.next();
// if (flow instanceof StaticContent) {
// continue;
// private Flow getCurrentFlow(String regionClass) {
// Region region = getCurrentSimplePageMaster().getRegion(regionClass);
// if (region != null) {
-// Flow flow = (Flow)_flowMap.get(region.getRegionName());
+// Flow flow = (Flow)flowMap.get(region.getRegionName());
// return flow;
// } else {
// Region region = spm.getRegion(Region.BODY);
-// Flow flow = (Flow)_flowMap.get(region.getRegionName());
+// Flow flow = (Flow)flowMap.get(region.getRegionName());
// /*if ((null == flow) || flow.getStatus().isIncomplete())
// return false;
// else
// this.isFlowSet = isFlowSet;
// }
+ /**
+ * Get the "initial-page-number" value.
+ *
+ * @return the initial-page-number property value
+ */
public String getIpnValue() {
return ipnValue;
}
+ /**
+ * Get the current page number for this page sequence.
+ *
+ * @return the current page number
+ */
public int getCurrentPageNumber() {
return currentPageNumber;
}
// }
// }
+ /**
+ * Get the current simple page master
+ * that is active for the last page created.
+ *
+ * @return the current simple page master
+ */
public SimplePageMaster getCurrentSimplePageMaster() {
return currentSimplePageMaster;
}
+
+ /**
+ * Get the static content FO node from the flow map.
+ * This gets the static content flow for the given flow name.
+ *
+ * @param name the flow name to find
+ * @return the static content FO node
+ */
public StaticContent getStaticContent(String name) {
- return (StaticContent)_flowMap.get(name);
+ return (StaticContent)flowMap.get(name);
}
}
package org.apache.fop.layoutmgr;
import org.apache.fop.apps.FOPException;
-import org.apache.fop.area.*;
+import org.apache.fop.area.AreaTree;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.area.Flow;
+import org.apache.fop.area.RegionViewport;
+import org.apache.fop.area.RegionReference;
+import org.apache.fop.area.BodyRegion;
+import org.apache.fop.area.MainReference;
+import org.apache.fop.area.Span;
+import org.apache.fop.area.BeforeFloat;
+import org.apache.fop.area.Footnote;
+import org.apache.fop.area.Resolveable;
import org.apache.fop.fo.flow.StaticContent;
import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fo.pagination.Region;
import org.apache.fop.fo.pagination.PageNumberGenerator;
import org.apache.fop.fo.properties.Constants;
+import org.apache.fop.area.MinOptMax;
+
import java.util.ArrayList;
import java.util.List;
public class PageLayoutManager extends AbstractLayoutManager implements Runnable {
private static class BlockBreakPosition extends LeafPosition {
- BreakPoss breakps;
+ protected BreakPoss breakps;
- BlockBreakPosition(LayoutManager lm, BreakPoss bp) {
+ protected BlockBreakPosition(LayoutManager lm, BreakPoss bp) {
super(lm, 0);
breakps = bp;
}
private PageNumberGenerator pageNumberGenerator;
private int pageCount = 1;
private String pageNumberString;
+ private boolean isFirstPage = true;
/** True if haven't yet laid out any pages.*/
private boolean bFirstPage;
/**
* This is the top level layout manager.
* It is created by the PageSequence FO.
+ *
+ * @param areaTree the area tree to add pages to
+ * @param pageseq the page sequence fo
*/
public PageLayoutManager(AreaTree areaTree, PageSequence pageseq) {
super(pageseq);
pageSequence = pageseq;
}
+ /**
+ * Set the page counting for this page sequence.
+ * This sets the initial page number and the page number formatter.
+ *
+ * @param pc the starting page number
+ * @param generator the page number generator
+ */
public void setPageCounting(int pc, PageNumberGenerator generator) {
pageCount = pc;
pageNumberGenerator = generator;
pageNumberString = pageNumberGenerator.makeFormattedPageNumber(pageCount);
}
+ /**
+ * Get the page count.
+ * Used to get the last page number for reference for
+ * the next page sequence.
+ *
+ * @return the page number
+ */
public int getPageCount() {
return pageCount;
}
flush();
}
- public void doLayout() {
+ /**
+ * Do the layout of this page sequence.
+ * This completes the layout of the page sequence
+ * which creates and adds all the pages to the area tree.
+ */
+ protected void doLayout() {
// this should be done another way
makeNewPage(false, false);
pageCount--;
}
-
+ /**
+ * Get the next break possibility.
+ * This finds the next break for a page which is always at the end
+ * of the page.
+ *
+ * @param context the layout context for finding breaks
+ * @return the break for the page
+ */
public BreakPoss getNextBreakPoss(LayoutContext context) {
LayoutManager curLM ; // currently active LM
return null;
}
+ /**
+ * Get the current page number string.
+ * This returns the formatted string for the current page.
+ *
+ * @return the formatted page number string
+ */
public String getCurrentPageNumber() {
return pageNumberString;
}
+ /**
+ * Resolve a reference ID.
+ * This resolves a reference ID and returns the first PageViewport
+ * that contains the reference ID or null if reference not found.
+ *
+ * @param ref the reference ID to lookup
+ * @return the first page viewport that contains the reference
+ */
public PageViewport resolveRefID(String ref) {
List list = areaTree.getIDReferences(ref);
if (list != null && list.size() > 0) {
return null;
}
+ /**
+ * Add the areas to the current page.
+ * Given the page break position this adds the areas to the current
+ * page.
+ *
+ * @param bbp the block break position
+ */
public void addAreas(BlockBreakPosition bbp) {
List list = new ArrayList();
list.add(bbp.breakps);
- bbp.getLM().addAreas( new BreakPossPosIter(list, 0,
+ bbp.getLM().addAreas(new BreakPossPosIter(list, 0,
1), null);
}
+ /**
+ * Add an ID reference to the current page.
+ * When adding areas the area adds its ID reference.
+ * For the page layout manager it adds the id reference
+ * with the current page to the area tree.
+ *
+ * @param id the ID reference to add
+ */
public void addIDToPage(String id) {
areaTree.addIDRef(id, curPage);
}
+ /**
+ * Add an unresolved area to the layout manager.
+ * The Page layout manager handles the unresolved ID
+ * reference by adding to the current page and then adding
+ * the page as a resolveable to the area tree.
+ * This is so that the area tree can resolve the reference
+ * and the page can serialize the resolvers if required.
+ *
+ * @param id the ID reference to add
+ * @param res the resolveable object that needs resolving
+ */
public void addUnresolvedArea(String id, Resolveable res) {
// add unresolved to tree
// adds to the page viewport so it can serialize
areaTree.addUnresolvedID(id, curPage);
}
+ /**
+ * Add the marker to the page layout manager.
+ *
+ * @param name the marker class name
+ * @param lm the layout manager for the marker contents
+ * @param start true if starting marker area, false for ending
+ */
public void addMarker(String name, LayoutManager lm, boolean start) {
- if(start) {
+ if (start) {
// add marker to page on area tree
} else {
// add end marker to page on area tree
}
}
+ /**
+ * Retrieve a marker from this layout manager.
+ *
+ * @param name the marker class name to lookup
+ * @param pos the position to locate the marker
+ * @param boundary the boundary for locating the marker
+ * @return the layout manager for the marker contents
+ */
public LayoutManager retrieveMarker(String name, int pos, int boundary) {
// get marker from the current markers on area tree
return null;
/**
* For now, only handle normal flow areas.
+ *
+ * @param childArea the child area to add
*/
public boolean addChild(Area childArea) {
if (childArea == null) {
return false;
}
if (childArea.getAreaClass() == Area.CLASS_NORMAL) {
- return placeFlowRefArea(childArea);
+ placeFlowRefArea(childArea);
} else {
- ; // TODO: all the others!
+ ; // todo: all the others!
}
return false;
}
* current span area. In fact the area has already been added to the
* current span, so we are just checking to see if the span is "full",
* possibly moving to the next column or to the next page.
+ *
+ * @param area the area to place
*/
- protected boolean placeFlowRefArea(Area area) {
+ protected void placeFlowRefArea(Area area) {
// assert (curSpan != null);
// assert (area == curFlow);
// assert (curFlow == curSpan.getFlow(curSpan.getColumnCount()-1));
// Consider it filled
if (curSpan.getColumnCount() == curSpanColumns) {
finishPage();
- return true;
} else
curFlow = null; // Create new flow on next getParentArea()
}*/
- return false;
}
-
protected void placeAbsoluteArea(Area area) {
}
private PageViewport makeNewPage(boolean bIsBlank, boolean bIsLast) {
finishPage();
try {
- curPage = pageSequence.createPage(pageCount, bIsBlank, bIsLast);
+ curPage = pageSequence.createPage(pageCount, bIsBlank, isFirstPage, bIsLast);
+ isFirstPage = false;
} catch (FOPException fopex) { /* ???? */
fopex.printStackTrace();
}
}
private void layoutStaticContent(Region region, int regionClass) {
- if (region != null ) {
+ if (region != null) {
StaticContent flow = pageSequence
.getStaticContent(region.getRegionName());
if (flow != null) {
RegionViewport reg = curPage.getPage()
.getRegion(regionClass);
reg.getRegion().setIPD((int)reg.getViewArea().getWidth());
- if (reg == null ) {
+ if (reg == null) {
System.out.println("no region viewport: shouldn't happen");
}
StaticContentLayoutManager lm = flow.getLayoutManager();
if (bp != null) {
ArrayList vecBreakPoss = new ArrayList();
vecBreakPoss.add(bp);
- lm.addAreas( new BreakPossPosIter(vecBreakPoss, 0,
+ lm.addAreas(new BreakPossPosIter(vecBreakPoss, 0,
vecBreakPoss.size()), null);
} else {
- System.out.println("bp==null cls="+regionClass);
+ System.out.println("bp==null cls=" + regionClass);
}
}
//lm.flush();
/**
* This is called from FlowLayoutManager when it needs to start
* a new flow container (while generating areas).
- * @param area The area for which a container is needed. It must be
+ *
+ * @param childArea The area for which a container is needed. It must be
* some kind of block-level area. It must have area-class, break-before
* and span properties set.
+ * @return the parent area
*/
public Area getParentArea(Area childArea) {
int aclass = childArea.getAreaClass();
if (aclass == Area.CLASS_NORMAL) {
- // TODO: how to get properties from the Area???
+ // todo: how to get properties from the Area???
// Need span, break
int breakVal = Constants.AUTO; // childArea.getBreakBefore();
if (breakVal != Constants.AUTO) {
createBodyMainReferenceArea();
bNeedSpan = true;
} else if (numCols != curSpanColumns) {
- // TODO: BALANCE EXISTING COLUMNS
+ // todo: BALANCE EXISTING COLUMNS
if (curSpanColumns > 1) {
// balanceColumns();
}
}
return fn;
}
- // TODO!!! other area classes (side-float, absolute, fixed)
+ // todo!!! other area classes (side-float, absolute, fixed)
return null;
}
}
-
/**
* Depending on the kind of break condition, make new column
* or page. May need to make an empty page if next page would
* not have the desired "handedness".
+ *
+ * @param breakVal the break value to handle
*/
protected void handleBreak(int breakVal) {
if (breakVal == Constants.COLUMN) {
}
}
-
/**
* If we have already started to layout content on a page,
* and there is a forced break, see if we need to generate
/**
* See if need to generate a new page for a forced break condition.
- * TODO: methods to see if the current page is empty and to get
+ * todo: methods to see if the current page is empty and to get
* its number.
*/
private boolean needNewPage(int breakValue) {
//}
}
-
private void createBodyMainReferenceArea() {
curBody.setMainReference(new MainReference());
}
}
}
+