001: package org.andromda.cartridges.jsf.renderkit.html;
002:
003: import java.io.IOException;
004:
005: import java.util.Iterator;
006: import java.util.Map;
007:
008: import javax.faces.component.NamingContainer;
009: import javax.faces.component.UICommand;
010: import javax.faces.component.UIComponent;
011: import javax.faces.component.UIForm;
012: import javax.faces.component.UIViewRoot;
013: import javax.faces.context.FacesContext;
014: import javax.faces.context.ResponseWriter;
015: import javax.faces.el.MethodBinding;
016: import javax.faces.event.ActionEvent;
017: import javax.faces.render.Renderer;
018:
019: import javax.servlet.http.HttpServletRequest;
020:
021: import org.andromda.cartridges.jsf.Constants;
022: import org.andromda.cartridges.jsf.component.html.HtmlPopupFrame;
023:
024: /**
025: * A custom renderer for rendering a popup frame.
026: */
027: public class PopupRenderer extends Renderer {
028: public static final String POPUP_FRAME_HIDDEN = "hiddenPopupFrame";
029:
030: /**
031: * Retrieves the current request instance.
032: *
033: * @return the current request.
034: */
035: private HttpServletRequest getRequest() {
036: return (HttpServletRequest) FacesContext.getCurrentInstance()
037: .getExternalContext().getRequest();
038: }
039:
040: /**
041: * Retrieve the popup resource path (the path within the
042: * deployed web application) given the relative <code>path</code>
043: *
044: * @param path the relative path.
045: * @return the complete path including the context path of the application.
046: */
047: private String getPopupResourcePath(final String path) {
048: return getRequest().getContextPath()
049: + Constants.RESOURCE_CONTEXT + path;
050: }
051:
052: /**
053: * keeps track of whether or not the javascript has been rendered.
054: */
055: private static final String JS_ATTRIBUTE = "andromda.jsf.js";
056:
057: protected void commonJavascript(final FacesContext context,
058: final UIComponent component) throws IOException {
059: final ResponseWriter writer = context.getResponseWriter();
060: if (this .getRequest().getAttribute(JS_ATTRIBUTE) == null) {
061: getRequest().setAttribute(JS_ATTRIBUTE, JS_ATTRIBUTE);
062: writer.startElement("script", component);
063: writer.writeAttribute("language", "JavaScript", null);
064: writer.writeAttribute("src",
065: getPopupResourcePath("/popup/js/popup.js"), null);
066: writer.endElement("script");
067: }
068: writer.startElement("input", null);
069: writer.writeAttribute("type", "hidden", null);
070: writer.writeAttribute("name", POPUP_FRAME_HIDDEN, null);
071: writer.writeAttribute("value", "", null);
072: writer.endElement("input");
073: }
074:
075: private static final String DEFAULT_STYLE = "position:absolute; left:0; top:0; visibility:hidden; border:1px solid black; background-color:#FFFFFF; ";
076:
077: /**
078: * @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
079: */
080: public void decode(final FacesContext context,
081: final UIComponent component) {
082: final HtmlPopupFrame command = (HtmlPopupFrame) component;
083: final Map parameters = context.getExternalContext()
084: .getRequestParameterMap();
085: final String popupAction = (String) parameters
086: .get(PopupRenderer.POPUP_FRAME_HIDDEN);
087: if (popupAction != null
088: && popupAction.equals(getHiddenFieldOpen(command,
089: context))) {
090: final MethodBinding binding = command.getActionOpen();
091: command.setAction(binding);
092: final ActionEvent actionEvent = new ActionEvent(command);
093: if (command.isImmediate()) {
094: command.queueEventImmediate(actionEvent);
095: } else {
096: command.queueEventNormal(actionEvent);
097: }
098: } else if (popupAction != null
099: && popupAction.equals(getHiddenFieldClose(command,
100: context))) {
101: final MethodBinding binding = command.getActionClose();
102: if (binding != null) {
103: command.setAction(binding);
104: ActionEvent actionEvent = new ActionEvent(command);
105: command.queueEventImmediate(actionEvent);
106: }
107: }
108: }
109:
110: /**
111: * @see javax.faces.render.Renderer#getRendersChildren()
112: */
113: public boolean getRendersChildren() {
114: return true;
115: }
116:
117: private String getHiddenFieldOpen(HtmlPopupFrame command,
118: FacesContext context) {
119: return command.getClientId(context)
120: + NamingContainer.SEPARATOR_CHAR
121: + UIViewRoot.UNIQUE_ID_PREFIX + "op";
122: }
123:
124: private String getHiddenFieldClose(HtmlPopupFrame command,
125: FacesContext context) {
126: return command.getClientId(context)
127: + NamingContainer.SEPARATOR_CHAR
128: + UIViewRoot.UNIQUE_ID_PREFIX + "cl";
129: }
130:
131: /**
132: * @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
133: */
134: public void encodeBegin(FacesContext context, UIComponent component)
135: throws IOException {
136: final HtmlPopupFrame command = (HtmlPopupFrame) component;
137: if (command.isRendered()) {
138: final UIForm uiform = this .getForm(context, command);
139: if (uiform == null) {
140: throw new RuntimeException(
141: "JSF h:form needed to use this component");
142: }
143:
144: final String formClientId = uiform.getClientId(context);
145:
146: // start differences from command link
147: final ResponseWriter writer = context.getResponseWriter();
148: commonJavascript(context, command);
149:
150: writer.startElement("a", command);
151: writer.writeAttribute("href", "#", null);
152:
153: String form = "document.forms['" + formClientId + "']";
154:
155: StringBuffer buffer = new StringBuffer();
156: buffer.append("showPopupFrame(");
157: buffer.append(form);
158: buffer.append(",this,event");
159: buffer.append(",'");
160: buffer.append(getHiddenFieldClose(command, context));
161: buffer.append("','");
162: buffer.append(command.getStyleClassFrame() == null ? ""
163: : command.getStyleClassFrame());
164: buffer.append("','");
165: buffer.append(DEFAULT_STYLE);
166: buffer.append(command.getStyleFrame() == null ? ""
167: : command.getStyleFrame());
168: buffer.append("',");
169: buffer.append(command.getMouseHorizPos() == null ? "0"
170: : command.getMouseHorizPos());
171: buffer.append(",");
172: buffer.append(command.getMouseVertPos() == null ? "0"
173: : command.getMouseVertPos());
174: buffer.append(",");
175: buffer.append(command.getAbsolute() == null ? "false"
176: : command.getAbsolute());
177: buffer.append(",");
178: buffer.append(command.getCenter() == null ? "false"
179: : command.getCenter());
180: buffer.append(",'");
181: buffer.append(command.getHeight() == null ? "" : command
182: .getHeight());
183: buffer.append("','");
184: buffer.append(command.getWidth() == null ? "" : command
185: .getWidth());
186: buffer.append("','");
187: buffer.append(command.getScrolling() == null ? "auto"
188: : command.getScrolling().toLowerCase());
189: buffer.append("');");
190:
191: buffer.append(form);
192: buffer.append(".target='");
193: buffer.append("hiddenPopupFrameTarget");
194: buffer.append("';");
195:
196: buffer.append(form);
197: buffer.append(".elements['");
198: buffer.append(POPUP_FRAME_HIDDEN);
199: buffer.append("'].value='");
200: buffer.append(getHiddenFieldOpen(command, context));
201: buffer.append("';");
202:
203: buffer.append(form);
204: buffer.append(".submit();");
205: buffer.append(form);
206: buffer.append(".elements['");
207: buffer.append(POPUP_FRAME_HIDDEN);
208: buffer.append("'].value='';");
209:
210: buffer.append(form);
211: buffer.append(".target='';");
212:
213: buffer.append("return false;");
214:
215: writer.writeAttribute("onclick", buffer.toString(), null);
216:
217: writer.writeAttribute("id", command.getClientId(context),
218: null);
219:
220: final String accesskey = command.getAccesskey();
221: if (accesskey != null) {
222: writer.writeAttribute("accesskey", accesskey,
223: "accesskey");
224: }
225:
226: final String directory = command.getDir();
227: if (directory != null) {
228: writer.writeAttribute("dir", directory, "dir");
229: }
230:
231: final String lang = command.getLang();
232: if (lang != null) {
233: writer.writeAttribute("lang", lang, "lang");
234: }
235:
236: final String tabindex = command.getTabindex();
237: if (tabindex != null) {
238: writer.writeAttribute("tabindex", tabindex, "tabindex");
239: }
240:
241: final String title = command.getTitle();
242: if (title != null) {
243: writer.writeAttribute("title", title, "title");
244: }
245:
246: final String styleClass = command.getStyleClass();
247: if (styleClass != null) {
248: writer
249: .writeAttribute("class", styleClass,
250: "styleClass");
251: }
252:
253: final String style = command.getStyle();
254: if (style != null) {
255: writer.writeAttribute("style", style, "style");
256: }
257:
258: String label = null;
259: final Object value = ((UICommand) component).getValue();
260: if (value != null) {
261: label = value.toString();
262: }
263: if (label != null && label.length() != 0) {
264: writer.write(label);
265: }
266: writer.flush();
267: }
268: }
269:
270: /**
271: * @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
272: */
273: public void encodeChildren(final FacesContext context,
274: final UIComponent component) throws IOException {
275: // - only render if rendered is true
276: if (component.isRendered()) {
277: for (Iterator iterator = component.getChildren().iterator(); iterator
278: .hasNext();) {
279: final UIComponent child = (UIComponent) iterator.next();
280: child.encodeBegin(context);
281: if (child.getRendersChildren()) {
282: child.encodeChildren(context);
283: }
284: child.encodeEnd(context);
285: }
286: }
287: }
288:
289: /**
290: * @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
291: */
292: public void encodeEnd(final FacesContext context,
293: final UIComponent component) throws IOException {
294: final UICommand command = (UICommand) component;
295:
296: // - only render if rendered is true
297: if (command.isRendered()) {
298: final ResponseWriter writer = context.getResponseWriter();
299:
300: // - complete writing Anchor element
301: writer.endElement("a");
302: writer.flush();
303: }
304: }
305:
306: /**
307: * @see javax.faces.render.Renderer#convertClientId(javax.faces.context.FacesContext, java.lang.String)
308: */
309: public String convertClientId(final FacesContext context,
310: final String clientId) {
311: return clientId;
312: }
313:
314: /**
315: * Gets the form to which the <code>component</code> belongs
316: * or null if the form can not be found.
317: *
318: * @param context the faces context.
319: * @param component the component.
320: * @return the form.
321: */
322: protected UIForm getForm(final FacesContext context,
323: final UIComponent component) {
324: UIComponent parent = component.getParent();
325: while (parent != null) {
326: if (parent instanceof UIForm) {
327: break;
328: }
329: parent = parent.getParent();
330: }
331: return (UIForm) parent;
332: }
333: }
|