/* * SmartDoc : Ultimate document format based on XML * Copyright (C) 1998-2003 ASAMI, Tomoharu (asami@XMLSmartDoc.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.xmlsmartdoc.SmartDoc.xhtml; import org.xmlsmartdoc.SmartDoc.AbstractXMLGeneratorBase; import org.xmlsmartdoc.SmartDoc.CSSStyle; import org.xmlsmartdoc.SmartDoc.Container; import org.xmlsmartdoc.SmartDoc.Content; import org.xmlsmartdoc.SmartDoc.Doc; import org.xmlsmartdoc.SmartDoc.Head; import org.xmlsmartdoc.SmartDoc.TOCNode; import org.xmlsmartdoc.SmartDoc.Table; import org.xmlsmartdoc.SmartDoc.Td; import org.xmlsmartdoc.SmartDoc.Th; import org.xmlsmartdoc.SmartDoc.Title; import org.xmlsmartdoc.SmartDoc.TitledBlock; import org.xmlsmartdoc.SmartDoc.TrContent; import org.xmlsmartdoc.SmartDoc.UDoc; import org.xmlsmartdoc.SmartDoc.xhtml.handler.SimpleXHTMLIndicatorHandler; import com.AsamiOffice.util.D2Array; /** * AbstractXHTMLGeneratorBase * * @since May. 7, 1999 * @version Oct. 20, 2003 * @author ASAMI, Tomoharu (asami@XMLSmartDoc.org) */ public abstract class AbstractXHTMLGeneratorBase extends AbstractXMLGeneratorBase { public static final String PREV_ID ="doc_prev_page_"; public static final String NEXT_ID ="doc_next_page_"; protected IXHTMLDynamicHandler dynamic_; protected IXHTMLIndicatorHandler indicator_; protected AbstractXHTMLGeneratorBase() { indicator_ = new SimpleXHTMLIndicatorHandler(); } protected void _setIndicatorHandler(IXHTMLIndicatorHandler handler) { indicator_ = handler; } protected void _setDynamicHandler(IXHTMLDynamicHandler handler) { dynamic_ = handler; } protected void _makeIndicatorTop( Head head, Container container, StringBuffer buffer ) { Pointer[] prevnext = _getPrevNextAsPointer(container); if (prevnext[0] != null) { StringBuffer temp = new StringBuffer(prevnext[0].prologue); temp.setCharAt(temp.length() - 1, ' '); temp.append("id=\""); temp.append(PREV_ID); temp.append("\">"); prevnext[0].prologue = new String(temp); } if (prevnext[1] != null) { StringBuffer temp = new StringBuffer(prevnext[1].prologue); temp.setCharAt(temp.length() - 1, ' '); temp.append("id=\""); temp.append(NEXT_ID); temp.append("\">"); prevnext[1].prologue = new String(temp); } if (prevnext[0] != null || prevnext[1] != null) { buffer.append( indicator_.getTopIndicator( _getPointer(container), _getPathAsPointer(container), prevnext[0], prevnext[1] ) ); } } protected void _makeIndicatorBottom( Head head, Container container, StringBuffer buffer ) { Pointer[] prevnext = _getPrevNextAsPointer(container); if (prevnext[0] != null || prevnext[1] != null) { buffer.append( indicator_.getBottomIndicator( _getPointer(container), _getPathAsPointer(container), prevnext[0], prevnext[1] ) ); } } protected void _makeTOCNodes(Container container, StringBuffer buffer) { _makeTOCNodes(container, false, buffer); } protected void _makeTOCNodes( Container container, boolean withNumber, StringBuffer buffer ) { _makeTOCNodes(container, withNumber, false, buffer); } protected void _makeTOCNodes( Container container, boolean withNumber, boolean isXhtml, StringBuffer buffer ) { TOCNode node = container.getTOCTree(); TitledBlock heading = node.getHeading(); String rootFile = getLogicalFile(container); heading = null; // XXX if (heading != null) { Title title = heading.getTitleNode(); String id = _getID(heading); String file = getLogicalFile(heading); buffer.append("<ul>\n"); buffer.append("<li> "); String link; link = file + "#" + id; // XXX if (title != null) { _embedRefTag(link, title, buffer); } else { // XXX : worning } buffer.append("\n"); _makeTOCNodes(node, rootFile, 1, withNumber, isXhtml, buffer); if (isXhtml) { buffer.append("</li>\n"); } buffer.append("</ul>\n"); } else { _makeTOCNodes(node, rootFile, 1, withNumber, isXhtml, buffer); } } protected void _makeTOCNodes( TOCNode node, String rootFile, int depth, boolean withNumber, boolean isXhtml, StringBuffer buffer ) { int size = node.getChildCount(); if (size == 0) { return; } if (dynamic_ != null && depth > 1) { String attr = dynamic_.getEvent("expandhide"); if (attr != null) { buffer.append("<ul "); buffer.append(attr); buffer.append(">"); } else { buffer.append("<ul>\n"); } } else { buffer.append("<ul>\n"); } for (int i = 0;i < size;i++) { TOCNode child = (TOCNode)node.getChildAt(i); TitledBlock heading = child.getHeading(); Title title = heading.getTitleNode(); String number; if (withNumber) { number = UDoc.getTitleNo(heading, "."); if (number != null) { number = number + " "; } else { number = ""; } } else { number = ""; } String id = _getID(heading); String file = getLogicalFile(heading); if (file.equals(rootFile)) { file = ""; } buffer.append("<li> "); String link; link = file + "#" + id; if (title != null) { _embedRefTag(link, number, title, buffer); } else { // XXX : warning } if (dynamic_ != null && child.getChildCount() > 0) { String toggle = dynamic_.getToggle(); if (toggle != null) { buffer.append(" "); buffer.append(toggle); } } buffer.append("\n"); _makeTOCNodes( child, rootFile, depth + 1, withNumber, isXhtml, buffer ); if (isXhtml) { buffer.append("</li>\n"); } } buffer.append("</ul>\n"); } protected void _embedTableData( D2Array data, Table table, StringBuffer buffer ) { int width = data.getWidth(); int height = data.getHeight(); for (int y = 0;y < height;y++) { buffer.append("<tr"); if ((y % 2) == 0) { buffer.append(" class=\"even\""); } else { buffer.append(" class=\"odd\""); } buffer.append(">\n"); for (int x = 0;x < width;x++) { TrContent content = (TrContent)data.get(x, y); if (content == null) { continue; } String tag; if (content instanceof Th) { tag = "th"; } else if (content instanceof Td) { tag = "td"; } else { throw (new InternalError()); } String clazz = _getCellClass(content, table, x, y); CSSStyle style = _getCellStyle(content, table, x, y); int rowspan = content.getRowSpan(); int colspan = content.getColSpan(); String align = _getCellAlign(content, table, x, y); buffer.append("<"); buffer.append(tag); if (clazz != null) { buffer.append(" class=\""); buffer.append(clazz); buffer.append("\""); } if (style != null) { _embedAttr("style", style.getText(), buffer); } if (rowspan != 1) { _embedAttr("rowspan", rowspan, buffer); } if (colspan != 1) { _embedAttr("colspan", colspan, buffer); } if (align != null) { _embedAttr("align", align, buffer); } buffer.append(">"); _makeString(content, buffer); buffer.append("</"); buffer.append(tag); buffer.append(">\n"); } buffer.append("</tr>\n"); } } protected String _getCellClass( TrContent cell, Table table, int x, int y ) { String clazz = cell.getClazz(); if (clazz != null) { return (clazz); } if (table != null) { return (table.getClazz(x, y)); } else { return (null); } } protected CSSStyle _getCellStyle( TrContent cell, Table table, int x, int y ) { return (cell.getStyle()); } protected String _getCellAlign( TrContent cell, Table table, int x, int y ) { return (cell.getAlign()); } protected void _embedRefTag( String href, String content, StringBuffer buffer ) { _embedRefTagPrologue(href, buffer); buffer.append(_escape(content)); _embedRefTagEpilogue(buffer); } protected void _embedRefTag( String href, Content content, StringBuffer buffer ) { _embedRefTagPrologue(href, content, buffer); _makeString(content, buffer); _embedRefTagEpilogue(buffer); } protected void _embedRefTag( String href, String prefix, Content content, StringBuffer buffer ) { _embedRefTagPrologue(href, content, buffer); buffer.append(prefix); _makeString(content, buffer); _embedRefTagEpilogue(buffer); } protected void _embedRefTagPrologue(String href, StringBuffer buffer) { String type; if (href.charAt(0) == '#') { type = "selflink"; } else if (href.startsWith("http:")) { type = "externallink"; } else { type = "hyperlink"; } buffer.append("<a href=\""); buffer.append(_escape(href)); buffer.append("\""); if (type.equals("externallink")){ _embedRefTagPrologueExternalLinkAttributes(href, buffer); } if (dynamic_ != null) { String script = dynamic_.getEvent(type); if (script != null) { buffer.append(" "); buffer.append(script); } } buffer.append(">"); } protected void _embedRefTagPrologue( String href, Content content, StringBuffer buffer ) { String type; if (href.charAt(0) == '#') { type = "selflink"; } else if (href.startsWith("http:")) { type = "externallink"; } else { type = "hyperlink"; } _embedTagPrologue("a", content, buffer); buffer.deleteCharAt(buffer.length() - 1); buffer.append(" href=\""); buffer.append(_escape(href)); buffer.append("\""); if (type.equals("externallink")){ _embedRefTagPrologueExternalLinkAttributes(href, buffer); } if (dynamic_ != null) { String script = dynamic_.getEvent(type); if (script != null) { buffer.append(" "); buffer.append(script); } } buffer.append(">"); } protected void _embedRefTagPrologueExternalLinkAttributes( String href, StringBuffer buffer ) { buffer.append(" target=\"_top\""); } protected void _embedRefTagEpilogue(StringBuffer buffer) { buffer.append("</a>"); } protected Pointer _getPointer(Content content) { Pointer pointer = new Pointer(); pointer.content = content; String file = getLogicalFile(content); String link; if (content instanceof Doc) { // XXX : more generic Doc doc = (Doc)content; Head head = doc.getHead(); pointer.title = ""; if (head != null) { Title title = head.getDocTitle(); if (title != null) { pointer.title = title.getText(); } } link = file; } else { pointer.title = content.getTitle(); link = file + "#" + _getID(content); } StringBuffer buffer = new StringBuffer(); _embedRefTagPrologue(link, buffer); pointer.prologue = new String(buffer); buffer = new StringBuffer(); _embedRefTagEpilogue(buffer); pointer.epilogue = new String(buffer); return (pointer); } protected Pointer _getPointerFile(Content content) { Pointer pointer = new Pointer(); pointer.content = content; String link = getLogicalFile(content); StringBuffer buffer = new StringBuffer(); _embedRefTagPrologue(link, buffer); pointer.prologue = new String(buffer); buffer = new StringBuffer(); _embedRefTagEpilogue(buffer); pointer.epilogue = new String(buffer); return (pointer); } protected Pointer[] _getPathAsPointer(Content content) { Doc doc = (Doc)UDoc.getRoot(content); TitledBlock[] path = UDoc.getHeadingPath(content); Pointer[] pointers = new Pointer[path.length + 1]; pointers[0] = _getPointer(doc); for (int i = 0;i < path.length;i++) { pointers[i + 1] = _getPointer(path[i]); } return (pointers); } protected Pointer[] _getPrevNextAsPointer(Content content) { Content[] pair = _getPrevNext(content); Pointer[] pointers = new Pointer[2]; if (pair[0] != null) { pointers[0] = _getPointerFile(pair[0]); } if (pair[1] != null) { pointers[1] = _getPointerFile(pair[1]); } return (pointers); } protected Content[] _getPrevNext(Content content) { Doc doc = (Doc)UDoc.getRoot(content); TitledBlock[] headings = UDoc.getHeadings(doc); if (headings.length == 0) { return (new Content[] { null, null } ); } String currentFile = getLogicalFile(content); String rootFile = getLogicalFile(doc); String prevFile = null; String nextFile = null; Content prev = null; Content next = null; for (int i = 0;i < headings.length;i++) { if (headings[i] == content) { if (i > 0) { for (int j = i - 1;j >= 0;j--) { prevFile = getLogicalFile(headings[j]); if (!prevFile.equals(currentFile)) { prev = headings[j]; break; } } if (prevFile.equals(currentFile)) { prevFile = rootFile; prev = doc; } } else { prevFile = rootFile; prev = doc; } if (i < headings.length - 1) { for (int j = i + 1;j < headings.length;j++) { nextFile = getLogicalFile(headings[j]); if (!nextFile.equals(currentFile)) { next = headings[j]; break; } } if (nextFile.equals(currentFile)){ nextFile = null; next = null; } } break; } } if (prevFile == null && nextFile == null) { nextFile = getLogicalFile(headings[0]); next = headings[0]; } return (new Content[] { prev, next }); } }