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.Facets;
24  import org.apache.myfaces.tobago.component.UIButton;
25  import org.apache.myfaces.tobago.config.Configurable;
26  import org.apache.myfaces.tobago.context.ResourceManagerUtils;
27  import org.apache.myfaces.tobago.internal.component.AbstractUIForm;
28  import org.apache.myfaces.tobago.internal.util.AccessKeyMap;
29  import org.apache.myfaces.tobago.layout.Measure;
30  import org.apache.myfaces.tobago.renderkit.CommandRendererBase;
31  import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
32  import org.apache.myfaces.tobago.renderkit.css.Classes;
33  import org.apache.myfaces.tobago.renderkit.css.Style;
34  import org.apache.myfaces.tobago.renderkit.html.Command;
35  import org.apache.myfaces.tobago.renderkit.html.CommandMap;
36  import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
37  import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
38  import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
39  import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
40  import org.apache.myfaces.tobago.renderkit.html.JsonUtils;
41  import org.apache.myfaces.tobago.renderkit.html.Popup;
42  import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
43  import org.apache.myfaces.tobago.renderkit.util.RenderUtils;
44  import org.apache.myfaces.tobago.util.ComponentUtils;
45  import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
46  import org.slf4j.Logger;
47  import org.slf4j.LoggerFactory;
48  
49  import javax.faces.component.UIComponent;
50  import javax.faces.component.ValueHolder;
51  import javax.faces.context.FacesContext;
52  import java.io.IOException;
53  
54  public class ButtonRenderer extends CommandRendererBase {
55  
56    private static final Logger LOG = LoggerFactory.getLogger(ButtonRenderer.class);
57  
58    public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
59  
60      final UIButton button = (UIButton) component;
61      final String clientId = button.getClientId(facesContext);
62      final boolean disabled = button.isDisabled();
63      final LabelWithAccessKey label = new LabelWithAccessKey(button);
64  
65      final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
66  
67      writer.startElement(HtmlElements.BUTTON, button);
68      writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON, false);
69      writer.writeNameAttribute(clientId);
70      writer.writeIdAttribute(clientId);
71      HtmlRendererUtils.writeDataAttributes(facesContext, writer, button);
72      HtmlRendererUtils.renderTip(button, writer);
73      writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
74  
75      if (!disabled) {
76        final ValueHolder confirmationFacet = (ValueHolder) component.getFacet(Facets.CONFIRMATION);
77        final String confirmation = confirmationFacet != null ? "" + confirmationFacet.getValue() : null;
78  
79        final String url = RenderUtils.generateUrl(facesContext, button);
80        final CommandMap map = new CommandMap();
81        final String[] partialIds
82            = HtmlRendererUtils.getComponentIdsAsList(facesContext, button, button.getRenderedPartially());
83        final Popup popup = Popup.createPopup(button);
84        final Command click = new Command(
85            null, button.isTransition(), button.getTarget(), url, partialIds, null, confirmation, null, popup);
86        if (button.getOnclick() != null) {
87          click.setScript(button.getOnclick());
88        }
89        map.setClick(click);
90        writer.writeAttribute(DataAttributes.COMMANDS, JsonUtils.encode(map), true);
91  
92        writer.writeAttribute(HtmlAttributes.HREF, "#", false);
93  
94        if (label.getAccessKey() != null) {
95          writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
96        }
97  
98        final Integer tabIndex = button.getTabIndex();
99        if (tabIndex != null) {
100         writer.writeAttribute(HtmlAttributes.TABINDEX, tabIndex);
101       }
102     }
103 
104     Style style = new Style(facesContext, button);
105     writer.writeStyleAttribute(style);
106     HtmlRendererUtils.renderDojoDndItem(component, writer, true);
107     writer.writeClassAttribute(Classes.create(button));
108     if (((UIButton) component).isDefaultCommand()) {
109       final AbstractUIForm form = ComponentUtils.findAncestor(component, AbstractUIForm.class);
110       writer.writeAttribute(DataAttributes.DEFAULT, form.getClientId(facesContext), false);
111     }
112     writer.flush(); // force closing the start tag
113 
114     String image = (String) button.getAttributes().get(Attributes.IMAGE);
115     if (image != null) {
116       if (ResourceManagerUtils.isAbsoluteResource(image)) {
117         // absolute Path to image : nothing to do
118       } else {
119         image = getImageWithPath(facesContext, image, disabled);
120       }
121       writer.startElement(HtmlElements.IMG, null);
122       writer.writeAttribute(HtmlAttributes.SRC, image, true);
123       String tip = button.getTip();
124       writer.writeAttribute(HtmlAttributes.ALT, tip != null ? tip : "", true);
125       writer.endElement(HtmlElements.IMG);
126     }
127 
128     if (label.getText() != null) {
129       writer.startElement(HtmlElements.SPAN, null);
130       HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
131       writer.endElement(HtmlElements.SPAN);
132     }
133 
134     writer.endElement(HtmlElements.BUTTON);
135     if (label.getAccessKey() != null) {
136       if (LOG.isInfoEnabled()
137           && !AccessKeyMap.addAccessKey(facesContext, label.getAccessKey())) {
138         LOG.info("duplicated accessKey : " + label.getAccessKey());
139       }
140       HtmlRendererUtils.addClickAcceleratorKey(
141           facesContext, button.getClientId(facesContext), label.getAccessKey());
142     }
143   }
144 
145   @Override
146   public Measure getPreferredWidth(FacesContext facesContext, Configurable component) {
147 
148     UIButton button = (UIButton) component;
149     Measure width = Measure.ZERO;
150     boolean image = button.getImage() != null;
151     if (image) {
152       width = getResourceManager().getThemeMeasure(facesContext, button, "imageWidth");
153     }
154     LabelWithAccessKey label = new LabelWithAccessKey(button);
155 
156     width = width.add(RenderUtils.calculateStringWidth(facesContext, button, label.getText()));
157     Measure padding = getResourceManager().getThemeMeasure(facesContext, button, "paddingWidth");
158     // left padding, right padding and when an image and an text then a middle padding.
159     width = width.add(padding.multiply(image && label.getText() != null ? 3 : 2));
160 
161     return width;
162   }
163 }