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.util.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 public boolean isEmpty() {
099 return classes.isEmpty();
100 }
101
102 private String nameOfClass(String renderer, String sub) {
103 StringBuilder builder = new StringBuilder(PREFIX);
104 builder.append(renderer);
105 builder.append(SEPERATOR);
106 builder.append(sub);
107 return builder.toString();
108 }
109
110 public void addMarkupClass(String renderer, String markup) {
111 addMarkupClass(renderer, null, markup);
112 }
113
114 public void removeMarkupClass(String renderer, String markup) {
115 removeMarkupClass(renderer, null, markup);
116 }
117
118 public void addMarkupClass(String renderer, String sub, String markup) {
119 classes.add(nameOfMarkupClass(renderer, sub, markup));
120 }
121
122 public void removeMarkupClass(String renderer, String sub, String markup) {
123 classes.remove(nameOfMarkupClass(renderer, sub, markup));
124 }
125
126 private String nameOfMarkupClass(String renderer, String sub, String markup) {
127 StringBuilder builder = new StringBuilder(PREFIX);
128 builder.append(renderer);
129 if (sub != null) {
130 builder.append(SEPERATOR);
131 builder.append(sub);
132 }
133 builder.append(MARKUP);
134 builder.append(markup);
135 return builder.toString();
136 }
137
138 public void addMarkupClass(UIComponent component, String rendererName) {
139 if (component instanceof SupportsMarkup) {
140 addMarkupClass((SupportsMarkup) component, rendererName, null);
141 }
142 }
143
144 public void addMarkupClass(SupportsMarkup supportsMarkup, String rendererName, String sub) {
145 for (String markup : supportsMarkup.getMarkup()) {
146 if (!StringUtils.isBlank(markup)) {
147 Theme theme = ClientProperties.getInstance(FacesContext.getCurrentInstance().getViewRoot()).getTheme();
148 if (theme.getRenderersConfig().isMarkupSupported(rendererName, markup)) {
149 addMarkupClass(rendererName, sub, markup);
150 } else if (!"none".equals(markup)) {
151 LOG.warn("Unknown markup='" + markup + "'");
152 }
153 }
154 }
155 }
156
157 public void addAspectClass(String renderer, Aspect aspect) {
158 classes.add(nameOfAspectClass(renderer, aspect));
159 }
160
161 public void removeAspectClass(String renderer, Aspect aspect) {
162 classes.remove(nameOfAspectClass(renderer, aspect));
163 }
164
165 private String nameOfAspectClass(String renderer, Aspect aspect) {
166 StringBuilder builder = new StringBuilder(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(PREFIX);
183 builder.append(renderer);
184 builder.append(SEPERATOR);
185 builder.append(sub);
186 builder.append(aspect);
187 return builder.toString();
188 }
189
190 public void addClasses(StyleClasses styleClasses) {
191 for (String clazz : (Iterable<String>) styleClasses.classes) {
192 classes.add(clazz);
193 }
194 }
195
196 public void removeClass(String clazz) {
197 classes.remove(clazz);
198 }
199
200 public void removeTobagoClasses(String rendererName) {
201 for (Iterator i = classes.iterator(); i.hasNext();) {
202 String clazz = (String) i.next();
203 if (clazz.startsWith(PREFIX + rendererName)) {
204 i.remove();
205 }
206 }
207 }
208
209 public void updateClassAttributeAndMarkup(UIComponent component, String rendererName) {
210 updateClassAttribute(component, rendererName);
211 addMarkupClass(component, rendererName);
212 }
213
214 public void updateClassAttribute(UIComponent component, String rendererName) {
215 // first remove old tobago-<rendererName>-<type> classes from class-attribute
216 removeTobagoClasses(rendererName);
217
218 addAspectClass(rendererName, Aspect.DEFAULT);
219 if (ComponentUtil.getBooleanAttribute(component, ATTR_DISABLED)) {
220 addAspectClass(rendererName, Aspect.DISABLED);
221 }
222 if (ComponentUtil.getBooleanAttribute(component, ATTR_READONLY)) {
223 addAspectClass(rendererName, Aspect.READONLY);
224 }
225 if (ComponentUtil.getBooleanAttribute(component, ATTR_INLINE)) {
226 addAspectClass(rendererName, Aspect.INLINE);
227 }
228 if (component instanceof UIInput) {
229 UIInput input = (UIInput) component;
230 if (ComponentUtil.isError(input)) {
231 addAspectClass(rendererName, Aspect.ERROR);
232 }
233 if (input.isRequired()) {
234 addAspectClass(rendererName, Aspect.REQUIRED);
235 }
236 }
237 }
238
239 @Override
240 public String toString() {
241 if (classes.isEmpty()) {
242 return null;
243 }
244 StringBuilder buffer = new StringBuilder(16 * classes.size());
245 for (Iterator i = classes.iterator(); i.hasNext();) {
246 String clazz = (String) i.next();
247 buffer.append(clazz);
248 if (i.hasNext()) {
249 buffer.append(' ');
250 }
251 }
252 return buffer.toString();
253 }
254
255 public enum Aspect {
256
257 DEFAULT,
258 DISABLED,
259 READONLY,
260 INLINE,
261 ERROR,
262 REQUIRED;
263
264 private String aspect;
265
266 Aspect() {
267 aspect = '-' + name().toLowerCase(Locale.ENGLISH);
268 }
269
270 @Override
271 public String toString() {
272 return aspect;
273 }
274 }
275 }