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.UITreeNode;
23  import org.apache.myfaces.tobago.component.UITreeSelect;
24  import org.apache.myfaces.tobago.context.Markup;
25  import org.apache.myfaces.tobago.event.TreeExpansionEvent;
26  import org.apache.myfaces.tobago.event.TreeMarkedEvent;
27  import org.apache.myfaces.tobago.internal.component.AbstractUITree;
28  import org.apache.myfaces.tobago.model.Selectable;
29  import org.apache.myfaces.tobago.renderkit.CommandRendererBase;
30  import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
31  import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
32  import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
33  import org.apache.myfaces.tobago.util.ComponentUtils;
34  import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  import javax.faces.component.UIComponent;
39  import javax.faces.component.UINamingContainer;
40  import javax.faces.context.FacesContext;
41  import java.io.IOException;
42  import java.util.Map;
43  
44  public class TreeListboxNodeRenderer extends CommandRendererBase {
45  
46    private static final Logger LOG = LoggerFactory.getLogger(TreeListboxNodeRenderer.class);
47  
48    // TODO cleanup: there might be some stuff to remove after tree refactoring
49  
50    @Override
51    public void decode(FacesContext facesContext, UIComponent component) {
52  
53      UITreeNode node = (UITreeNode) component;
54  
55      super.decode(facesContext, node);
56  
57      if (ComponentUtils.isOutputOnly(node)) {
58        return;
59      }
60  
61      final AbstractUITree tree = ComponentUtils.findAncestor(node, AbstractUITree.class);
62      final String treeId = tree.getClientId(facesContext);
63      final String nodeStateId = node.nodeStateId(facesContext);
64      final Map<String, String> requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
65      final String id = node.getClientId(facesContext);
66      final boolean folder = node.isFolder();
67  
68      // expand state
69      if (folder) {
70        boolean expanded = Boolean.parseBoolean(requestParameterMap.get(id + "-expanded"));
71        if (node.isExpanded() != expanded) {
72          new TreeExpansionEvent(node, node.isExpanded(), expanded).queue();
73        }
74      }
75  
76      // select
77      if (tree.getSelectableAsEnum() != Selectable.NONE) { // selection
78        String selected = requestParameterMap.get(treeId + AbstractUITree.SELECT_STATE);
79        String searchString = ";" + node.getClientId(facesContext) + ";";
80        UITreeSelect treeSelect = ComponentUtils.findDescendant(node, UITreeSelect.class);
81        if (treeSelect != null) {
82          treeSelect.setSubmittedValue(selected.contains(searchString));
83        }
84      }
85  
86      // marked
87      String marked = requestParameterMap.get(treeId + ComponentUtils.SUB_SEPARATOR + AbstractUITree.SUFFIX_MARKED);
88      if (marked != null) {
89        String searchString = treeId + UINamingContainer.getSeparatorChar(facesContext) + nodeStateId;
90        boolean markedValue = marked.equals(searchString);
91        if (node.isMarked() != markedValue) {
92          new TreeMarkedEvent(node, node.isMarked(), markedValue).queue();
93        }
94      } else {
95        LOG.warn("This log message is help clarifying the occurrence of this else case.");
96      }
97    }
98  
99    @Override
100   public void prepareRender(FacesContext facesContext, UIComponent component) throws IOException {
101     super.prepareRender(facesContext, component);
102 
103     final UITreeNode node = (UITreeNode) component;
104     if (node.isMarked()) {
105       node.setMarkup(Markup.MARKED.add(node.getMarkup()));
106     }
107   }
108 
109   @Override
110   public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
111     final UITreeNode node = (UITreeNode) component;
112     final boolean folder = node.isFolder();
113     final String id = node.getClientId(facesContext);
114     final boolean expanded = folder && node.isExpanded();
115 
116     final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
117 
118     writer.startElement(HtmlElements.OPTION, null);
119     // todo: define where to store the selection of a tree, node.getValue() seems not to be a god place.
120     //        writer.writeAttribute(HtmlAttributes.VALUE, node.getValue().toString(), true); // XXX converter?
121     writer.writeAttribute(HtmlAttributes.VALUE, id, true);
122     writer.writeIdAttribute(id);
123     writer.writeAttribute(HtmlAttributes.SELECTED, expanded);
124   }
125 
126   @Override
127   public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
128     final UITreeNode node = (UITreeNode) component;
129     final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
130     final boolean folder = node.isFolder();
131 
132     if (folder) {
133       writer.writeText(" \u2192"); // this is an right arrow →
134     }
135     writer.endElement(HtmlElements.OPTION);
136   }
137 }