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}