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}