Esempio n. 1
0
  public Document nextTableRow(String atts) {

    // peek at current cell - stay with it IF
    //  + it's the first cell in the row
    //  + the current cursor points at the first child (a block)
    //  + the block pointed by cursor is empty
    Element cell = peek("table-cell", "nextTableRow() is not applicable outside enclosing table");
    if (cell.getPreviousSibling() == null
        && cursor == cell.getFirstChild()
        && !cursor.hasChildNodes()) {
      attributes((Element) cell.getParentNode(), atts);
      return this;
    }

    // pop to table
    pop("table", "nextTableRow() is not applicable outside enclosing table");
    Element table = cursor;

    // last child is already table-body?
    if (table.getLastChild().getNodeName().equals("table-body")) {
      cursor = (Element) table.getLastChild();
    } else {
      push("table-body");
    }

    // add row
    push("table-row", atts);

    // add cell
    push("table-cell", "border=" + table.getAttribute("border"));
    push("block");

    // done
    return this;
  }
Esempio n. 2
0
  /** Add a list item */
  public Document nextListItem(String format) {

    // <list-block>
    //  <list-item>
    //    <list-item-label end-indent="label-end()"><block>&#x2022;</block></list-item-label>
    //    <list-item-body start-indent="body-start()">
    //       <block/>
    //    </list-item-body>
    //  </list-item>

    // check containing list-block
    Element list = peek("list-block", "nextListItem() is not applicable outside list block");

    // a list with only one item containing an empty block?
    if (list.getChildNodes().getLength() == 1
        && cursor.getFirstChild() == null
        && cursor.getPreviousSibling() == null
        && cursor.getParentNode().getLocalName().equals("list-item-body")) {
      // delete list-item and start over
      list.removeChild(list.getFirstChild());
    }

    // continue with list
    cursor = list;

    // find out what 'bullet' to use
    String label = attribute("genj:label", format);
    if (label != null) {
      // check provisional-distance-between-starts - we assume a certain 'em' per label character
      String dist = list.getAttribute("provisional-distance-between-starts");
      if (dist.endsWith("em")) {
        float len = label.length() * 0.6F;
        if (Float.parseFloat(dist.substring(0, dist.length() - 2)) < len)
          list.setAttribute("provisional-distance-between-starts", len + "em");
      }
    } else {
      label = "\u2219"; // &bullet; /u2219 works in JEditPane, &bull; \u2022 doesn't
    }

    // add new item
    push("list-item");
    push("list-item-label", "end-indent=label-end()");
    push("block");
    text(label, "");
    pop();
    pop();
    push("list-item-body", "start-indent=body-start()");
    push("block");

    return this;
  }
Esempio n. 3
0
  /** Add a link */
  public Document addLink(String text, String id) {

    // <basic-link>text</basic-link>
    push("basic-link", "internal-destination=" + id);
    text(text, "");
    pop();
    // done
    return this;
  }
Esempio n. 4
0
  /** End a list */
  public Document endList() {

    // *
    //  <list-block>
    pop("list-block", "endList() is not applicable outside list-block").pop();
    push("block", "");

    return this;
  }
Esempio n. 5
0
  public Document nextTableCell(String atts) {

    // peek at current cell - stay with it IF
    //  + it's the first cell in the row
    //  + the current cursor points at the first child (a block)
    //  + the block pointed by cursor is empty
    Element cell = peek("table-cell", "nextTableCell() is not applicable outside enclosing table");
    if (cell.getPreviousSibling() == null
        && cursor == cell.getFirstChild()
        && !cursor.hasChildNodes()) {
      attributes(cell, atts);
      // add empty content to block so another call to nextTableCell() willl actually move forward
      push("inline", "").pop();
      return this;
    }

    // peek at row
    Element row =
        peek("table-row", "nextTableCell() is not applicable outside enclosing table row");
    int cells = row.getElementsByTagName("table-cell").getLength();

    // peek at table - add new row if we have all columns already
    Element table = peek("table", "nextTableCell() is not applicable outside enclosing table");
    int cols = table.getElementsByTagName("table-column").getLength();
    if (cols > 0 && cells == cols) return nextTableRow();

    // pop to row
    pop("table-row", "nextTableCell() is not applicable outside enclosing table row");

    // 20060215 wanted to use border=inherit here but that would require table-row
    // and table-body to have border=inherit as well. table-body can't have a
    // border property in a table with border-collapse=separate (which is the only
    // model FOP supports).
    // So we're simply doing our own 'inherit' here :) Alternative would be to do
    // us border=from-nearest-specified-value() on each cell or border=inherit
    // on the table-columns and then border=from-table-column() on the cells.

    // add now
    push("table-cell", "border=" + table.getAttribute("border") + "," + atts);
    push("block");

    // done
    return this;
  }
