001package com.hfg.xml.msofficexml.docx.wordprocessingml.style; 002 003import java.awt.Color; 004import java.util.ArrayList; 005import java.util.List; 006 007import com.hfg.graphics.units.Points; 008import com.hfg.xml.XMLTag; 009import com.hfg.xml.msofficexml.docx.Docx; 010import com.hfg.xml.msofficexml.docx.wordprocessingml.WmlTextRunProperties; 011import com.hfg.xml.msofficexml.docx.wordprocessingml.WmlXML; 012 013//------------------------------------------------------------------------------ 014/** 015 Paragraph style for Docx's Office Open XML documents. 016 017 @author J. Alex Taylor, hairyfatguy.com 018 */ 019//------------------------------------------------------------------------------ 020// com.hfg XML/HTML Coding Library 021// 022// This library is free software; you can redistribute it and/or 023// modify it under the terms of the GNU Lesser General Public 024// License as published by the Free Software Foundation; either 025// version 2.1 of the License, or (at your option) any later version. 026// 027// This library is distributed in the hope that it will be useful, 028// but WITHOUT ANY WARRANTY; without even the implied warranty of 029// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 030// Lesser General Public License for more details. 031// 032// You should have received a copy of the GNU Lesser General Public 033// License along with this library; if not, write to the Free Software 034// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 035// 036// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 037// jataylor@hairyfatguy.com 038//------------------------------------------------------------------------------ 039 040public class WmlParagraphStyle extends WmlStyle 041{ 042 public static final String NORMAL_STYLE_ID = "Normal"; 043 public static final String HEADING1_STYLE_ID = "Heading1"; 044 public static final String HEADING2_STYLE_ID = "Heading2"; 045 public static final String TOC_HEADING_STYLE_ID = "TOCHeading"; 046 public static final String TOC1_STYLE_ID = "TOC1"; 047 public static final String TOC2_STYLE_ID = "TOC2"; 048 public static final String TOC3_STYLE_ID = "TOC3"; 049 public static final String LIST_PARAGRAPH_STYLE_ID = "ListParagraph"; 050 051 private WmlTextRunProperties mRunProperties; 052 private XMLTag mNextTag; 053 054 //########################################################################## 055 // CONSTRUCTORS 056 //########################################################################## 057 058 //--------------------------------------------------------------------------- 059 public WmlParagraphStyle(Docx inDocx) 060 { 061 super(WmlStyleType.paragraph, inDocx); 062 } 063 064 //--------------------------------------------------------------------------- 065 public WmlParagraphStyle(String inId, Docx inDocx) 066 { 067 super(WmlStyleType.paragraph, inId, inDocx); 068 } 069 070 071 //########################################################################## 072 // PUBLIC METHODS 073 //########################################################################## 074 075 //--------------------------------------------------------------------------- 076 @Override 077 public WmlParagraphStyle setName(String inValue) 078 { 079 return (WmlParagraphStyle) super.setName(inValue); 080 } 081 082 083 //--------------------------------------------------------------------------- 084 @Override 085 public WmlParagraphStyle setBasedOn(String inStyleId) 086 { 087 return (WmlParagraphStyle) super.setBasedOn(inStyleId); 088 } 089 090 //--------------------------------------------------------------------------- 091 @Override 092 public WmlParagraphStyle setSemiHidden() 093 { 094 return (WmlParagraphStyle) super.setSemiHidden(); 095 } 096 097 //--------------------------------------------------------------------------- 098 @Override 099 public WmlParagraphStyle setUnhideWhenUsed() 100 { 101 return (WmlParagraphStyle) super.setUnhideWhenUsed(); 102 } 103 104 //--------------------------------------------------------------------------- 105 @Override 106 public WmlParagraphStyle setLink(String inStyleId) 107 { 108 return (WmlParagraphStyle) super.setLink(inStyleId); 109 } 110 111 //--------------------------------------------------------------------------- 112 @Override 113 public WmlParagraphStyle setUI_Priority(Integer inValue) 114 { 115 return (WmlParagraphStyle) super.setUI_Priority(inValue); 116 } 117 118 //--------------------------------------------------------------------------- 119 /** 120 Specifies whether this is a "Primary Style" which should be included in the Quick Gallery. 121 * @param inValue whether this is a "Primary Style" which should be included in the Quick Gallery 122 * @return this style object to enable method chaining 123 */ 124 public WmlParagraphStyle setPrimaryStyle(boolean inValue) 125 { 126 if (inValue) 127 { 128 if (null == getOptionalSubtagByName(WmlXML.PRIMARY_STYLE)) 129 { 130 addSubtag(new XMLTag(WmlXML.PRIMARY_STYLE)); 131 } 132 } 133 else 134 { 135 removeSubtagsByName(WmlXML.PRIMARY_STYLE); 136 } 137 138 return this; 139 } 140 141 //--------------------------------------------------------------------------- 142 /** 143 * Returns the run properties tag if one exists or else instantiates a new one. 144 * @return the run properties 145 */ 146 public WmlTextRunProperties getTextRunProperties() 147 { 148 if (null == mRunProperties) 149 { 150 // Check it it has been added via addSubtag()... 151 mRunProperties = getOptionalSubtagByName(WmlXML.RUN_PROPS); 152 if (null == mRunProperties) 153 { 154 mRunProperties = new WmlTextRunProperties(getParentDoc()); 155 addSubtag(0, mRunProperties); 156 } 157 } 158 159 return mRunProperties; 160 } 161 162 //--------------------------------------------------------------------------- 163 /** 164 * Sets the style that should be used for the paragraph that follows this one. 165 */ 166 public WmlParagraphStyle setNext(String inStyleId) 167 { 168 if (null == mNextTag) 169 { 170 // Check it it has been added via addSubtag()... 171 mNextTag = getOptionalSubtagByName(WmlXML.NEXT); 172 if (null == mNextTag) 173 { 174 mNextTag = new XMLTag(WmlXML.NEXT); 175 mNextTag.setAttribute(WmlXML.VALUE_ATT, inStyleId); 176 addSubtag(mNextTag); 177 } 178 } 179 180 return this; 181 } 182 183 //--------------------------------------------------------------------------- 184 public WmlParagraphStyle setAutoRedefine() 185 { 186 if (null == getOptionalSubtagByName(WmlXML.AUTO_REDEFINE)) 187 { 188 addSubtag(WmlXML.AUTO_REDEFINE); 189 } 190 191 return this; 192 } 193 194 //--------------------------------------------------------------------------- 195 public static List<WmlStyle> generateDefaultStyles(Docx inParentDoc) 196 { 197 List<WmlStyle> defaultStyles = new ArrayList<>(5); 198 199 // Normal 200 WmlStyle normalStyle = new WmlParagraphStyle(NORMAL_STYLE_ID, inParentDoc) 201 .setIsDefault(true); 202 defaultStyles.add(normalStyle); 203 204 205 // Heading 1 206 defaultStyles.add(generateHeading1(inParentDoc)); 207 208 // Heading 2 209 defaultStyles.add(generateHeading2(inParentDoc)); 210 211 // TOC Heading 212 defaultStyles.add(generateTOCHeading(inParentDoc)); 213 214 // TOC1 215 defaultStyles.add(generateTOC1(inParentDoc)); 216 217 // TOC2 218 defaultStyles.add(generateTOC2(inParentDoc)); 219 220 // TOC3 221 defaultStyles.add(generateTOC3(inParentDoc)); 222 223 // List Paragraph 224 defaultStyles.add(generateListParagraph(inParentDoc)); 225 226 return defaultStyles; 227 } 228 229 230 //########################################################################## 231 // PRIVATE METHODS 232 //########################################################################## 233 234 //--------------------------------------------------------------------------- 235 /* 236 <w:style w:type="paragraph" w:styleId="Heading1"> 237 <w:name w:val="heading 1"/> 238 <w:basedOn w:val="Normal"/> 239 <w:next w:val="Normal"/> 240 <w:link w:val="Heading1Char"/> 241 <w:uiPriority w:val="9"/> 242 <w:qFormat/> 243 <w:rsid w:val="00BF045C"/> 244 <w:pPr> 245 <w:keepNext/> 246 <w:keepLines/> 247 <w:spacing w:before="240"/> 248 <w:outlineLvl w:val="0"/> 249 </w:pPr> 250 <w:rPr> 251 <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi"/> 252 <w:color w:val="2F5496" w:themeColor="accent1" w:themeShade="BF"/> 253 <w:sz w:val="32"/> 254 <w:szCs w:val="32"/> 255 </w:rPr> 256 </w:style> 257 */ 258 private static WmlParagraphStyle generateHeading1(Docx inParentDoc) 259 { 260 WmlParagraphStyle style = new WmlParagraphStyle(HEADING1_STYLE_ID, inParentDoc) 261 .setName("Heading 1") 262 .setBasedOn(NORMAL_STYLE_ID) 263 .setNext(NORMAL_STYLE_ID) 264 .setLink(WmlCharacterStyle.HEADING1_CHAR_STYLE_ID) 265 .setUI_Priority(9) 266 .setPrimaryStyle(true); 267 268 style.getParagraphProperties() 269 .setKeepNext() 270 .setKeepLines() 271 .setOutlineLevel(0) 272 .getSpacing().setBefore(new Points(240 / 20)); 273 274 style.getTextRunProperties() 275 .setAnsiThemeFont("majorHAnsi") 276 .setAsciiThemeFont("majorHAnsi") 277 .setComplexScriptThemeFont("majorBidi") 278 .setEastAsiaThemeFont("majorEastAsia") 279 .setColor(Color.decode("#2F5496")) 280 .setThemeColor("accent1") 281 .setThemeShade("BF") 282 .setSize(new Points(16)) 283 .setComplexScriptSize(new Points(16)); 284 285 return style; 286 } 287 288 //--------------------------------------------------------------------------- 289 /* 290 <w:style w:type="paragraph" w:styleId="Heading2"> 291 <w:name w:val="heading 2"/> 292 <w:basedOn w:val="Normal"/> 293 <w:next w:val="Normal"/> 294 <w:link w:val="Heading2Char"/> 295 <w:uiPriority w:val="9"/> 296 <w:unhideWhenUsed/> 297 <w:qFormat/> 298 <w:rsid w:val="00BF045C"/> 299 <w:pPr> 300 <w:keepNext/> 301 <w:keepLines/> 302 <w:spacing w:before="40"/> 303 <w:outlineLvl w:val="1"/> 304 </w:pPr> 305 <w:rPr> 306 <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi"/> 307 <w:color w:val="2F5496" w:themeColor="accent1" w:themeShade="BF"/> 308 <w:sz w:val="26"/> 309 <w:szCs w:val="26"/> 310 </w:rPr> 311 </w:style> 312 */ 313 private static WmlParagraphStyle generateHeading2(Docx inParentDoc) 314 { 315 WmlParagraphStyle style = new WmlParagraphStyle(HEADING2_STYLE_ID, inParentDoc) 316 .setName("Heading 2") 317 .setBasedOn(NORMAL_STYLE_ID) 318 .setNext(NORMAL_STYLE_ID) 319 .setLink(WmlCharacterStyle.HEADING2_CHAR_STYLE_ID) 320 .setUI_Priority(9) 321 .setUnhideWhenUsed() 322 .setPrimaryStyle(true); 323 324 style.getParagraphProperties() 325 .setKeepNext() 326 .setKeepLines() 327 .setOutlineLevel(1) 328 .getSpacing().setBefore(new Points(40 / 20)); 329 330 style.getTextRunProperties() 331 .setAnsiThemeFont("majorHAnsi") 332 .setAsciiThemeFont("majorHAnsi") 333 .setComplexScriptThemeFont("majorBidi") 334 .setEastAsiaThemeFont("majorEastAsia") 335 .setColor(Color.decode("#2F5496")) 336 .setThemeColor("accent1") 337 .setThemeShade("BF") 338 .setSize(new Points(13)) 339 .setComplexScriptSize(new Points(13)); 340 341 return style; 342 } 343 344 //--------------------------------------------------------------------------- 345 /* 346 <w:style w:type="paragraph" w:styleId="TOCHeading"> 347 <w:name w:val="TOC Heading"/> 348 <w:basedOn w:val="Heading1"/> 349 <w:next w:val="Normal"/> 350 <w:uiPriority w:val="39"/> 351 <w:unhideWhenUsed/> 352 <w:qFormat/> 353 <w:rsid w:val="00463183"/> 354 <w:pPr> 355 <w:spacing w:before="480" w:line="276" w:lineRule="auto"/> 356 <w:outlineLvl w:val="9"/> 357 </w:pPr> 358 <w:rPr> 359 <w:b/> 360 <w:bCs/> 361 <w:sz w:val="28"/> 362 <w:szCs w:val="28"/> 363 </w:rPr> 364 </w:style> 365 */ 366 private static WmlParagraphStyle generateTOCHeading(Docx inParentDoc) 367 { 368 WmlParagraphStyle style = new WmlParagraphStyle(TOC_HEADING_STYLE_ID, inParentDoc) 369 .setName("TOC Heading") 370 .setBasedOn(HEADING1_STYLE_ID) 371 .setNext(NORMAL_STYLE_ID) 372 .setUI_Priority(39) 373 .setPrimaryStyle(true); // qFormat 374 375 style.getParagraphProperties() 376 .setKeepNext() 377 .setKeepLines() 378 .setOutlineLevel(9) 379 .getSpacing().setBefore(new Points(480 / 20)).setLine(new Points(276 / 20)).setAutoLineRule(); 380 381 style.getTextRunProperties() 382 .setBold() 383 .setComplexScriptBold() 384 .setSize(new Points(14)) 385 .setComplexScriptSize(new Points(14)); 386 387 return style; 388 } 389 390 //--------------------------------------------------------------------------- 391 /* 392 <w:style w:type="paragraph" w:styleId="TOC1"> 393 <w:name w:val="toc 1"/> 394 <w:basedOn w:val="Normal"/> 395 <w:next w:val="Normal"/> 396 <w:autoRedefine/> 397 <w:uiPriority w:val="39"/> 398 <w:unhideWhenUsed/> 399 <w:rsid w:val="00463183"/> 400 <w:pPr> 401 <w:spacing w:before="120"/> 402 </w:pPr> 403 <w:rPr> 404 <w:rFonts w:cstheme="minorHAnsi"/> 405 <w:b/> 406 <w:bCs/> 407 <w:i/> 408 <w:iCs/> 409 </w:rPr> 410 </w:style> 411 */ 412 private static WmlParagraphStyle generateTOC1(Docx inParentDoc) 413 { 414 WmlParagraphStyle style = new WmlParagraphStyle(TOC1_STYLE_ID, inParentDoc) 415 .setName("TOC 1") 416 .setBasedOn(NORMAL_STYLE_ID) 417 .setNext(NORMAL_STYLE_ID) 418 .setAutoRedefine() 419 .setUI_Priority(39); 420 421 style.getParagraphProperties() 422 .getSpacing().setBefore(new Points(120 / 20)); 423 424 style.getTextRunProperties() 425 .setComplexScriptThemeFont("minorHAnsi") 426 .setBold() 427 .setComplexScriptBold() 428 .setItalics() 429 .setComplexScriptItalics(); 430 431 return style; 432 } 433 434 //--------------------------------------------------------------------------- 435 /* 436 <w:style w:type="paragraph" w:styleId="TOC2"> 437 <w:name w:val="toc 2"/> 438 <w:basedOn w:val="Normal"/> 439 <w:next w:val="Normal"/> 440 <w:autoRedefine/> 441 <w:uiPriority w:val="39"/> 442 <w:semiHidden/> 443 <w:unhideWhenUsed/> 444 <w:rsid w:val="00463183"/> 445 <w:pPr> 446 <w:spacing w:before="120"/> 447 <w:ind w:left="240"/> 448 </w:pPr> 449 <w:rPr> 450 <w:rFonts w:cstheme="minorHAnsi"/> 451 <w:b/> 452 <w:bCs/> 453 <w:sz w:val="22"/> 454 <w:szCs w:val="22"/> 455 </w:rPr> 456 </w:style> 457 */ 458 private static WmlParagraphStyle generateTOC2(Docx inParentDoc) 459 { 460 WmlParagraphStyle style = new WmlParagraphStyle(TOC2_STYLE_ID, inParentDoc) 461 .setName("TOC 2") 462 .setBasedOn(NORMAL_STYLE_ID) 463 .setNext(NORMAL_STYLE_ID) 464 .setAutoRedefine() 465 .setUI_Priority(39) 466 .setSemiHidden(); 467 468 style.getParagraphProperties() 469 .getSpacing().setBefore(new Points(120 / 20)); 470 style.getParagraphProperties() 471 .getIndentation().setLeft(new Points(240 / 20)); 472 473 style.getTextRunProperties() 474 .setComplexScriptThemeFont("minorHAnsi") 475 .setBold() 476 .setComplexScriptBold() 477 .setSize(new Points(11)) 478 .setComplexScriptSize(new Points(11)); 479 480 return style; 481 } 482 483 //--------------------------------------------------------------------------- 484 /* 485 <w:style w:type="paragraph" w:styleId="TOC3"> 486 <w:name w:val="toc 3"/> 487 <w:basedOn w:val="Normal"/> 488 <w:next w:val="Normal"/> 489 <w:autoRedefine/> 490 <w:uiPriority w:val="39"/> 491 <w:semiHidden/> 492 <w:unhideWhenUsed/> 493 <w:rsid w:val="00463183"/> 494 <w:pPr> 495 <w:ind w:left="480"/> 496 </w:pPr> 497 <w:rPr> 498 <w:rFonts w:cstheme="minorHAnsi"/> 499 <w:sz w:val="20"/> 500 <w:szCs w:val="20"/> 501 </w:rPr> 502 </w:style> 503 */ 504 private static WmlParagraphStyle generateTOC3(Docx inParentDoc) 505 { 506 WmlParagraphStyle style = new WmlParagraphStyle(TOC3_STYLE_ID, inParentDoc) 507 .setName("TOC 3") 508 .setBasedOn(NORMAL_STYLE_ID) 509 .setNext(NORMAL_STYLE_ID) 510 .setAutoRedefine() 511 .setUI_Priority(39) 512 .setSemiHidden(); 513 514 style.getParagraphProperties() 515 .getIndentation().setLeft(new Points(480 / 20)); 516 517 style.getTextRunProperties() 518 .setComplexScriptThemeFont("minorHAnsi") 519 .setSize(new Points(10)) 520 .setComplexScriptSize(new Points(10)); 521 522 return style; 523 } 524 525 //--------------------------------------------------------------------------- 526 /* 527 <w:style w:type="paragraph" w:styleId="ListParagraph"> 528 <w:name w:val="List Paragraph"/> 529 <w:basedOn w:val="Normal"/> 530 <w:uiPriority w:val="34"/> 531 <w:qFormat/> 532 <w:rsid w:val="006E46D5"/> 533 <w:pPr> 534 <w:ind w:left="720"/> 535 <w:contextualSpacing/> 536 </w:pPr> 537 </w:style> 538 */ 539 private static WmlParagraphStyle generateListParagraph(Docx inParentDoc) 540 { 541 WmlParagraphStyle style = new WmlParagraphStyle(LIST_PARAGRAPH_STYLE_ID, inParentDoc) 542 .setName("List Paragraph") 543 .setBasedOn(NORMAL_STYLE_ID) 544 .setUI_Priority(34) 545 .setPrimaryStyle(true); 546 547 style.getParagraphProperties() 548 .setContextualSpacing(true) 549 .getIndentation().setLeft(new Points(720 / 20)); 550 551 return style; 552 } 553 554}