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.config.Configurable;
23  import org.apache.myfaces.tobago.context.ResourceManagerUtils;
24  import org.apache.myfaces.tobago.internal.component.AbstractUILink;
25  import org.apache.myfaces.tobago.internal.util.AccessKeyMap;
26  import org.apache.myfaces.tobago.layout.Measure;
27  import org.apache.myfaces.tobago.layout.PixelMeasure;
28  import org.apache.myfaces.tobago.renderkit.CommandRendererBase;
29  import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
30  import org.apache.myfaces.tobago.renderkit.css.Classes;
31  import org.apache.myfaces.tobago.renderkit.css.Style;
32  import org.apache.myfaces.tobago.renderkit.html.Command;
33  import org.apache.myfaces.tobago.renderkit.html.CommandMap;
34  import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
35  import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
36  import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
37  import org.apache.myfaces.tobago.renderkit.html.JsonUtils;
38  import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
39  import org.apache.myfaces.tobago.renderkit.util.RenderUtils;
40  import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
41  import org.slf4j.Logger;
42  import org.slf4j.LoggerFactory;
43  
44  import javax.faces.component.UIComponent;
45  import javax.faces.context.FacesContext;
46  import javax.faces.context.ResponseWriter;
47  import java.io.IOException;
48  
49  public class LinkRenderer extends CommandRendererBase {
50  
51    private static final Logger LOG = LoggerFactory.getLogger(LinkRenderer.class);
52  
53    public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
54  
55      final AbstractUILink link = (AbstractUILink) component;
56      final String clientId = link.getClientId(facesContext);
57      final boolean disabled = link.isDisabled();
58  // final CommandRendererHelper helper = new CommandRendererHelper(facesContext, link, CommandRendererHelper.Tag.ANCHOR);
59  // final String href = helper.getHref();
60  
61      final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
62  
63      LabelWithAccessKey label = new LabelWithAccessKey(link);
64  
65      if (disabled) {
66        writer.startElement(HtmlElements.SPAN, link);
67      } else {
68        writer.startElement(HtmlElements.A, link);
69  //      writer.writeAttribute(HtmlAttributes.HREF, href, true); XXX
70  
71        final CommandMap map = new CommandMap(new Command(facesContext, link));
72        writer.writeAttribute(DataAttributes.COMMANDS, JsonUtils.encode(map), true);
73  
74        writer.writeAttribute(HtmlAttributes.HREF, "#", false);
75  
76        if (label.getAccessKey() != null) {
77          writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
78        }
79  
80        final Integer tabIndex = link.getTabIndex();
81        if (tabIndex != null) {
82          writer.writeAttribute(HtmlAttributes.TABINDEX, tabIndex);
83        }
84      }
85      HtmlRendererUtils.writeDataAttributes(facesContext, writer, link);
86      Style style = new Style(facesContext, link);
87      writer.writeStyleAttribute(style);
88      HtmlRendererUtils.renderDojoDndItem(component, writer, true);
89      writer.writeClassAttribute(Classes.create(link));
90      writer.writeIdAttribute(clientId);
91      writer.writeNameAttribute(clientId);
92      HtmlRendererUtils.renderTip(link, writer);
93      writer.flush();
94  
95  //  image
96      String image = link.getImage();
97      if (image != null) {
98        if (ResourceManagerUtils.isAbsoluteResource(image)) {
99          // absolute Path to image : nothing to do
100       } else {
101         image = getImageWithPath(facesContext, image, disabled);
102       }
103       writer.startElement(HtmlElements.IMG, link);
104       writer.writeClassAttribute(Classes.create(link, "image"));
105       writer.writeAttribute(HtmlAttributes.SRC, image, true);
106       writer.writeAttribute(HtmlAttributes.BORDER, 0); // TODO: is border=0 setting via style possible?
107       String tip = link.getTip();
108       writer.writeAttribute(HtmlAttributes.ALT, tip != null ? tip : "", true);
109       if (tip != null) {
110         writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
111       }
112       writer.endElement(HtmlElements.IMG);
113     }
114 
115 //  label
116     if (label.getText() != null) {
117       if (image != null) {
118         writer.write(" "); // separator: e.g.  
119       }
120       HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
121     }
122 
123     if (label.getAccessKey() != null && !disabled) {
124       if (LOG.isInfoEnabled()
125           && !AccessKeyMap.addAccessKey(facesContext, label.getAccessKey())) {
126         LOG.info("duplicated accessKey : " + label.getAccessKey());
127       }
128 
129       //HtmlRendererUtils.addClickAcceleratorKey(facesContext, clientId, label.getAccessKey());
130     }
131   }
132 
133   public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
134     AbstractUILink link = (AbstractUILink) component;
135     ResponseWriter writer = facesContext.getResponseWriter();
136     if (link.isDisabled()) {
137       writer.endElement(HtmlElements.SPAN);
138     } else {
139       writer.endElement(HtmlElements.A);
140     }
141   }
142 
143   @Override
144   public Measure getPreferredWidth(FacesContext facesContext, Configurable component) {
145     final AbstractUILink link = (AbstractUILink) component;
146     final LabelWithAccessKey label = new LabelWithAccessKey(link);
147     final String text = label.getText();
148     final String image = link.getImage();
149 
150     Measure width = PixelMeasure.ZERO;
151     if (text != null) {
152       final Measure m = RenderUtils.calculateStringWidth(facesContext, link, text);
153       width = width.add(m);
154     }
155     if ((text != null && image != null)) {
156       width = width.add(4);
157     }
158     if (image != null) {
159       width = width.add(16);
160     }
161     return width;
162   }
163 }