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 }