1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.collapsiblepanel;
20
21 import java.io.IOException;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.faces.application.Application;
26 import javax.faces.application.ViewHandler;
27 import javax.faces.component.UICommand;
28 import javax.faces.component.UIComponent;
29 import javax.faces.component.behavior.ClientBehavior;
30 import javax.faces.component.behavior.ClientBehaviorHolder;
31 import javax.faces.component.html.HtmlCommandLink;
32 import javax.faces.component.html.HtmlOutputText;
33 import javax.faces.context.FacesContext;
34 import javax.faces.context.ResponseWriter;
35 import javax.faces.convert.ConverterException;
36
37 import org.apache.myfaces.renderkit.html.util.DummyFormUtils;
38 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
39 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
40 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRenderer;
41 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
42 import org.apache.myfaces.shared_tomahawk.renderkit.html.util.ResourceUtils;
43
44
45
46
47
48
49
50
51
52
53 public class HtmlCollapsiblePanelRenderer extends HtmlRenderer {
54
55 private static final String LINK_ID = "ToggleCollapsed".intern();
56 private static final String COLLAPSED_STATE_ID = "CollapsedState".intern();
57
58 public boolean getRendersChildren() {
59 return true;
60 }
61
62 public void encodeChildren(FacesContext facesContext, UIComponent uiComponent) throws IOException {
63
64 ResponseWriter writer = facesContext.getResponseWriter();
65 HtmlCollapsiblePanel collapsiblePanel = (HtmlCollapsiblePanel) uiComponent;
66
67 UIComponent headerComp = collapsiblePanel.getFacet("header");
68
69 if (headerComp == null){
70 HtmlCommandLink link = getLink(facesContext, collapsiblePanel);
71 collapsiblePanel.getChildren().add(link);
72
73 headerComp = link;
74 }
75
76
77 HtmlRendererUtils.renderHiddenInputField(writer, collapsiblePanel.getClientId(facesContext) +
78 COLLAPSED_STATE_ID,
79 collapsiblePanel.getSubmittedValue() != null ?
80 collapsiblePanel.getSubmittedValue() : (collapsiblePanel.isCollapsed() + ""));
81
82
83 RendererUtils.renderChild(facesContext, headerComp);
84 headerComp.setRendered(false);
85
86
87 if (!collapsiblePanel.isCollapsed()) {
88 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
89
90 writer.startElement(HTML.DIV_ELEM, uiComponent);
91 RendererUtils.renderChildren(facesContext, uiComponent);
92 writer.endElement(HTML.DIV_ELEM);
93 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
94 }
95 else {
96 UIComponent component = collapsiblePanel.getFacet("closedContent");
97 if (component != null) {
98 writer.startElement(HTML.DIV_ELEM, uiComponent);
99 RendererUtils.renderChild(facesContext, component);
100 writer.endElement(HTML.DIV_ELEM);
101 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
102 }
103 }
104
105 headerComp.setRendered(true);
106 }
107
108 public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException {
109 RendererUtils.checkParamValidity(facesContext, uiComponent, HtmlCollapsiblePanel.class);
110 ResponseWriter writer = facesContext.getResponseWriter();
111
112 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
113 writer.startElement(HTML.DIV_ELEM, uiComponent);
114
115 Map<String, List<ClientBehavior>> behaviors = null;
116 if (uiComponent instanceof ClientBehaviorHolder)
117 {
118 behaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
119 if (!behaviors.isEmpty())
120 {
121 ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, facesContext.getResponseWriter());
122 }
123 }
124
125 if (behaviors != null && !behaviors.isEmpty())
126 {
127 writer.writeAttribute(HTML.ID_ATTR, uiComponent.getClientId(facesContext), null);
128 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.UNIVERSAL_ATTRIBUTES);
129 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, uiComponent, behaviors);
130 }
131 else
132 {
133 HtmlRendererUtils.writeIdIfNecessary(writer, uiComponent, facesContext);
134 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.COMMON_PASSTROUGH_ATTRIBUTES);
135 }
136
137 ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
138 String viewId = facesContext.getViewRoot().getViewId();
139 viewHandler.getActionURL(facesContext, viewId);
140
141 facesContext.getApplication();
142 }
143
144
145 public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException {
146
147 ResponseWriter writer = facesContext.getResponseWriter();
148 writer.endElement(HTML.DIV_ELEM);
149 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
150 }
151
152 public void decode(FacesContext facesContext, UIComponent uiComponent) {
153 RendererUtils.checkParamValidity(facesContext, uiComponent, HtmlCollapsiblePanel.class);
154 HtmlCollapsiblePanel collapsiblePanel = (HtmlCollapsiblePanel) uiComponent;
155
156 Map reqParams = facesContext.getExternalContext().getRequestParameterMap();
157
158 String togglingIndicated = (String) reqParams.get(HtmlRendererUtils
159 .getHiddenCommandLinkFieldName(
160 DummyFormUtils.findNestingForm(collapsiblePanel, facesContext)));
161
162
163
164 if (togglingIndicated == null
165 && reqParams.containsKey(collapsiblePanel.getClientId(facesContext) + LINK_ID)) {
166 togglingIndicated = collapsiblePanel.getClientId(facesContext) + LINK_ID;
167 }
168
169 String reqValue = (String) reqParams.get(
170 collapsiblePanel.getClientId(facesContext) + COLLAPSED_STATE_ID);
171
172 collapsiblePanel.setCurrentlyCollapsed(HtmlCollapsiblePanel.isCollapsed(reqValue));
173
174 if ((collapsiblePanel.getClientId(facesContext) + LINK_ID).equals(togglingIndicated)) {
175 if (reqValue != null)
176 {
177 collapsiblePanel.setSubmittedValue("" + !collapsiblePanel.isCurrentlyCollapsed());
178 }
179 else
180 {
181 collapsiblePanel.setSubmittedValue("" + !collapsiblePanel.isCollapsed());
182 }
183
184 UIComponent header = collapsiblePanel.getFacet("header");
185
186 if (header != null)
187 {
188 UICommand link = (UICommand)RendererUtils.findComponent(header,HtmlHeaderLink.class);
189
190 if (link != null && link.isImmediate())
191 {
192
193
194
195
196
197
198 Object convertedValue = getConvertedValue(facesContext,collapsiblePanel,
199 collapsiblePanel.getSubmittedValue());
200
201 collapsiblePanel.setValue(convertedValue);
202 collapsiblePanel.setSubmittedValue(null);
203 collapsiblePanel.updateModel(facesContext);
204 }
205 }
206 }
207 else {
208 if (reqValue != null)
209 collapsiblePanel.setSubmittedValue("" + collapsiblePanel.isCurrentlyCollapsed());
210 }
211
212 HtmlRendererUtils.decodeClientBehaviors(facesContext, uiComponent);
213 }
214
215 protected HtmlCommandLink getLink(FacesContext facesContext, HtmlCollapsiblePanel collapsiblePanel)
216 throws IOException {
217 Application application = facesContext.getApplication();
218 HtmlCommandLink link = (HtmlCommandLink) application.createComponent(HtmlCommandLink.COMPONENT_TYPE);
219 link.setId(collapsiblePanel.getId() + LINK_ID);
220 link.setTransient(true);
221 link.setImmediate(true);
222
223 List<UIComponent> children = link.getChildren();
224
225 HtmlOutputText uiText = (HtmlOutputText) application.createComponent(HtmlOutputText.COMPONENT_TYPE);
226 uiText.setTransient(true);
227 uiText.setValue(collapsiblePanel.isCollapsed() ? ">" : "ν");
228 uiText.setEscape(false);
229 uiText.setStyleClass(collapsiblePanel.getIndicatorStyleClass());
230 uiText.setStyle(collapsiblePanel.getIndicatorStyle());
231 children.add(uiText);
232
233
234 String label = collapsiblePanel.getTitle();
235 if (label != null) {
236 uiText = (HtmlOutputText) application.createComponent(HtmlOutputText.COMPONENT_TYPE);
237 uiText.setTransient(true);
238 uiText.setValue(" " + label);
239 uiText.setStyleClass(collapsiblePanel.getTitleStyleClass());
240 uiText.setStyle(collapsiblePanel.getTitleStyle());
241 children.add(uiText);
242 }
243 return link;
244 }
245
246 public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException {
247 if (submittedValue instanceof String) {
248 return Boolean.valueOf((String) submittedValue);
249 }
250
251 return super.getConvertedValue(context, component, submittedValue);
252 }
253 }