001package com.hfg.xml.msofficexml.docx.wordprocessingml.style;
002
003
004import com.hfg.css.CSSBorderStyle;
005import com.hfg.css.CSSDeclaration;
006import com.hfg.css.CSSException;
007import com.hfg.css.CSSProperty;
008import com.hfg.graphics.units.GfxSize;
009import com.hfg.graphics.units.GfxUnits;
010import com.hfg.graphics.units.Pixels;
011import com.hfg.graphics.units.Points;
012import com.hfg.html.attribute.HTMLColor;
013import com.hfg.graphics.ColorUtil;
014import com.hfg.util.StringUtil;
015import com.hfg.xml.msofficexml.docx.Docx;
016import com.hfg.xml.msofficexml.docx.DocxException;
017import com.hfg.xml.msofficexml.OfficeOpenXMLTag;
018import com.hfg.xml.msofficexml.docx.wordprocessingml.WmlXML;
019
020import java.awt.Color;
021import java.util.regex.Matcher;
022import java.util.regex.Pattern;
023
024/**
025 Reference: ECMA-376, 3rd Edition (June, 2011), Fundamentals and Markup Language Reference 17.18.2.
026 */
027
028public class WmlTextBorder extends OfficeOpenXMLTag
029{
030   private static final Pattern sizePattern = Pattern.compile("(\\d+)(px)?");
031
032   //---------------------------------------------------------------------------
033   public WmlTextBorder(Docx inDocx)
034   {
035      super(WmlXML.BORDER, inDocx);
036
037      init();
038   }
039
040
041   //---------------------------------------------------------------------------
042   public WmlTextBorder(Docx inDocx, CSSDeclaration inCSSDeclaration)
043   {
044      this(inDocx);
045
046      if (! inCSSDeclaration.getProperty().equals(CSSProperty.border))
047      {
048         throw new CSSException("The CSS declaration " + StringUtil.singleQuote(inCSSDeclaration.toString())
049               + " cannot be used to construct a " + this.getClass().getSimpleName() + " object!");
050      }
051
052      // Ex: '1px solid blue'
053
054      boolean findSize  = true;
055      boolean findStyle = true;
056      boolean findColor = true;
057
058      String[] valuePieces = inCSSDeclaration.getValue().split("\\s+");
059      for (int i = 0; i < valuePieces.length; i++)
060      {
061         String token = valuePieces[i];
062
063         if (findSize)
064         {
065            findSize = false; // Size should always come first
066            Matcher m = sizePattern.matcher(token);
067            if (m.matches())
068            {
069               setSize(new Pixels(Integer.parseInt(m.group(1))));
070               continue;
071            }
072         }
073
074         if (findStyle)
075         {
076            findStyle = false;
077            CSSBorderStyle style = CSSBorderStyle.valueOf(token);
078            if (style != null)
079            {
080               WmlLineBorderStyle wmlStyle = WmlLineBorderStyle.valueOf(style);
081               if (wmlStyle != null)
082               {
083                  setStyle(wmlStyle);
084               }
085               continue;
086            }
087
088         }
089
090         if (findColor)
091         {
092            findColor = false;
093            HTMLColor color = HTMLColor.valueOf(token);
094            if (color != null)
095            {
096               setColor(color);
097            }
098         }
099      }
100   }
101
102   //---------------------------------------------------------------------------
103   private void init()
104   {
105      // Set some default values
106      setStyle(WmlLineBorderStyle.single);
107      setSize(new Points(1));
108      setColor(Color.black);
109   }
110
111   //---------------------------------------------------------------------------
112   /**
113    * Specifies the width of the border in eighths of a point, with a minimum value
114    * of 1/4 of a point and a maximum value of twelve points.
115    * @param inValue width of the border
116    */
117   public WmlTextBorder setSize(GfxSize inValue)
118   {
119      int eighthOfAPointValue = (int) (inValue.to(GfxUnits.points) * 8);
120      if (eighthOfAPointValue < 2)
121      {
122         throw new DocxException("The border size must be between 1/4 to 12 points!");
123      }
124
125      setAttribute(WmlXML.SIZE_ATT, eighthOfAPointValue);
126      return this;
127   }
128
129   //---------------------------------------------------------------------------
130   public WmlTextBorder setStyle(WmlLineBorderStyle inValue)
131   {
132      if (inValue != null)
133      {
134         setAttribute(WmlXML.VALUE_ATT, inValue.name());
135      }
136      else
137      {
138         removeAttribute(WmlXML.VALUE_ATT.toString());
139      }
140
141      return this;
142   }
143
144   //---------------------------------------------------------------------------
145   public WmlTextBorder setColor(Color inValue)
146   {
147      if (inValue != null)
148      {
149         setAttribute(WmlXML.COLOR_ATT, ColorUtil.colorToHex(inValue));
150      }
151      else
152      {
153         removeAttribute(WmlXML.COLOR_ATT.toString());
154      }
155
156      return this;
157   }
158
159   //---------------------------------------------------------------------------
160   public WmlTextBorder setAutoColor(boolean inValue)
161   {
162      if (inValue)
163      {
164         setAttribute(WmlXML.COLOR_ATT, "auto");
165      }
166      else
167      {
168         removeAttribute(WmlXML.COLOR_ATT.toString());
169      }
170
171      return this;
172   }
173
174   //---------------------------------------------------------------------------
175   public WmlTextBorder setShadow(boolean inValue)
176   {
177      setAttribute(WmlXML.SHADOW_ATT, inValue);
178      return this;
179   }
180
181   //---------------------------------------------------------------------------
182   /**
183    * The padding between the text and the border.
184    * @param inValue padding
185    */
186   public WmlTextBorder setSpace(GfxSize inValue)
187   {
188      setAttribute(WmlXML.SIZE_ATT, inValue.toInt(GfxUnits.points));
189      return this;
190   }
191}