/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ package org.openoffice.xmerge.converter.xml.sxc; import org.w3c.dom.NodeList; import org.w3c.dom.Node; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Element; import org.openoffice.xmerge.converter.xml.Style; import org.openoffice.xmerge.converter.xml.StyleCatalog; import org.openoffice.xmerge.util.Debug; import org.openoffice.xmerge.util.TwipsConverter; /** * Represents a text Style in an OpenOffice document. * * @author Martin Maher */ public class RowStyle extends Style implements Cloneable { private int rowHeight = 255; /** * Constructor for use when going from DOM to client device format. * * @param node The style:style Node containing * the Style. (This Node is * assumed have a family attribute of text). * @param sc The StyleCatalog, which is used for * looking up ancestor Style objects. */ public RowStyle(Node node, StyleCatalog sc) { super(node, sc); // Run through the attributes of this node, saving // the ones we're interested in. NamedNodeMap attrNodes = node.getAttributes(); if (attrNodes != null) { int len = attrNodes.getLength(); for (int i = 0; i < len; i++) { Node attr = attrNodes.item(i); handleAttribute(attr.getNodeName(), attr.getNodeValue()); } } // Look for children. Only ones we care about are "style:properties" // nodes. If any are found, recursively traverse them, passing // along the style element to add properties to. if (node.hasChildNodes()) { NodeList children = node.getChildNodes(); int len = children.getLength(); for (int i = 0; i < len; i++) { Node child = children.item(i); String name = child.getNodeName(); if (name.equals("style:properties")) { NamedNodeMap childAttrNodes = child.getAttributes(); if (childAttrNodes != null) { int nChildAttrNodes = childAttrNodes.getLength(); for (int j = 0; j < nChildAttrNodes; j++) { Node attr = childAttrNodes.item(j); handleAttribute(attr.getNodeName(), attr.getNodeValue()); } } } } } } /** * Constructor for use when going from client device format to DOM * * @param name Name of text Style. Can be null. * @param family Family of text Style (usually * text). Can be null. * @param parent Name of parent text Style, or null * for none. * @param rowHeight The height of this row * @param sc The StyleCatalog, which is used for * looking up ancestor Style objects. */ public RowStyle(String name, String family, String parent,int rowHeight, StyleCatalog sc) { super(name, family, parent, sc); this.rowHeight=rowHeight; } /** * Returns the height of this row * * @return the Format object */ public int getRowHeight() { return rowHeight; } /** * Sets the height of this row * * @param rowHeight the row height */ public void setRowHeight(int rowHeight) { this.rowHeight = rowHeight; } /** * Parse a colheight in the form "1.234cm" to twips * * @param value String specification to parse. * * @return The twips equivalent. */ private int parseRowHeight(String value) { int height = 255; // Default value if(value.indexOf("cm")!=-1) { float heightCM = Float.parseFloat(value.substring(0,value.indexOf("c"))); height = TwipsConverter.cm2twips(heightCM); } else if(value.indexOf("inch")!=-1) { float heightInch = Float.parseFloat(value.substring(0,value.indexOf("i"))); height = TwipsConverter.inches2twips(heightInch); } return (height); } /** * Set an attribute. * * @param attr The attribute to set. * @param value The attribute value to set. */ private void handleAttribute(String attr, String value) { if (attr.equals("style:row-height")) { rowHeight = parseRowHeight(value); } else { Debug.log(Debug.INFO, "RowStyle Unhandled: " + attr + "=" + value); } } /** * Return a Style object corresponding to this one, * but with all of the inherited information from parent * Style objects filled in. The object returned will * be a new object, not a reference to this object, even if it does * not need any information added. * * @return The StyleCatalog in which to look up * ancestors. */ public Style getResolved() { // Create a new object to return, which is a clone of this one. RowStyle resolved = null; try { resolved = (RowStyle)this.clone(); } catch (Exception e) { Debug.log(Debug.ERROR, "Can't clone", e); } // Look up the parentStyle. (If there is no style catalog // specified, we can't do any lookups.) RowStyle parentStyle = null; if (sc != null) { if (parent != null) { parentStyle = (RowStyle)sc.lookup(parent, family, null, this.getClass()); if (parentStyle == null) Debug.log(Debug.ERROR, "parent style lookup of " + parent + " failed!"); else parentStyle = (RowStyle)parentStyle.getResolved(); } else if (!name.equals("DEFAULT_STYLE")) { parentStyle = (RowStyle)sc.lookup("DEFAULT_STYLE", null, null, this.getClass()); } } // If we found a parent, for any attributes which we don't have // set, try to get the values from the parent. if (parentStyle != null) { parentStyle = (RowStyle)parentStyle.getResolved(); if ((rowHeight == 0) && (parentStyle.getRowHeight() != 0)) resolved.setRowHeight(parentStyle.getRowHeight()); } return resolved; } /** * Create a new Node in the Document, and * write this Style to it. * * @param parentDoc Parent Document of the * Node to create. * @param name Name to use for the new Node (e.g. * style:style) * * @return Created Node. */ public Node createNode(org.w3c.dom.Document parentDoc, String name) { Element node = parentDoc.createElement(name); writeAttributes(node); return node; } /** * Return true if style specifies as much or less * than this Style, and nothing it specifies * contradicts this Style. * * @param style The Style to check. * * @return true if style is a subset, false * otherwise. */ public boolean isSubset(Style style) { if (style.getClass() != this.getClass()) return false; RowStyle tStyle = (RowStyle)style; if(rowHeight!=tStyle.getRowHeight()) return false; return true; } /** * Write this Style object's attributes to a * Node in the Document. * * @param node The Node to add Style * attributes. */ public void writeAttributes(Element node) { if(rowHeight!=0) { String height = TwipsConverter.twips2cm(rowHeight) + "cm"; node.setAttribute("style:row-height", height); } } private static String[] ignored = { "fo:break-before", "fo:keep-with-next" }; /* * This code checks whether an attribute is one that we * intentionally ignore. * * @param attribute The attribute to check. * * @return true if attribute can be ignored, * otherwise false. */ private boolean isIgnored(String attribute) { for (int i = 0; i < ignored.length; i++) { if (ignored[i].equals(attribute)) return true; } return false; } }