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