001package com.hfg.css; 002 003import java.awt.Color; 004import java.util.List; 005import java.util.Map; 006import java.util.HashMap; 007import java.util.regex.Pattern; 008import java.util.regex.Matcher; 009 010import com.hfg.graphics.ColorUtil; 011import com.hfg.util.StringBuilderPlus; 012import com.hfg.util.StringUtil; 013import com.hfg.xml.XMLTag; 014 015//------------------------------------------------------------------------------ 016/** 017 * Contains CSS-related utility functions. 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 042public class CssUtil 043{ 044 //########################################################################### 045 // PUBLIC FUNCTIONS 046 //########################################################################### 047 048 //-------------------------------------------------------------------------- 049 public static String colorToCssValue(Color inValue) 050 { 051 String value = ""; 052 if (inValue != null) 053 { 054 if (255 == inValue.getAlpha()) 055 { 056 // No opacity 057 value = "#" + ColorUtil.colorToHex(inValue); 058 } 059 else 060 { 061 // Use rgba() format to specify the opacity 062 value = "rgba(" + inValue.getRed() + ", " + inValue.getGreen() + ", " + inValue.getBlue() 063 + ", " + String.format("%.1f", inValue.getAlpha()/255f)+ ")"; 064 } 065 } 066 067 return value; 068 } 069 070 //-------------------------------------------------------------------------- 071 /** 072 Adds the specified style attribute content to the specified tag. 073 @param inTag extends XMLTag instead of HTMLTag so that the SVG classes can use it as well. 074 @param inValue style value to add 075 */ 076 public static void addStyle(XMLTag inTag, String inValue) 077 { 078 if (StringUtil.isSet(inValue)) 079 { 080 String oldValue = inTag.getAttributeValue(CSS.STYLE); 081 if (StringUtil.isSet(oldValue)) 082 { 083 String[] attrPairs = inValue.trim().split(";"); 084 Map<String, String> styleAttrMap = new HashMap<>(attrPairs.length); 085 for (String pair : attrPairs) 086 { 087 String[] pieces = pair.split(":"); 088 styleAttrMap.put(pieces[0].trim(), pieces[1].trim()); 089 } 090 091 StringBuilderPlus buffer = new StringBuilderPlus(oldValue.trim()).setDelimiter(";"); 092 for (String attrName : styleAttrMap.keySet()) 093 { 094 boolean newAttr = true; 095 if (buffer.indexOf(attrName) >= 0) 096 { 097 // The specified attribute may already be present. Check more carefully 098 Pattern pattern = Pattern.compile("(?:^|;|\\s)" + attrName + "\\s*:\\s*(.+?)(?:;|$)"); 099 Matcher m = pattern.matcher(buffer.toString()); 100 if (m.find()) 101 { 102 if (styleAttrMap.get(attrName).contains("!important") 103 || ! m.group(1).contains("!important")) 104 { 105 buffer.replace(m.start(1), m.end(1), styleAttrMap.get(attrName)); 106 } 107 108 newAttr = false; 109 } 110 } 111 112 if (newAttr) 113 { 114 // Add the new style attribute 115 if (buffer.charAt(buffer.length() -1) == ';') 116 { 117 buffer.append(' '); 118 buffer.append(attrName); 119 } 120 else 121 { 122 buffer.delimitedAppend(attrName); 123 } 124 125 buffer.append(":"); 126 buffer.append(styleAttrMap.get(attrName)); 127 } 128 129 } 130 131 inValue = buffer.toString(); 132 } 133 134 inTag.setAttribute(CSS.STYLE, inValue); 135 } 136 } 137 138 //-------------------------------------------------------------------------- 139 /** 140 Removes the specified CSS property from the style attribute content of the specified tag if it is present. 141 @param inTag extends XMLTag instead of HTMLTag so that the SVG classes can use it as well. 142 @param inProperty CSS property to remove 143 */ 144 public static void removeStyleProperty(XMLTag inTag, CSSProperty inProperty) 145 { 146 if (inProperty != null) 147 { 148 String oldValue = inTag.getAttributeValue(CSS.STYLE); 149 if (StringUtil.isSet(oldValue)) 150 { 151 List<CSSDeclaration> declarations = CSSDeclaration.parse(oldValue); 152 boolean containsProperty = false; 153 for (int i = 0; i < declarations.size(); i++) 154 { 155 CSSDeclaration declaration = declarations.get(i); 156 if (declaration.getProperty().equals(inProperty)) 157 { 158 containsProperty = true; 159 declarations.remove(i); 160 break; 161 } 162 } 163 164 // It the property wasn't present there is nothing to do 165 if (containsProperty) 166 { 167 inTag.setAttribute(CSS.STYLE, StringUtil.join(declarations, ";")); 168 } 169 } 170 } 171 } 172}