Esempio n. 6
0
  /** Add Table of content */
  private Document toc() {

    // anything to do?
    if (toc.isEmpty()) return this;
    Element old = cursor;

    // pop back to flow
    pop("flow", "can't create TOC without enclosing flow");

    // add block for toc AS FIRST child
    push("block", "", cursor.getFirstChild());

    // <block>
    //  Table of Contents
    //  <block>
    //    Title 1<leader/><page-number-citation/>
    //   </block>
    //   ...
    // </block>

    // add toc header
    push("block", formatSectionLarger);
    text(RESOURCES.getString("toc"), "");
    pop();

    // add toc entries
    for (Iterator it = toc.iterator(); it.hasNext(); ) {
      push(
          "block",
          "start-indent=1cm,end-indent=1cm,text-indent=0cm,text-align-last=justify,text-align=justify");
      TOCEntry entry = (TOCEntry) it.next();
      addLink(entry.text, entry.id);
      push("leader", "leader-pattern=dots").pop();
      push("page-number-citation", "ref-id=" + entry.id).pop();

      pop();
    }

    // done
    cursor = old;
    return this;
  }
Esempio n. 7
0
  /** Start a list */
  public Document startList(String format) {

    // <list-block>
    pop();
    push(
        "list-block",
        "provisional-distance-between-starts=0.6em, provisional-label-separation=0pt," + format);
    nextListItem();

    return this;
  }
Esempio n. 8
0
  /** Add text element */
  private Document text(String text, String atts) {

    // ignore empties
    if (text.length() == 0) return this;

    // create a text node for it
    Node txt = doc.createTextNode(text);
    if (atts.length() > 0) {
      push("inline", atts);
      cursor.appendChild(txt);
      pop();
    } else {
      cursor.appendChild(txt);
    }
    return this;
  }
Esempio n. 9
0
  public Document startTable(String format) {

    // patch format - FOP only supports table-layout=fixed
    format = "table-layout=fixed," + format;

    // <table>
    // <table-header>
    //  <table-row>
    //   <table-cell>
    //    <block>
    //    ...
    // </table-header>
    // <table-body>
    //  <table-row>
    //   <table-cell>
    //    <block>
    //    ...
    push("table", format);
    Element table = cursor;

    // mark as cvs if applicable - non fo namespace attributes won't be picked up by push() and
    // attributes()
    if ("true".equals(attribute("genj:csv", format))) {
      containsCSV = true;
      cursor.setAttributeNS(NS_GENJ, "genj:csv", "true");

      String prefix = attribute("genj:csvprefix", format);
      if (prefix != null) cursor.setAttributeNS(NS_GENJ, "genj:csvprefix", prefix);
    }

    // head/body & row
    if (format.indexOf("genj:header=true") >= 0) {
      push("table-header");
      push("table-row", "color=#ffffff,background-color=#c0c0c0,font-weight=bold");
    } else {
      push("table-body");
      push("table-row");
    }

    // cell and done
    push("table-cell", "border=" + table.getAttribute("border"));
    push("block");

    return this;
  }
Esempio n. 10
0
  /** Add a column to the table (this is not necessary) */
  public Document addTableColumn(String atts) {

    // <table>
    // <table-column/>
    Element save = cursor;

    // find the enclosing table
    pop("table", "addTableColumn() is not applicable outside enclosing table");

    // find last table definition
    Node before = cursor.getFirstChild();
    while (before != null && before.getNodeName().equals("table-column"))
      before = before.getNextSibling();

    push("table-column", atts, before);

    // done for now
    cursor = save;

    return this;
  }
Esempio n. 11
0
  /**
   * Add image file reference to the document
   *
   * @param file the file pointing to the image
   * @param atts fo attributes for the image
   */
  public Document addImage(File file, String atts) {

    // anything we care about?
    if (file == null || !file.exists()) return this;

    // check dimension - let's not make this bigger than 1x1 inch
    Dimension2D dim = new ImageSniffer(file).getDimensionInInches();
    if (dim == null) return this;
    if (dim.getWidth() > dim.getHeight()) {
      if (dim.getWidth() > 1)
        atts = "width=1in,content-width=scale-to-fit," + atts; // can be overriden
    } else {
      if (dim.getHeight() > 1)
        atts = "height=1in,content-height=scale-to-fit," + atts; // can be overriden
    }

    //  <fo:external-graphic src="file"/>
    push("external-graphic", "src=" + file.getAbsolutePath() + "," + atts);

    // remember file in case a formatter wants to resolve file location later
    List elements = (List) file2elements.get(file);
    if (elements == null) {
      elements = new ArrayList(3);
      file2elements.put(file, elements);
    }
    elements.add(cursor);

    // back to enclosing block
    pop();

    // add opportunity to line break
    addText(" ");

    // done
    return this;
  }
