View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.renderkit.html.scarborough.standard.tag;
21  
22  import org.apache.myfaces.tobago.component.Attributes;
23  import org.apache.myfaces.tobago.component.UIButton;
24  import org.apache.myfaces.tobago.config.Configurable;
25  import org.apache.myfaces.tobago.context.ResourceManagerUtils;
26  import org.apache.myfaces.tobago.internal.component.AbstractUIForm;
27  import org.apache.myfaces.tobago.internal.util.AccessKeyMap;
28  import org.apache.myfaces.tobago.layout.Measure;
29  import org.apache.myfaces.tobago.renderkit.CommandRendererBase;
30  import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
31  import org.apache.myfaces.tobago.renderkit.css.Classes;
32  import org.apache.myfaces.tobago.renderkit.css.Style;
33  import org.apache.myfaces.tobago.renderkit.html.Command;
34  import org.apache.myfaces.tobago.renderkit.html.CommandMap;
35  import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
36  import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
37  import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
38  import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
39  import org.apache.myfaces.tobago.renderkit.html.JsonUtils;
40  import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
41  import org.apache.myfaces.tobago.renderkit.util.RenderUtils;
42  import org.apache.myfaces.tobago.util.ComponentUtils;
43  import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
44  import org.slf4j.Logger;
45  import org.slf4j.LoggerFactory;
46  
47  import javax.faces.component.UIComponent;
48  import javax.faces.context.FacesContext;
49  import java.io.IOException;
50  
51  public class ButtonRenderer extends CommandRendererBase {
52  
53    private static final Logger LOG = LoggerFactory.getLogger(ButtonRenderer.class);
54  
55    public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
56  
57      final UIButton button = (UIButton) component;
58      final String clientId = button.getClientId(facesContext);
59      final boolean disabled = button.isDisabled();
60      final LabelWithAccessKey label = new LabelWithAccessKey(button);
61  
62      final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
63  
64      writer.startElement(HtmlElements.BUTTON, button);
65      writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON, false);
66      writer.writeNameAttribute(clientId);
67      writer.writeIdAttribute(clientId);
68      HtmlRendererUtils.writeDataAttributes(facesContext, writer, button);
69      HtmlRendererUtils.renderTip(button, writer);
70      writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
71  
72      if (!disabled) {
73        final CommandMap map = new CommandMap(new Command(facesContext, button));
74        writer.writeAttribute(DataAttributes.COMMANDS, JsonUtils.encode(map), true);
75  
76        writer.writeAttribute(HtmlAttributes.HREF, "#", false);
77  
78        if (label.getAccessKey() != null) {
79          writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
80        }
81  
82        final Integer tabIndex = button.getTabIndex();
83        if (tabIndex != null) {
84          writer.writeAttribute(HtmlAttributes.TABINDEX, tabIndex);
85        }
86      }
87  
88      Style style = new Style(facesContext, button);
89      writer.writeStyleAttribute(style);
90      HtmlRendererUtils.renderDojoDndItem(component, writer, true);
91      writer.writeClassAttribute(Classes.create(button));
92      if (((UIButton) component).isDefaultCommand()) {
93        final AbstractUIForm form = ComponentUtils.findAncestor(component, AbstractUIForm.class);
94        writer.writeAttribute(DataAttributes.DEFAULT, form.getClientId(facesContext), false);
95      }
96      writer.flush(); // force closing the start tag
97  
98      String image = (String) button.getAttributes().get(Attributes.IMAGE);
99      if (image != null) {
100       if (ResourceManagerUtils.isAbsoluteResource(image)) {
101         // absolute Path to image : nothing to do
102       } else {
103         image = getImageWithPath(facesContext, image, disabled);
104       }
105       writer.startElement(HtmlElements.IMG, null);
106       writer.writeAttribute(HtmlAttributes.SRC, image, true);
107       String tip = button.getTip();
108       writer.writeAttribute(HtmlAttributes.ALT, tip != null ? tip : "", true);
109       writer.endElement(HtmlElements.IMG);
110     }
111 
112     if (label.getText() != null) {
113       writer.startElement(HtmlElements.SPAN, null);
114       HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
115       writer.endElement(HtmlElements.SPAN);
116     }
117 
118     writer.endElement(HtmlElements.BUTTON);
119     if (label.getAccessKey() != null) {
120       if (LOG.isInfoEnabled()
121           && !AccessKeyMap.addAccessKey(facesContext, label.getAccessKey())) {
122         LOG.info("duplicated accessKey : " + label.getAccessKey());
123       }
124       HtmlRendererUtils.addClickAcceleratorKey(
125           facesContext, button.getClientId(facesContext), label.getAccessKey());
126     }
127   }
128 
129   @Override
130   public Measure getPreferredWidth(FacesContext facesContext, Configurable component) {
131 
132     UIButton button = (UIButton) component;
133     Measure width = Measure.ZERO;
134     boolean image = button.getImage() != null;
135     if (image) {
136       width = getResourceManager().getThemeMeasure(facesContext, button, "imageWidth");
137     }
138     LabelWithAccessKey label = new LabelWithAccessKey(button);
139 
140     width = width.add(RenderUtils.calculateStringWidth(facesContext, button, label.getText()));
141     Measure padding = getResourceManager().getThemeMeasure(facesContext, button, "paddingWidth");
142     // left padding, right padding and when an image and an text then a middle padding.
143     width = width.add(padding.multiply(image && label.getText() != null ? 3 : 2));
144 
145     return width;
146   }
147 }