View Javadoc
1   /*
2    * Copyright (c) 2011-2024 PrimeFaces Extensions
3    *
4    *  Permission is hereby granted, free of charge, to any person obtaining a copy
5    *  of this software and associated documentation files (the "Software"), to deal
6    *  in the Software without restriction, including without limitation the rights
7    *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    *  copies of the Software, and to permit persons to whom the Software is
9    *  furnished to do so, subject to the following conditions:
10   *
11   *  The above copyright notice and this permission notice shall be included in
12   *  all copies or substantial portions of the Software.
13   *
14   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   *  THE SOFTWARE.
21   */
22  package org.primefaces.extensions.component.layout;
23  
24  import java.io.IOException;
25  
26  import javax.el.ValueExpression;
27  import javax.faces.component.UIComponent;
28  import javax.faces.context.FacesContext;
29  import javax.faces.context.ResponseWriter;
30  
31  import org.primefaces.extensions.model.layout.LayoutOptions;
32  import org.primefaces.extensions.util.Attrs;
33  import org.primefaces.renderkit.CoreRenderer;
34  import org.primefaces.util.FastStringWriter;
35  import org.primefaces.util.LangUtils;
36  import org.primefaces.util.WidgetBuilder;
37  
38  /**
39   * Renderer for the {@link Layout} component.
40   *
41   * @author Oleg Varaksin / last modified by Melloware
42   * @since 0.2
43   */
44  public class LayoutRenderer extends CoreRenderer {
45  
46      @Override
47      public void decode(final FacesContext fc, final UIComponent component) {
48          decodeBehaviors(fc, component);
49      }
50  
51      @Override
52      public void encodeBegin(final FacesContext fc, final UIComponent component) throws IOException {
53          ResponseWriter writer = fc.getResponseWriter();
54          final Layout layout = (Layout) component;
55  
56          final boolean buildOptions = layout.getOptions() == null;
57          layout.setBuildOptions(buildOptions);
58  
59          if (buildOptions) {
60              final FastStringWriter fsw = new FastStringWriter();
61              layout.setOriginalWriter(writer);
62              layout.setFastStringWriter(fsw);
63              fc.setResponseWriter(writer.cloneWithWriter(fsw));
64              writer = fc.getResponseWriter();
65          }
66  
67          if (layout.isElementLayout()) {
68              writer.startElement("div", layout);
69              writer.writeAttribute("id", layout.getClientId(fc), "id");
70  
71              if (layout.getStyle() != null) {
72                  writer.writeAttribute(Attrs.STYLE, layout.getStyle(), Attrs.STYLE);
73              }
74  
75              if (layout.getStyleClass() != null) {
76                  writer.writeAttribute(Attrs.CLASS, layout.getStyleClass(), "styleClass");
77              }
78          }
79      }
80  
81      @Override
82      public void encodeEnd(final FacesContext fc, final UIComponent component) throws IOException {
83          final ResponseWriter writer = fc.getResponseWriter();
84          final Layout layout = (Layout) component;
85  
86          if (layout.isElementLayout()) {
87              if (!layout.isStateCookie()) {
88                  // render hidden field for server-side state saving
89                  final String clientId = layout.getClientId(fc);
90                  renderHiddenInput(fc, clientId + "_state", null, false);
91              }
92  
93              writer.endElement("div");
94          }
95  
96          if (layout.isBuildOptions()) {
97              fc.setResponseWriter(layout.getOriginalWriter());
98              encodeScript(fc, layout);
99              fc.getResponseWriter().write(layout.getFastStringWriter().toString());
100             layout.removeOptions();
101             layout.setOriginalWriter(null);
102             layout.setFastStringWriter(null);
103         }
104         else {
105             encodeScript(fc, layout);
106         }
107 
108         layout.setBuildOptions(false);
109     }
110 
111     protected void encodeScript(final FacesContext fc, final Layout layout) throws IOException {
112         final WidgetBuilder wb = getWidgetBuilder(fc);
113         wb.init("ExtLayout", layout);
114         wb.attr("clientState", layout.isStateCookie());
115         wb.attr("full", layout.isFullPage(), false);
116 
117         if (layout.isNested()) {
118             wb.attr("parent", layout.getParent().getClientId(fc));
119         }
120 
121         final ValueExpression stateVE = layout.getValueExpression(Layout.PropertyKeys.state.toString());
122         if (stateVE != null && !layout.isFullPage() && !layout.isStateCookie()) {
123             wb.attr("serverState", true);
124 
125             final String state = layout.getState();
126             if (LangUtils.isNotBlank(state)) {
127                 wb.attr("state", state);
128             }
129             else {
130                 wb.nativeAttr("state", "{}");
131             }
132         }
133         else {
134             wb.attr("serverState", false);
135         }
136 
137         final Object layoutOptions = layout.getOptions();
138         if (layoutOptions instanceof LayoutOptions) {
139             final LayoutOptions options = (LayoutOptions) layoutOptions;
140             wb.append(",options:" + options.toJson());
141         }
142         else if (layoutOptions instanceof String) {
143             // already serialized as JSON string
144             wb.append(",options:" + layoutOptions);
145         }
146         else {
147             wb.append(",options:{}");
148         }
149 
150         encodeClientBehaviors(fc, layout);
151 
152         wb.finish();
153     }
154 }