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.lang.StringUtils; 022 import org.apache.myfaces.tobago.component.Attributes; 023 import org.apache.myfaces.tobago.component.SupportsMarkup; 024 import org.apache.myfaces.tobago.context.Markup; 025 import org.apache.myfaces.tobago.context.Theme; 026 import org.apache.myfaces.tobago.internal.util.Deprecation; 027 import org.apache.myfaces.tobago.util.ComponentUtils; 028 import org.apache.myfaces.tobago.util.VariableResolverUtils; 029 import org.slf4j.Logger; 030 import org.slf4j.LoggerFactory; 031 032 import javax.faces.component.UIComponent; 033 import javax.faces.component.UIInput; 034 import javax.faces.context.FacesContext; 035 import java.io.Serializable; 036 import java.util.Iterator; 037 import java.util.Locale; 038 import java.util.Map; 039 040 /** 041 * @deprecated since Tobago 1.5.0. Please use {@link org.apache.myfaces.tobago.renderkit.css.Classes}. 042 */ 043 @Deprecated 044 public class StyleClasses implements Serializable { 045 046 private static final long serialVersionUID = 3738052927067803517L; 047 048 private static final Logger LOG = LoggerFactory.getLogger(StyleClasses.class); 049 050 public static final char SEPARATOR = '-'; 051 public static final String PREFIX = "tobago" + SEPARATOR; 052 public static final String MARKUP = SEPARATOR + "markup" + SEPARATOR; 053 054 private ListOrderedSet classes; 055 056 public StyleClasses() { 057 classes = new ListOrderedSet(); 058 } 059 060 /** 061 * Creates a StyleClasses element and adds one entry for a sub-component with the name of the renderer. 062 * E. g.: UITreeNode + "icon" -> tobago-treeNode-icon 063 */ 064 public StyleClasses(UIComponent component, String sub) { 065 this(); 066 addClass(StringUtils.uncapitalize(component.getRendererType()), sub); 067 } 068 069 private StyleClasses(StyleClasses base) { 070 this(); 071 classes.addAll(base.classes); 072 } 073 074 public static StyleClasses ensureStyleClasses(UIComponent component) { 075 Map attributes = component.getAttributes(); 076 StyleClasses classes = (StyleClasses) attributes.get(Attributes.STYLE_CLASS); 077 if (classes == null) { 078 classes = new StyleClasses(); 079 attributes.put(Attributes.STYLE_CLASS, classes); 080 } 081 return classes; 082 } 083 084 public static StyleClasses ensureStyleClassesCopy(UIComponent component) { 085 return new StyleClasses(ensureStyleClasses(component)); 086 } 087 088 /** 089 * @deprecated since Tobago 1.5.0. Please use {@link org.apache.myfaces.tobago.renderkit.css.Classes}. 090 */ 091 @Deprecated 092 public void addFullQualifiedClass(String clazz) { 093 classes.add(clazz); 094 } 095 /** 096 * @deprecated since Tobago 1.5.0. Please use {@link org.apache.myfaces.tobago.renderkit.css.Classes}. 097 */ 098 @Deprecated 099 public void removeFullQualifiedClass(String clazz) { 100 classes.remove(clazz); 101 } 102 103 public void addClass(String renderer, String sub) { 104 classes.add(nameOfClass(renderer, sub)); 105 } 106 107 public void removeClass(String renderer, String sub) { 108 classes.remove(nameOfClass(renderer, sub)); 109 } 110 111 public boolean isEmpty() { 112 return classes.isEmpty(); 113 } 114 115 private String nameOfClass(String renderer, String sub) { 116 StringBuilder builder = new StringBuilder(PREFIX); 117 builder.append(renderer); 118 builder.append(SEPARATOR); 119 builder.append(sub); 120 return builder.toString(); 121 } 122 123 public void addMarkupClass(String renderer, String markup) { 124 addMarkupClass(renderer, null, markup); 125 } 126 127 public void removeMarkupClass(String renderer, String markup) { 128 removeMarkupClass(renderer, null, markup); 129 } 130 131 public void addMarkupClass(String renderer, String sub, String markup) { 132 classes.add(nameOfMarkupClass(renderer, sub, markup)); 133 } 134 135 public void removeMarkupClass(String renderer, String sub, String markup) { 136 classes.remove(nameOfMarkupClass(renderer, sub, markup)); 137 } 138 139 private String nameOfMarkupClass(String renderer, String sub, String markup) { 140 StringBuilder builder = new StringBuilder(PREFIX); 141 builder.append(renderer); 142 if (sub != null) { 143 builder.append(SEPARATOR); 144 builder.append(sub); 145 } 146 builder.append(MARKUP); 147 builder.append(markup); 148 return builder.toString(); 149 } 150 151 public void addMarkupClass(UIComponent component, String rendererName) { 152 if (component instanceof SupportsMarkup) { 153 addMarkupClass((SupportsMarkup) component, rendererName, null); 154 } 155 } 156 157 public void addMarkupClass(SupportsMarkup supportsMarkup, String rendererName, String sub) { 158 Markup m = supportsMarkup.getCurrentMarkup(); 159 if (m != null) { 160 for (String markup : m) { 161 Theme theme = VariableResolverUtils.resolveClientProperties(FacesContext.getCurrentInstance()).getTheme(); 162 if (theme.getRenderersConfig().isMarkupSupported(rendererName, markup)) { 163 addMarkupClass(rendererName, sub, markup); 164 } else if ("none".equals(markup)) { 165 Deprecation.LOG.warn("Markup 'none' is deprecated, please use a NULL pointer instead."); 166 } else { 167 LOG.warn("Unknown markup='" + markup + "'"); 168 } 169 } 170 } 171 } 172 173 public void addAspectClass(String renderer, Aspect aspect) { 174 classes.add(nameOfAspectClass(renderer, aspect)); 175 } 176 177 public void removeAspectClass(String renderer, Aspect aspect) { 178 classes.remove(nameOfAspectClass(renderer, aspect)); 179 } 180 181 private String nameOfAspectClass(String renderer, Aspect aspect) { 182 StringBuilder builder = new StringBuilder(PREFIX); 183 builder.append(renderer); 184 builder.append(aspect); 185 return builder.toString(); 186 } 187 188 public void addAspectClass(String renderer, String sub, Aspect aspect) { 189 classes.add(nameOfAspectClass(renderer, sub, aspect)); 190 } 191 192 public void removeAspectClass(String renderer, String sub, Aspect aspect) { 193 classes.remove(nameOfAspectClass(renderer, sub, aspect)); 194 } 195 196 private String nameOfAspectClass(String renderer, String sub, Aspect aspect) { 197 StringBuilder builder = new StringBuilder(PREFIX); 198 builder.append(renderer); 199 builder.append(SEPARATOR); 200 builder.append(sub); 201 builder.append(aspect); 202 return builder.toString(); 203 } 204 205 public void addClasses(StyleClasses styleClasses) { 206 for (String clazz : (Iterable<String>) styleClasses.classes) { 207 classes.add(clazz); 208 } 209 } 210 211 public void removeClass(String clazz) { 212 classes.remove(clazz); 213 } 214 215 public void removeTobagoClasses(String rendererName) { 216 for (Iterator i = classes.iterator(); i.hasNext();) { 217 String clazz = (String) i.next(); 218 if (clazz.startsWith(PREFIX + rendererName)) { 219 i.remove(); 220 } 221 } 222 } 223 224 public void updateClassAttributeAndMarkup(UIComponent component, String rendererName) { 225 updateClassAttribute(component, rendererName); 226 addMarkupClass(component, rendererName); 227 } 228 229 public void updateClassAttribute(UIComponent component, String rendererName) { 230 // first remove old tobago-<rendererName>-<type> classes from class-attribute 231 removeTobagoClasses(rendererName); 232 233 addAspectClass(rendererName, Aspect.DEFAULT); 234 if (ComponentUtils.getBooleanAttribute(component, Attributes.DISABLED)) { 235 addAspectClass(rendererName, Aspect.DISABLED); 236 } 237 if (ComponentUtils.getBooleanAttribute(component, Attributes.READONLY)) { 238 addAspectClass(rendererName, Aspect.READONLY); 239 } 240 if (ComponentUtils.getBooleanAttribute(component, Attributes.INLINE)) { 241 addAspectClass(rendererName, Aspect.INLINE); 242 } 243 if (component instanceof UIInput) { 244 UIInput input = (UIInput) component; 245 if (ComponentUtils.isError(input)) { 246 addAspectClass(rendererName, Aspect.ERROR); 247 } 248 if (input.isRequired()) { 249 addAspectClass(rendererName, Aspect.REQUIRED); 250 } 251 } 252 } 253 254 @Override 255 public String toString() { 256 if (classes.isEmpty()) { 257 return null; 258 } 259 StringBuilder buffer = new StringBuilder(16 * classes.size()); 260 for (Iterator i = classes.iterator(); i.hasNext();) { 261 String clazz = (String) i.next(); 262 buffer.append(clazz); 263 if (i.hasNext()) { 264 buffer.append(' '); 265 } 266 } 267 return buffer.toString(); 268 } 269 270 /** 271 * @deprecated since Tobago 1.5.0. Please use {@link org.apache.myfaces.tobago.context.Markup}. 272 */ 273 @Deprecated 274 public enum Aspect { 275 276 DEFAULT, 277 DISABLED, 278 READONLY, 279 INLINE, 280 ERROR, 281 REQUIRED; 282 283 private String aspect; 284 285 Aspect() { 286 aspect = name().equals("DEFAULT") ? "" : '-' + name().toLowerCase(Locale.ENGLISH); 287 } 288 289 @Override 290 public String toString() { 291 return aspect; 292 } 293 } 294 }