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 static org.apache.myfaces.tobago.TobagoConstants.ATTR_DISABLED; 024 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_INLINE; 025 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_READONLY; 026 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE_CLASS; 027 import org.apache.myfaces.tobago.component.ComponentUtil; 028 import org.apache.myfaces.tobago.component.SupportsMarkup; 029 import org.apache.myfaces.tobago.context.Theme; 030 import org.apache.myfaces.tobago.context.ClientProperties; 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.Map; 038 039 /* 040 * Date: 2007-05-01 041 */ 042 043 public class StyleClasses implements Serializable { 044 045 private static final Log LOG = LogFactory.getLog(StyleClasses.class); 046 047 public static final char SEPERATOR = '-'; 048 public static final String PREFIX = "tobago" + SEPERATOR; 049 public static final String MARKUP = SEPERATOR + "markup" + SEPERATOR; 050 051 private ListOrderedSet classes; 052 053 public StyleClasses() { 054 classes = new ListOrderedSet(); 055 } 056 057 private StyleClasses(StyleClasses base) { 058 this(); 059 classes.addAll(base.classes); 060 } 061 062 public static StyleClasses ensureStyleClasses(UIComponent component) { 063 Map attributes = component.getAttributes(); 064 StyleClasses classes = (StyleClasses) attributes.get(ATTR_STYLE_CLASS); 065 if (classes == null) { 066 classes = new StyleClasses(); 067 attributes.put(ATTR_STYLE_CLASS, classes); 068 } 069 return classes; 070 } 071 072 public static StyleClasses ensureStyleClassesCopy(UIComponent component) { 073 return new StyleClasses(ensureStyleClasses(component)); 074 } 075 076 @Deprecated 077 public void addFullQualifiedClass(String clazz) { 078 classes.add(clazz); 079 } 080 081 public void addClass(String renderer, String sub) { 082 StringBuilder builder = new StringBuilder(); 083 builder.append(PREFIX); 084 builder.append(renderer); 085 builder.append(SEPERATOR); 086 builder.append(sub); 087 classes.add(builder.toString()); 088 } 089 090 public void addMarkupClass(String renderer, String markup) { 091 StringBuilder builder = new StringBuilder(); 092 builder.append(PREFIX); 093 builder.append(renderer); 094 builder.append(MARKUP); 095 builder.append(markup); 096 classes.add(builder.toString()); 097 } 098 099 public void addMarkupClass(String renderer, String sub, String markup) { 100 StringBuilder builder = new StringBuilder(); 101 builder.append(PREFIX); 102 builder.append(renderer); 103 builder.append(SEPERATOR); 104 builder.append(sub); 105 builder.append(MARKUP); 106 builder.append(markup); 107 classes.add(builder.toString()); 108 } 109 110 public void addMarkupClass(UIComponent component, String rendererName) { 111 if (component instanceof SupportsMarkup) { 112 String[] markups = ((SupportsMarkup) component).getMarkup(); 113 for (String markup: markups) { 114 Theme theme = ClientProperties.getInstance(FacesContext.getCurrentInstance().getViewRoot()).getTheme(); 115 if (theme.getRenderersConfig().isMarkupSupported(rendererName, markup)) { 116 addMarkupClass(rendererName, markup); 117 } else { 118 LOG.warn("Unknown markup='" + markup + "'"); 119 } 120 } 121 } 122 } 123 124 public void addMarkupClass(UIComponent component, String rendererName, String sub) { 125 if (component instanceof SupportsMarkup) { 126 String[] markups = ((SupportsMarkup) component).getMarkup(); 127 for (String markup: markups) { 128 Theme theme = ClientProperties.getInstance(FacesContext.getCurrentInstance().getViewRoot()).getTheme(); 129 if (theme.getRenderersConfig().isMarkupSupported(rendererName, markup)) { 130 addMarkupClass(rendererName, sub, markup); 131 } else { 132 LOG.warn("Unknown markup='" + markup + "'"); 133 } 134 } 135 } 136 } 137 138 public void addAspectClass(String renderer, Aspect aspect) { 139 StringBuilder builder = new StringBuilder(); 140 builder.append(PREFIX); 141 builder.append(renderer); 142 builder.append(aspect); 143 classes.add(builder.toString()); 144 } 145 146 public void removeAspectClass(String renderer, Aspect aspect) { 147 StringBuilder builder = new StringBuilder(); 148 builder.append(PREFIX); 149 builder.append(renderer); 150 builder.append(aspect); 151 classes.remove(builder.toString()); 152 } 153 154 public void addAspectClass(String renderer, String sub, Aspect aspect) { 155 StringBuilder builder = new StringBuilder(); 156 builder.append(PREFIX); 157 builder.append(renderer); 158 builder.append(SEPERATOR); 159 builder.append(sub); 160 builder.append(aspect); 161 classes.add(builder.toString()); 162 } 163 164 public void addClasses(StyleClasses styleClasses) { 165 for (String clazz : (Iterable<String>) styleClasses.classes) { 166 classes.add(clazz); 167 } 168 } 169 170 public void removeClass(String clazz) { 171 classes.remove(clazz); 172 } 173 174 public void removeTobagoClasses(String rendererName) { 175 for (Iterator i = classes.iterator(); i.hasNext();) { 176 String clazz = (String) i.next(); 177 if (clazz.startsWith(PREFIX + rendererName)) { 178 i.remove(); 179 } 180 } 181 } 182 183 public void updateClassAttribute(UIComponent component, String rendererName) { 184 // first remove old tobago-<rendererName>-<type> classes from class-attribute 185 removeTobagoClasses(rendererName); 186 187 addAspectClass(rendererName, Aspect.DEFAULT); 188 if (ComponentUtil.getBooleanAttribute(component, ATTR_DISABLED)) { 189 addAspectClass(rendererName, Aspect.DISABLED); 190 } 191 if (ComponentUtil.getBooleanAttribute(component, ATTR_READONLY)) { 192 addAspectClass(rendererName, Aspect.READONLY); 193 } 194 if (ComponentUtil.getBooleanAttribute(component, ATTR_INLINE)) { 195 addAspectClass(rendererName, Aspect.INLINE); 196 } 197 if (component instanceof UIInput) { 198 UIInput input = (UIInput) component; 199 if (ComponentUtil.isError(input)) { 200 addAspectClass(rendererName, Aspect.ERROR); 201 } 202 if (input.isRequired()) { 203 addAspectClass(rendererName, Aspect.REQUIRED); 204 } 205 } 206 207 addMarkupClass(component, rendererName); 208 } 209 210 @Override 211 public String toString() { 212 StringBuffer buffer = new StringBuffer(); 213 for (Iterator i = classes.iterator(); i.hasNext();) { 214 String clazz = (String) i.next(); 215 buffer.append(clazz); 216 if (i.hasNext()) { 217 buffer.append(' '); 218 } 219 } 220 return buffer.toString(); 221 } 222 223 public enum Aspect { 224 225 DEFAULT, 226 DISABLED, 227 READONLY, 228 INLINE, 229 ERROR, 230 REQUIRED; 231 232 private String aspect; 233 234 Aspect() { 235 aspect = '-' + name().toLowerCase(); 236 } 237 238 @Override 239 public String toString() { 240 return aspect; 241 } 242 } 243 }