/************************************************************** * * 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 ColumnStyle extends Style implements Cloneable { private int colWidth = 0; /** * 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 ColumnStyle(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 colWidth the width of this column * @param sc The StyleCatalog, which is used for * looking up ancestor Style objects. */ public ColumnStyle(String name, String family, String parent,int colWidth, StyleCatalog sc) { super(name, family, parent, sc); this.colWidth = colWidth; } /** * Returns the width of this column * * @return the Format object */ public int getColWidth() { return colWidth; } /** * Sets the width of this column * * @param colWidth the column width */ public void setColWidth(int colWidth) { this.colWidth = colWidth; } /** * Parse a colwidth in the form "1.234cm" to twips * * @param value String specification to parse. * * @return The twips equivalent. */ private int parseColWidth(String value) { int width = 255; // Default value if(value.indexOf("cm")!=-1) { float widthCM = Float.parseFloat(value.substring(0,value.indexOf("c"))); width = TwipsConverter.cm2twips(widthCM); } else if(value.indexOf("inch")!=-1) { float widthInch = Float.parseFloat(value.substring(0,value.indexOf("i"))); width = TwipsConverter.inches2twips(widthInch); } return (width); } /** * 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:column-width")) { colWidth = parseColWidth(value); } else { Debug.log(Debug.INFO, "ColumnStyle 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. ColumnStyle resolved = null; try { resolved = (ColumnStyle)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.) ColumnStyle parentStyle = null; if (sc != null) { if (parent != null) { parentStyle = (ColumnStyle)sc.lookup(parent, family, null, this.getClass()); if (parentStyle == null) Debug.log(Debug.ERROR, "parent style lookup of " + parent + " failed!"); else parentStyle = (ColumnStyle)parentStyle.getResolved(); } else if (!name.equals("DEFAULT_STYLE")) { parentStyle = (ColumnStyle)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 = (ColumnStyle)parentStyle.getResolved(); if ((colWidth == 0) && (parentStyle.getColWidth() != 0)) resolved.setColWidth(parentStyle.getColWidth()); } 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; ColumnStyle tStyle = (ColumnStyle)style; if(colWidth!=tStyle.getColWidth()) 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(colWidth!=0) { String width = TwipsConverter.twips2cm(colWidth) + "cm"; node.setAttribute("style:column-width", width); } } 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; } }