001 package org.apache.myfaces.tobago.renderkit.html; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020 import org.apache.commons.collections.set.ListOrderedSet; 021 import org.apache.commons.logging.Log; 022 import org.apache.commons.logging.LogFactory; 023 import org.apache.commons.lang.StringUtils; 024 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_DISABLED; 025 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_INLINE; 026 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_READONLY; 027 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE_CLASS; 028 import org.apache.myfaces.tobago.component.ComponentUtil; 029 import org.apache.myfaces.tobago.component.SupportsMarkup; 030 import org.apache.myfaces.tobago.context.ClientProperties; 031 import org.apache.myfaces.tobago.context.Theme; 032 033 import javax.faces.component.UIComponent; 034 import javax.faces.component.UIInput; 035 import javax.faces.context.FacesContext; 036 import java.io.Serializable; 037 import java.util.Iterator; 038 import java.util.Locale; 039 import java.util.Map; 040 041 /* 042 * Date: 2007-05-01 043 */ 044 045 public class StyleClasses implements Serializable { 046 047 private static final long serialVersionUID = 3738052927067803517L; 048 049 private static final Log LOG = LogFactory.getLog(StyleClasses.class); 050 051 public static final char SEPERATOR = '-'; 052 public static final String PREFIX = "tobago" + SEPERATOR; 053 public static final String MARKUP = SEPERATOR + "markup" + SEPERATOR; 054 055 private ListOrderedSet classes; 056 057 public StyleClasses() { 058 classes = new ListOrderedSet(); 059 } 060 061 private StyleClasses(StyleClasses base) { 062 this(); 063 classes.addAll(base.classes); 064 } 065 066 public static StyleClasses ensureStyleClasses(UIComponent component) { 067 Map attributes = component.getAttributes(); 068 StyleClasses classes = (StyleClasses) attributes.get(ATTR_STYLE_CLASS); 069 if (classes == null) { 070 classes = new StyleClasses(); 071 attributes.put(ATTR_STYLE_CLASS, classes); 072 } 073 return classes; 074 } 075 076 public static StyleClasses ensureStyleClassesCopy(UIComponent component) { 077 return new StyleClasses(ensureStyleClasses(component)); 078 } 079 080 @Deprecated 081 public void addFullQualifiedClass(String clazz) { 082 classes.add(clazz); 083 } 084 085 @Deprecated 086 public void removeFullQualifiedClass(String clazz) { 087 classes.remove(clazz); 088 } 089 090 public void addClass(String renderer, String sub) { 091 classes.add(nameOfClass(renderer, sub)); 092 } 093 094 public void removeClass(String renderer, String sub) { 095 classes.remove(nameOfClass(renderer, sub)); 096 } 097 098 private String nameOfClass(String renderer, String sub) { 099 StringBuilder builder = new StringBuilder(); 100 builder.append(PREFIX); 101 builder.append(renderer); 102 builder.append(SEPERATOR); 103 builder.append(sub); 104 return builder.toString(); 105 } 106 107 public void addMarkupClass(String renderer, String markup) { 108 addMarkupClass(renderer, null, markup); 109 } 110 111 public void removeMarkupClass(String renderer, String markup) { 112 removeMarkupClass(renderer, null, markup); 113 } 114 115 public void addMarkupClass(String renderer, String sub, String markup) { 116 classes.add(nameOfMarkupClass(renderer, sub, markup)); 117 } 118 119 public void removeMarkupClass(String renderer, String sub, String markup) { 120 classes.remove(nameOfMarkupClass(renderer, sub, markup)); 121 } 122 123 private String nameOfMarkupClass(String renderer, String sub, String markup) { 124 StringBuilder builder = new StringBuilder(); 125 builder.append(PREFIX); 126 builder.append(renderer); 127 if (sub != null) { 128 builder.append(SEPERATOR); 129 builder.append(sub); 130 } 131 builder.append(MARKUP); 132 builder.append(markup); 133 return builder.toString(); 134 } 135 136 public void addMarkupClass(UIComponent component, String rendererName) { 137 addMarkupClass(component, rendererName, null); 138 } 139 140 public void addMarkupClass(UIComponent component, String rendererName, String sub) { 141 if (component instanceof SupportsMarkup) { 142 String[] markups = ((SupportsMarkup) component).getMarkup(); 143 for (String markup: markups) { 144 if (!StringUtils.isBlank(markup)) { 145 Theme theme = ClientProperties.getInstance(FacesContext.getCurrentInstance().getViewRoot()).getTheme(); 146 if (theme.getRenderersConfig().isMarkupSupported(rendererName, markup)) { 147 addMarkupClass(rendererName, sub, markup); 148 } else if (!"none".equals(markup)) { 149 LOG.warn("Unknown markup='" + markup + "'"); 150 } 151 } 152 } 153 } 154 } 155 156 public void addAspectClass(String renderer, Aspect aspect) { 157 classes.add(nameOfAspectClass(renderer, aspect)); 158 } 159 160 public void removeAspectClass(String renderer, Aspect aspect) { 161 classes.remove(nameOfAspectClass(renderer, aspect)); 162 } 163 164 private String nameOfAspectClass(String renderer, Aspect aspect) { 165 StringBuilder builder = new StringBuilder(); 166 builder.append(PREFIX); 167 builder.append(renderer); 168 builder.append(aspect); 169 return builder.toString(); 170 } 171 172 173 public void addAspectClass(String renderer, String sub, Aspect aspect) { 174 classes.add(nameOfAspectClass(renderer, sub, aspect)); 175 } 176 177 public void removeAspectClass(String renderer, String sub, Aspect aspect) { 178 classes.remove(nameOfAspectClass(renderer, sub, aspect)); 179 } 180 181 private String nameOfAspectClass(String renderer, String sub, Aspect aspect) { 182 StringBuilder builder = new StringBuilder(); 183 builder.append(PREFIX); 184 builder.append(renderer); 185 builder.append(SEPERATOR); 186 builder.append(sub); 187 builder.append(aspect); 188 return builder.toString(); 189 } 190 191 public void addClasses(StyleClasses styleClasses) { 192 for (String clazz : (Iterable<String>) styleClasses.classes) { 193 classes.add(clazz); 194 } 195 } 196 197 public void removeClass(String clazz) { 198 classes.remove(clazz); 199 } 200 201 public void removeTobagoClasses(String rendererName) { 202 for (Iterator i = classes.iterator(); i.hasNext();) { 203 String clazz = (String) i.next(); 204 if (clazz.startsWith(PREFIX + rendererName)) { 205 i.remove(); 206 } 207 } 208 } 209 210 public void updateClassAttributeAndMarkup(UIComponent component, String rendererName) { 211 updateClassAttribute(component, rendererName); 212 addMarkupClass(component, rendererName); 213 } 214 215 public void updateClassAttribute(UIComponent component, String rendererName) { 216 // first remove old tobago-<rendererName>-<type> classes from class-attribute 217 removeTobagoClasses(rendererName); 218 219 addAspectClass(rendererName, Aspect.DEFAULT); 220 if (ComponentUtil.getBooleanAttribute(component, ATTR_DISABLED)) { 221 addAspectClass(rendererName, Aspect.DISABLED); 222 } 223 if (ComponentUtil.getBooleanAttribute(component, ATTR_READONLY)) { 224 addAspectClass(rendererName, Aspect.READONLY); 225 } 226 if (ComponentUtil.getBooleanAttribute(component, ATTR_INLINE)) { 227 addAspectClass(rendererName, Aspect.INLINE); 228 } 229 if (component instanceof UIInput) { 230 UIInput input = (UIInput) component; 231 if (ComponentUtil.isError(input)) { 232 addAspectClass(rendererName, Aspect.ERROR); 233 } 234 if (input.isRequired()) { 235 addAspectClass(rendererName, Aspect.REQUIRED); 236 } 237 } 238 } 239 240 @Override 241 public String toString() { 242 StringBuffer buffer = new StringBuffer(); 243 for (Iterator i = classes.iterator(); i.hasNext();) { 244 String clazz = (String) i.next(); 245 buffer.append(clazz); 246 if (i.hasNext()) { 247 buffer.append(' '); 248 } 249 } 250 return buffer.toString(); 251 } 252 253 public enum Aspect { 254 255 DEFAULT, 256 DISABLED, 257 READONLY, 258 INLINE, 259 ERROR, 260 REQUIRED; 261 262 private String aspect; 263 264 Aspect() { 265 aspect = '-' + name().toLowerCase(Locale.ENGLISH); 266 } 267 268 @Override 269 public String toString() { 270 return aspect; 271 } 272 } 273 }