001package com.hfg.xml.msofficexml.docx.wordprocessingml; 002 003 004import com.hfg.graphics.PaperSize; 005import com.hfg.graphics.units.GfxSize2D; 006import com.hfg.graphics.units.GfxUnits; 007import com.hfg.graphics.units.Pixels; 008import com.hfg.util.Orientation; 009import com.hfg.xml.XMLTag; 010import com.hfg.xml.msofficexml.docx.Docx; 011import com.hfg.xml.msofficexml.docx.DocxException; 012import com.hfg.xml.msofficexml.docx.RelationshipXML; 013 014 015//------------------------------------------------------------------------------ 016/** 017 Represents an Office Open XML section properties (<w:sectPr>) tag. 018 019 @author J. Alex Taylor, hairyfatguy.com 020 */ 021//------------------------------------------------------------------------------ 022// com.hfg XML/HTML Coding Library 023// 024// This library is free software; you can redistribute it and/or 025// modify it under the terms of the GNU Lesser General Public 026// License as published by the Free Software Foundation; either 027// version 2.1 of the License, or (at your option) any later version. 028// 029// This library is distributed in the hope that it will be useful, 030// but WITHOUT ANY WARRANTY; without even the implied warranty of 031// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 032// Lesser General Public License for more details. 033// 034// You should have received a copy of the GNU Lesser General Public 035// License along with this library; if not, write to the Free Software 036// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 037// 038// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 039// jataylor@hairyfatguy.com 040//------------------------------------------------------------------------------ 041// Section 17.6 (pg. 538) of Ecma Office Open XML Part 1 042/* 04317.6 Sections 044WordprocessingML does not natively store the concept of pages, since it is based on paragraphs and runs 045(which are laid out on to pages by consumers of this content). However, although there is no concept of 046storing pages in the WordprocessingML format, it is often necessary to store information about a page or 047group of pages in a document, in order to store information that is to be used to format the pages on which 048a set of paragraphs appear. In WordprocessingML, this information is stored via the use of sections. 049 050In WordprocessingML, sections are groupings of paragraphs that have a specific set of properties used to define 051the pages on which the text appears, as well as other section-level (applying to all paragraphs' appearance) properties. 052 053[Example: Consider a document with four paragraphs of text that is to be printed on a page in landscape mode, 054followed by ten paragraphs of text that are to be printed in portrait mode. This requirement implies information 055about the page(s) used to lay out each grouping of text - the first four paragraphs could require one page, or 056ten. 057 058Therefore, rather than try to cache knowledge of the number of pages and their properties (which is likely to become 059incorrect if the XML is manipulated by a producer that does not understand page layout), this information is stored 060by breaking the document into two sections, as follows: 061<pre> 062<w:p> ... 063</w:p> 064<w:p> ... 065</w:p> 066<w:p> ... 067</w:p> 068<w:p> 069 <w:sectPr> ... 070 (section one properties go here) <w:pgSz ... w:orient="landscape" /> ... 071 </w:sectPr> 072 ... 073</w:p> 074... 075<w:p> 076 <w:sectPr> ... 077 (section two properties go here) <w:pgSz ... w:orient="portrait" /> ... 078 </w:sectPr> 079 ... 080</w:p> 081</pre> 082 083end example] 084<p> 085 For all sections except the final section, the sectPr element is stored as a child element of the last paragraph 086 in the section. For the final section, this information is stored as the last child element of the body element 087</p> 088*/ 089public class WmlSectionProperties extends WmlXMLTag 090{ 091 private WmlPageMargins mPageMargins; 092 private WmlPageSize mPageSize; 093 094 //--------------------------------------------------------------------------- 095 public WmlSectionProperties(Docx inDocx) 096 { 097 super(WmlXML.SECT_PROPS, inDocx); 098 } 099 100 101 //--------------------------------------------------------------------------- 102 /** 103 * Sets the page dimensions based on the specified paper size and orientation. 104 */ 105 public WmlSectionProperties setPageSize(PaperSize inSize, Orientation inOrientation) 106 { 107 setPageSize(inSize); 108 getPageSize().setOrientation(inOrientation); 109 110 return this; 111 } 112 113 //--------------------------------------------------------------------------- 114 /** 115 * Sets the page dimensions based on the specified paper size. 116 */ 117 public WmlSectionProperties setPageSize(PaperSize inValue) 118 { 119 if (inValue != null) 120 { 121 getPageSize().setWidth(inValue.getDimensions().getWidth()).setHeight(inValue.getDimensions().getHeight()); 122 } 123 else 124 { 125 mPageSize = null; 126 } 127 128 return this; 129 } 130 131 //--------------------------------------------------------------------------- 132 /** 133 * Returns the page size tag if one exists or else instantiates a new one. 134 * @return the page size tag for this section 135 */ 136 public WmlPageSize getPageSize() 137 { 138 if (null == mPageSize) 139 { 140 // Check if it has been added via addSubtag()... 141 mPageSize = getOptionalSubtagByName(WmlXML.PAGE_SIZE); 142 if (null == mPageSize) 143 { 144 mPageSize = new WmlPageSize(); 145 addSubtag(mPageSize); 146 } 147 } 148 149 return mPageSize; 150 } 151 152 //--------------------------------------------------------------------------- 153 /** 154 * Returns the page margins if one exists or else instantiates a new one. 155 * @return the page margins for this section 156 */ 157 public WmlPageMargins getPageMargins() 158 { 159 if (null == mPageMargins) 160 { 161 // Check if it has been added via addSubtag()... 162 mPageMargins = getOptionalSubtagByName(WmlXML.PAGE_MARGINS); 163 if (null == mPageMargins) 164 { 165 mPageMargins = new WmlPageMargins(); 166 addSubtag(mPageMargins); 167 } 168 } 169 170 return mPageMargins; 171 } 172 173 //--------------------------------------------------------------------------- 174 public GfxSize2D getContentDimensions() 175 { 176 // Start with the page dimensions 177 GfxSize2D dimensions = getPageSize().getDimensions(); 178 179 float widthPx = dimensions.getWidth().to(GfxUnits.pixels); 180 float heightPx = dimensions.getHeight().to(GfxUnits.pixels); 181 182 // Now adjust for margins and gutter 183 184 WmlPageMargins pageMargins = getPageMargins(); 185 if (pageMargins.getLeft() != null) 186 { 187 widthPx -= pageMargins.getLeft().to(GfxUnits.pixels); 188 } 189 190 if (pageMargins.getRight() != null) 191 { 192 widthPx -= pageMargins.getRight().to(GfxUnits.pixels); 193 } 194 195 if (pageMargins.getGutter() != null) 196 { 197 widthPx -= pageMargins.getGutter().to(GfxUnits.pixels); 198 } 199 200 if (pageMargins.getTop() != null) 201 { 202 heightPx -= pageMargins.getTop().to(GfxUnits.pixels); 203 } 204 205 if (pageMargins.getBottom() != null) 206 { 207 heightPx -= pageMargins.getBottom().to(GfxUnits.pixels); 208 } 209 210 return new GfxSize2D().setWidth(new Pixels(widthPx)).setHeight(new Pixels(heightPx)); 211 } 212 213 214 //--------------------------------------------------------------------------- 215 // The header itself is placed in its own file and a reference is retained. 216 public void addHeader(WmlHeader inValue, WmlHeaderFooterType inType) 217 { 218 Docx docx = getParentDoc(); 219 if (null == docx) 220 { 221 throw new DocxException("No reference to the parent doc available!?"); 222 } 223 224 String headerId = docx.addHeader(inValue); 225 226 XMLTag headerRefTag = new XMLTag(WmlXML.HEADER_REFERENCE); 227 headerRefTag.setAttribute(RelationshipXML.ID_ATT, headerId); 228 headerRefTag.setAttribute(WmlXML.TYPE_ATT, inType); 229 230 addSubtag(headerRefTag); 231 } 232 233 234 //--------------------------------------------------------------------------- 235 // The footer itself is placed in its own file and a reference is retained. 236 public void addFooter(WmlFooter inValue, WmlHeaderFooterType inType) 237 { 238 Docx docx = getParentDoc(); 239 if (null == docx) 240 { 241 throw new DocxException("No reference to the parent doc available!?"); 242 } 243 244 String footerId = docx.addFooter(inValue); 245 246 XMLTag footerRefTag = new XMLTag(WmlXML.FOOTER_REFERENCE); 247 footerRefTag.setAttribute(RelationshipXML.ID_ATT, footerId); 248 footerRefTag.setAttribute(WmlXML.TYPE_ATT, inType); 249 250 addSubtag(footerRefTag); 251 } 252 253}