123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- /*
- * $Id$
- * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
- * For details on use and redistribution please refer to the
- * LICENSE file included with these sources.
- */
-
- package org.apache.fop.fo;
-
- // FOP
- import org.apache.fop.layout.AreaClass;
- import org.apache.fop.apps.FOPException;
- import org.apache.fop.apps.StructureHandler;
- import org.apache.fop.layoutmgr.LayoutManager;
- import org.apache.fop.fo.properties.FOPropertyMapping;
- import org.apache.fop.fo.flow.Marker;
-
- // Java
- import java.util.Iterator;
- import org.xml.sax.Attributes;
-
- import java.util.Iterator;
- import java.util.ListIterator;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.HashMap;
- import java.util.HashSet;
-
- /**
- * base class for representation of formatting objects and their processing
- */
- public class FObj extends FONode {
- protected StructureHandler structHandler;
- public PropertyList properties;
- protected PropertyManager propMgr;
- protected String areaClass = AreaClass.UNASSIGNED;
- protected String id = null;
-
- /**
- * value of marker before layout begins
- */
- public final static int START = -1000;
-
- /**
- * value of marker after break-after
- */
- public final static int BREAK_AFTER = -1001;
-
- /**
- * where the layout was up to.
- * for FObjs it is the child number
- * for FOText it is the character number
- */
- protected int marker = START;
-
- protected ArrayList children = new ArrayList(); // made public for searching for id's
-
- protected boolean isInTableCell = false;
-
- protected int forcedStartOffset = 0;
- protected int forcedWidth = 0;
-
- protected int widows = 0;
- protected int orphans = 0;
-
- // count of areas generated-by/returned-by
- public int areasGenerated = 0;
-
- // markers
- protected HashMap markers;
-
- public FObj(FONode parent) {
- super(parent);
- markers = new HashMap();
- if (parent instanceof FObj)
- this.areaClass = ((FObj) parent).areaClass;
- }
-
- public void setName(String str) {
- name = "fo:" + str;
- }
-
- protected static PropertyListBuilder plb = null;
-
- protected PropertyListBuilder getListBuilder() {
- if (plb == null) {
- plb = new PropertyListBuilder();
- plb.addList(FOPropertyMapping.getGenericMappings());
-
- for (Iterator iter =
- FOPropertyMapping.getElementMappings().iterator();
- iter.hasNext();) {
- String elem = (String) iter.next();
- plb.addElementList(elem,
- FOPropertyMapping.getElementMapping(elem));
- }
- }
- return plb;
- }
-
- /**
- * Handle the attributes for this element.
- * The attributes must be used immediately as the sax attributes
- * will be altered for the next element.
- */
- public void handleAttrs(Attributes attlist) throws FOPException {
- String uri = "http://www.w3.org/1999/XSL/Format";
- FONode par = parent;
- while (par != null && !(par instanceof FObj)) {
- par = par.parent;
- }
- PropertyList props = null;
- if (par != null) {
- props = ((FObj) par).properties;
- }
- properties = getListBuilder().makeList(uri, name, attlist, props,
- (FObj) par);
- properties.setFObj(this);
- this.propMgr = makePropertyManager(properties);
- setWritingMode();
- }
-
- protected PropertyManager makePropertyManager(
- PropertyList propertyList) {
- return new PropertyManager(propertyList);
- }
-
- protected void addChild(FONode child) {
- children.add(child);
- }
-
- public void setStructHandler(StructureHandler st) {
- structHandler = st;
- }
-
- /**
- * lets outside sources access the property list
- * first used by PageNumberCitation to find the "id" property
- * @param name - the name of the desired property to obtain
- * @return the property
- */
- public Property getProperty(String name) {
- return (properties.get(name));
- }
-
- protected void setupID() {
- Property prop = this.properties.get("id");
- if(prop != null) {
- String str = prop.getString();
- if(str != null && !str.equals("")) {
- HashSet idrefs = structHandler.getIDReferences();
- if(!idrefs.contains(str)) {
- id = str;
- idrefs.add(id);
- } else {
- getLogger().warn("duplicate id:" + str + " ignored");
- }
- }
- }
- }
-
- /**
- * Return the "content width" of the areas generated by this FO.
- * This is used by percent-based properties to get the dimension of
- * the containing block.
- * If an FO has a property with a percentage value, that value
- * is usually calculated on the basis of the corresponding dimension
- * of the area which contains areas generated by the FO.
- * NOTE: subclasses of FObj should implement this to return a reasonable
- * value!
- */
- public int getContentWidth() {
- return 0;
- }
-
- public boolean generatesReferenceAreas() {
- return false;
- }
-
-
- public boolean generatesInlineAreas() {
- return true;
- }
-
- /**
- * Set writing mode for this FO.
- * Find nearest ancestor, including self, which generates
- * reference areas and use the value of its writing-mode property.
- * If no such ancestor is found, use the value on the root FO.
- */
- protected void setWritingMode() {
- FObj p;
- FONode parent;
- for (p = this; !p.generatesReferenceAreas() &&
- (parent = p.getParent()) != null &&
- (parent instanceof FObj); p = (FObj) parent)
- ;
- this.properties.setWritingMode(
- p.getProperty("writing-mode").getEnum());
- }
-
- /**
- * Return a LayoutManager responsible for laying out this FObj's content.
- * Must override in subclasses if their content can be laid out.
- */
- public void addLayoutManager(List list) {
- }
-
- /**
- * Return an iterator over all the children of this FObj.
- * @return A ListIterator.
- */
- public ListIterator getChildren() {
- return children.listIterator();
- }
-
- /**
- * Return an iterator over the object's children starting
- * at the pased node.
- * @param childNode First node in the iterator
- * @return A ListIterator or null if childNode isn't a child of
- * this FObj.
- */
- public ListIterator getChildren(FONode childNode) {
- int i = children.indexOf(childNode);
- if (i >= 0) {
- return children.listIterator(i);
- } else
- return null;
- }
-
- public void setIsInTableCell() {
- this.isInTableCell = true;
- // made recursive by Eric Schaeffer
- for (int i = 0; i < this.children.size(); i++) {
- Object obj = this.children.get(i);
- if (obj instanceof FObj) {
- FObj child = (FObj) obj;
- child.setIsInTableCell();
- }
- }
- }
-
- public void forceStartOffset(int offset) {
- this.forcedStartOffset = offset;
- // made recursive by Eric Schaeffer
- for (int i = 0; i < this.children.size(); i++) {
- Object obj = this.children.get(i);
- if (obj instanceof FObj) {
- FObj child = (FObj) obj;
- child.forceStartOffset(offset);
- }
- }
- }
-
- public void forceWidth(int width) {
- this.forcedWidth = width;
- // made recursive by Eric Schaeffer
- for (int i = 0; i < this.children.size(); i++) {
- Object obj = this.children.get(i);
- if (obj instanceof FObj) {
- FObj child = (FObj) obj;
- child.forceWidth(width);
- }
- }
- }
-
- public void resetMarker() {
- this.marker = START;
- int numChildren = this.children.size();
- for (int i = 0; i < numChildren; i++) {
- Object obj = this.children.get(i);
- if (obj instanceof FObj) {
- FObj child = (FObj) obj;
- child.resetMarker();
- }
- }
- }
-
- public void setWidows(int wid) {
- widows = wid;
- }
-
- public void setOrphans(int orph) {
- orphans = orph;
- }
-
- public void removeAreas() {
- // still to do
- }
-
- /**
- * At the start of a new span area layout may be partway through a
- * nested FO, and balancing requires rollback to this known point.
- * The snapshot records exactly where layout is at.
- * @param snapshot a ArrayList of markers (Integer)
- * @returns the updated ArrayList of markers (Integers)
- */
- public ArrayList getMarkerSnapshot(ArrayList snapshot) {
- snapshot.add(new Integer(this.marker));
-
- // terminate if no kids or child not yet accessed
- if (this.marker < 0)
- return snapshot;
- else if (children.isEmpty())
- return snapshot;
- else
- return ( (FObj) children.get(this.marker)).getMarkerSnapshot(
- snapshot);
- }
-
- /**
- * When balancing occurs, the flow layout() method restarts at the
- * point specified by the current marker snapshot, which is retrieved
- * and restored using this method.
- * @param snapshot the ArrayList of saved markers (Integers)
- */
- public void rollback(ArrayList snapshot) {
- this.marker = ((Integer) snapshot.get(0)).intValue();
- snapshot.remove(0);
-
- if (this.marker == START) {
- // make sure all the children of this FO are also reset
- resetMarker();
- return;
- } else if ((this.marker == -1) || children.isEmpty())
- return;
-
- int numChildren = this.children.size();
-
- if (this.marker <= START) {
- return;
- }
-
- for (int i = this.marker + 1; i < numChildren; i++) {
- Object obj = this.children.get(i);
- if (obj instanceof FObj) {
- FObj child = (FObj) obj;
- child.resetMarker();
- }
- }
- ((FObj) children.get(this.marker)).rollback(snapshot);
- }
-
-
- public void addMarker(Marker marker) throws FOPException {
- String mcname = marker.getMarkerClassName();
- if (!markers.containsKey(mcname) && children.isEmpty()) {
- markers.put(mcname, marker);
- } else {
- getLogger().error("fo:marker must be an initial child," + "and 'marker-class-name' must be unique for same parent");
- throw new FOPException(
- "fo:marker must be an initial child," + "and 'marker-class-name' must be unique for same parent");
- }
- }
-
- public boolean hasMarkers() {
- return !markers.isEmpty();
- }
-
- public ArrayList getMarkers() {
- return new ArrayList(markers.values());
- }
-
- /**
- * lets layout managers access FO properties via PropertyManager
- * @return the property manager for this FO
- */
- public PropertyManager getPropertyManager() {
- return this.propMgr;
- }
-
- }
|