Esempio n. 12
0
  /** Add indexes */
  private Document indexes() {

    // loop over indexes
    for (Iterator indexes = index2primary2secondary2elements.keySet().iterator();
        indexes.hasNext(); ) {

      String index = (String) indexes.next();
      Map primary2secondary2elements = (Map) index2primary2secondary2elements.get(index);

      // add section
      nextPage();
      startSection(index);
      push("block", "start-indent=1cm");

      // loop over primaries
      for (Iterator primaries = primary2secondary2elements.keySet().iterator();
          primaries.hasNext(); ) {

        String primary = (String) primaries.next();
        Map secondary2elements = (Map) primary2secondary2elements.get(primary);

        // add block and primary
        push("block", "");
        text(primary + " ", "");

        // loop over secondaries
        for (Iterator secondaries = secondary2elements.keySet().iterator();
            secondaries.hasNext(); ) {

          String secondary = (String) secondaries.next();
          List elements = (List) secondary2elements.get(secondary);

          if (secondary.length() > 0) {
            push("block", "start-indent=2cm"); // start-indent?
            text(secondary + " ", "");
          }

          // loop over elements
          for (int e = 0; e < elements.size(); e++) {
            if (e > 0) text(", ", "");
            Element element = (Element) elements.get(e);
            String id = element.getAttribute("id");

            push("basic-link", "internal-destination=" + id);
            push("page-number-citation", "ref-id=" + id);
            cursor.setAttributeNS(NS_GENJ, "genj:citation", Integer.toString(e + 1));
            pop();
            pop();
          }

          if (secondary.length() > 0) pop();
          // next
        }

        // next
        pop();
      }

      // next
      pop();
    }

    // done
    return this;
  }
Esempio n. 13
0
 /** Force a page break */
 public Document nextPage() {
   pop();
   push("block", "page-break-before=always");
   return this;
 }
Esempio n. 14
0
  /** Constructor */
  public Document(String title) {

    // remember title
    this.title = title;

    // section size range
    setSectionSizes(FONT_MEDIUM, FONT_XX_LARGE);
    // create a dom document
    try {
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      doc = dbf.newDocumentBuilder().newDocument();
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }

    // boilerplate
    //  <root>
    //   <layout-master-set>
    //    <simple-page-master>
    //     <region-body/>
    //     <region-end/>
    //    </simple-page-master>
    //   </layout-master-set>
    //   <page-sequence>
    //    <title>
    //    <flow>
    //     <block/>
    //    </flow>
    //   </page-sequence>
    cursor = (Element) doc.appendChild(doc.createElementNS(NS_XSLFO, "root"));
    cursor.setAttribute("xmlns", NS_XSLFO);
    cursor.setAttribute("xmlns:genj", NS_GENJ);

    // FOP crashes when a title element is present so we use an extension to pass it to our fo2html
    // stylesheet
    // @see http://issues.apache.org/bugzilla/show_bug.cgi?id=38710
    cursor.setAttributeNS(NS_GENJ, "genj:title", title);

    push("layout-master-set");
    // Tip: see also http://www.dpawson.co.uk/xsl/sect3/N8565.html for a minimal page master.
    push(
        "simple-page-master",
        "master-name=master,margin-top=1cm,margin-bottom=1cm,margin-left=1cm,margin-right=1cm");
    push("region-body", "margin-bottom=1cm").pop();
    push("region-after", "extent=0.8cm").pop();
    pop().pop().push("page-sequence", "master-reference=master");

    /*
          Paul Grosso offers this suggestion for left-center-right header formatting
          at http://www.dpawson.co.uk/xsl/sect3/headers.html#d13432e123:

          <fo:static-content flow-name="xsl-region-before">
        <!-- header-width is the width of the full header in picas -->
        <xsl:variable name="header-width" select="36"/>
        <xsl:variable name="header-field-width">
        <xsl:value-of
    select="$header-width * 0.3333"/><xsl:text>pc</xsl:text>
        </xsl:variable>
        <fo:list-block font-size="8pt" provisional-label-separation="0pt">
            <xsl:attribute name="provisional-distance-between-starts">
                <xsl:value-of select="$header-field-width"/>
            </xsl:attribute>
            <fo:list-item>
                <fo:list-item-label end-indent="label-end()">
                    <fo:block text-align="left">
                        <xsl:text>The left header field</xsl:text>
                    </fo:block>
                </fo:list-item-label>
                <fo:list-item-body start-indent="body-start()">
                    <fo:list-block provisional-label-separation="0pt">
                        <xsl:attribute
                     name="provisional-distance-between-starts">
                            <xsl:value-of select="$header-field-width"/>
                        </xsl:attribute>
                        <fo:list-item>
                            <fo:list-item-label end-indent="label-end()">
                                <fo:block text-align="center">
                                    <fo:page-number/>
                                </fo:block>
                            </fo:list-item-label>
                            <fo:list-item-body start-indent="body-start()">
                                <fo:block text-align="right">
                        <xsl:text>The right header field</xsl:text>
                                </fo:block>
                            </fo:list-item-body>
                        </fo:list-item>
                    </fo:list-block>
                </fo:list-item-body>
            </fo:list-item>
        </fo:list-block>
    </fo:static-content>
        */
    push("static-content", "flow-name=xsl-region-after");
    push("block", "text-align=center");
    // text("p. ", ""); // todo bk better w/o text, to avoid language-dependency, but with title
    push("page-number").pop();
    pop(); // </block>
    pop(); // </static-content>

    // don't use title - see above
    // push("title").text(getTitle(), "").pop();

    push("flow", "flow-name=xsl-region-body");
    push("block");

    // done - cursor points to first block
  }