1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.fisheye;
20
21 import org.apache.commons.collections.map.HashedMap;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.myfaces.custom.dojo.DojoUtils;
25 import org.apache.myfaces.custom.navmenu.UINavigationMenuItem;
26 import org.apache.myfaces.renderkit.html.ext.HtmlLinkRenderer;
27 import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
28 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
29 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
30 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
31 import org.apache.myfaces.shared_tomahawk.renderkit.html.util.FormInfo;
32
33 import javax.faces.component.UIComponent;
34 import javax.faces.context.FacesContext;
35 import javax.faces.context.ResponseWriter;
36 import javax.faces.event.ActionEvent;
37 import javax.servlet.http.HttpServletRequest;
38 import java.io.IOException;
39 import java.util.*;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class HtmlFishEyeNavigationMenuRenderer extends HtmlLinkRenderer {
57
58 private static final String ON_CLICK_ATTR = "onClick";
59 private static final String DOJO_COMPONENT_TYPE = "ScrollableFisheyeList";
60 private static final String DOJO_ITEM_TYPE = "ScrollableFisheyeListItem";
61 public static final String ATTACH_EDGE_ATTR = "attachEdge";
62 public static final String CAPTION_ATTR = "caption";
63 public static final String EFFECT_UNITS_ATTR = "effectUnits";
64 public static final String ICON_SRC_ATTR = "iconSrc";
65 public static final String ITEM_HEIGHT_ATTR = "itemHeight";
66 public static final String ITEM_MAX_HEIGHT_ATTR = "itemMaxHeight";
67 public static final String ITEM_MAX_WIDTH_ATTR = "itemMaxWidth";
68 public static final String ITEM_PADDING_ATTR = "itemPadding";
69 public static final String ITEM_WIDTH_ATTR = "itemWidth";
70 public static final String LABEL_EDGE_ATTR = "labelEdge";
71 public static final String ORIENTATION_ATTR = "orientation";
72 public static final String CONSERVATIVE_TRIGGER_ATTR = "conservativeTrigger";
73 public static final String RENDERER_TYPE = "org.apache.myfaces.FishEyeList";
74
75 private Log log = LogFactory.getLog(HtmlFishEyeNavigationMenuRenderer.class);
76
77
78
79
80 public void decode(FacesContext context, UIComponent component) {
81 FormInfo nestingForm = findNestingForm(component, context);
82 if (nestingForm != null) {
83 String fieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(nestingForm);
84 String reqValue = (String) context.getExternalContext().getRequestParameterMap().get(fieldName);
85 if (reqValue != null && reqValue.length() > 0) {
86 if (component instanceof FishEyeCommandLink && reqValue.equals(component.getClientId(context))) {
87 component.queueEvent(new ActionEvent(component));
88 } else {
89
90 UIComponent source = context.getViewRoot().findComponent(reqValue);
91 if (source instanceof UINavigationMenuItem) {
92 source.queueEvent(new ActionEvent(source));
93 }
94
95 }
96 }
97 }
98 }
99
100
101
102
103
104 public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
105 if (component.isRendered()) {
106 HtmlFishEyeNavigationMenu fisheye = (HtmlFishEyeNavigationMenu) component;
107 ResponseWriter writer = context.getResponseWriter();
108
109 String javascriptLocation = (String) component.getAttributes().get(JSFAttr.JAVASCRIPT_LOCATION);
110 DojoUtils.addMainInclude(context, component, javascriptLocation, DojoUtils.getDjConfigInstance(context));
111 DojoUtils.addRequire(context, component, "dojo.widget.myfaces.ScrollableFisheyeList");
112 DojoUtils.addRequire(context, component, "dojo.widget.html.myfaces.ScrollableFisheyeListItem");
113 DojoUtils.addRequire(context, component, "dojo.widget.Button");
114 String leftName = "";
115 if (fisheye.getVisibleWindow() != null) {
116 writer.startElement(HTML.TABLE_ELEM, component);
117 writer.startElement(HTML.TR_ELEM, component);
118 writer.startElement(HTML.TD_ELEM, component);
119 writer.writeAttribute(HTML.WIDTH_ATTR, "30", null);
120 writer.startElement(HTML.DIV_ELEM, component);
121 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(context) + "_left", null);
122 writer.write("<<");
123 writer.endElement(HTML.DIV_ELEM);
124
125 Map paramMap = new TreeMap();
126 paramMap.put("id", DojoUtils.calculateWidgetVarName(component.getClientId(context) + "_left"));
127 leftName = DojoUtils.renderWidgetInitializationCode(writer, component, "Button", paramMap, component.getClientId(context) + "_left", true);
128
129 writer.endElement(HTML.TD_ELEM);
130 writer.startElement(HTML.TD_ELEM, component);
131 }
132
133 writer.startElement(HTML.DIV_ELEM, fisheye);
134 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(context), null);
135
136 writer.endElement(HTML.DIV_ELEM);
137 String rightName = "";
138 if (fisheye.getVisibleWindow() != null) {
139 writer.endElement(HTML.TD_ELEM);
140 writer.startElement(HTML.TD_ELEM, component);
141 writer.writeAttribute(HTML.WIDTH_ATTR, "30", null);
142 writer.startElement(HTML.DIV_ELEM, component);
143 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(context) + "_right", null);
144 writer.write(">>");
145 writer.endElement(HTML.DIV_ELEM);
146 Map paramMap = new TreeMap();
147 paramMap.put("id", DojoUtils.calculateWidgetVarName(component.getClientId(context) + "_right"));
148 rightName = DojoUtils.renderWidgetInitializationCode(writer, component, "Button", paramMap, component.getClientId(context) + "_right", true);
149
150 writer.endElement(HTML.TD_ELEM);
151 writer.endElement(HTML.TR_ELEM);
152 writer.endElement(HTML.TABLE_ELEM);
153 }
154
155 Map paramMap = new HashedMap();
156
157 if (fisheye.getVisibleWindow() != null) {
158 paramMap.put("visibleWindow", fisheye.getVisibleWindow());
159 } else {
160 HtmlFishEyeNavigationMenu menu = (HtmlFishEyeNavigationMenu) component;
161 int visibleWindow = calculateVisbleWindow(component, menu);
162 paramMap.put("visibleWindow",new Integer( visibleWindow));
163 }
164
165
166 paramMap.put(ITEM_WIDTH_ATTR, fisheye.getItemWidth());
167 paramMap.put(ITEM_HEIGHT_ATTR, fisheye.getItemHeight());
168 paramMap.put(ITEM_MAX_WIDTH_ATTR, fisheye.getItemMaxWidth());
169 paramMap.put(ITEM_MAX_HEIGHT_ATTR, fisheye.getItemMaxHeight());
170 paramMap.put(ORIENTATION_ATTR, fisheye.getOrientation());
171 paramMap.put(EFFECT_UNITS_ATTR, fisheye.getEffectUnits());
172 paramMap.put(ITEM_PADDING_ATTR, fisheye.getItemPadding());
173 paramMap.put(ATTACH_EDGE_ATTR, fisheye.getAttachEdge());
174 paramMap.put(LABEL_EDGE_ATTR, fisheye.getLabelEdge());
175 paramMap.put(CONSERVATIVE_TRIGGER_ATTR, fisheye.getConservativeTrigger());
176
177 DojoUtils.renderWidgetInitializationCode(context, component, DOJO_COMPONENT_TYPE, paramMap);
178
179 if (fisheye.getVisibleWindow() != null) {
180 writer.startElement(HTML.SCRIPT_ELEM, component);
181 writer.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
182 writer
183 .write(leftName + ".onClick = function(e) {" + DojoUtils.calculateWidgetVarName(component.getClientId(context))
184 + ".onLeftScroll();};");
185 writer.write(rightName + ".onClick = function(e) {" + DojoUtils.calculateWidgetVarName(component.getClientId(context))
186 + ".onRightScroll();};");
187 writer.endElement(HTML.SCRIPT_ELEM);
188 }
189
190 }
191
192 }
193
194 private int calculateVisbleWindow(UIComponent component, HtmlFishEyeNavigationMenu menu) {
195 int visibleWindow = 0;
196 if (menu.getChildCount() == 1 && menu.getChildren().get(0) instanceof FishEyeCommandLink) {
197 visibleWindow = menu.getRowCount();
198 } else {
199 List children = component.getChildren();
200
201 for (Iterator cit = children.iterator(); cit.hasNext();) {
202 UIComponent child = (UIComponent) cit.next();
203 if (!child.isRendered())
204 continue;
205 if (child instanceof UINavigationMenuItem) {
206 visibleWindow += 1;
207 }
208 }
209 }
210 return visibleWindow;
211 }
212
213 private Stack getChildsMenuStack(FacesContext context, UIComponent component) {
214
215
216 Stack menuStack = (Stack) context.getExternalContext().getRequestMap().get(component.getClientId(context)
217 + "_FishEyeMenuAttr");
218 if (menuStack != null)
219 return menuStack;
220
221 menuStack = new Stack();
222
223 context.getExternalContext().getRequestMap().put(
224 component.getClientId(context) + "_FishEyeMenuAttr", menuStack);
225
226 return menuStack;
227 }
228
229
230
231
232
233 public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
234 ResponseWriter writer = context.getResponseWriter();
235 List children = component.getChildren();
236 Stack menuStack = getChildsMenuStack(context, component);
237 HtmlFishEyeNavigationMenu menu = (HtmlFishEyeNavigationMenu) component;
238 if (menu.getChildCount() == 1 && menu.getChildren().get(0) instanceof FishEyeCommandLink) {
239 FishEyeCommandLink link = (FishEyeCommandLink) menu.getChildren().get(0);
240 for (int i = 0; i < menu.getRowCount(); i++) {
241 menu.setRowIndex(i);
242 if(!menu.isRowAvailable()) {
243 log.error("Model is not available. Rowindex = " + i);
244 break;
245 }
246 renderMenuItem(context, writer, component, link, menuStack);
247 }
248 } else {
249 for (Iterator cit = children.iterator(); cit.hasNext();) {
250 UIComponent child = (UIComponent) cit.next();
251 if (!child.isRendered())
252 continue;
253 if (child instanceof UINavigationMenuItem) {
254 renderMenuItem(context, writer, component, (UINavigationMenuItem) child, menuStack);
255 }
256 }
257 }
258 }
259
260
261
262
263
264 public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
265 if (component.isRendered()) {
266 ResponseWriter writer = context.getResponseWriter();
267 Stack menuStack = getChildsMenuStack(context, component);
268 String jsMenuVar = DojoUtils.calculateWidgetVarName(component.getClientId(context));
269
270 writer.startElement(HTML.SCRIPT_ELEM, component);
271 writer.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
272 while (!menuStack.isEmpty()) {
273 String item = (String) menuStack.pop();
274 writer.write(jsMenuVar);
275 writer.write(".addChild(");
276 writer.write(item);
277 writer.write(");\n");
278 }
279 writer.write(jsMenuVar + ".postCreate(['programmaticdone'],null);\n");
280 writer.endElement(HTML.SCRIPT_ELEM);
281 }
282 }
283
284
285
286
287 public boolean getRendersChildren() {
288
289 return true;
290 }
291
292 protected void renderMenuItem(FacesContext context, ResponseWriter writer, UIComponent menu, UIComponent item, Stack childsMenuStack)
293 throws IOException {
294
295 FormInfo formInfo = findNestingForm(item, context);
296 String clientId = item.getClientId(context);
297 if (formInfo == null) {
298 throw new IllegalArgumentException("Component " + clientId + " must be embedded in an form");
299 }
300 UIComponent nestingForm = formInfo.getForm();
301 String formName = formInfo.getFormName();
302
303 StringBuffer onClick = new StringBuffer();
304
305 String jsForm = "document.forms['" + formName + "']";
306 if (RendererUtils.isAdfOrTrinidadForm(formInfo.getForm())) {
307 onClick.append("submitForm('");
308 onClick.append(formInfo.getForm().getClientId(context));
309 onClick.append("',1,{source:'");
310 onClick.append(clientId);
311 onClick.append("'});return false;");
312 } else {
313
314 onClick.append(HtmlRendererUtils.getClearHiddenCommandFormParamsFunctionName(formName)).append("();");
315
316
317
318
319
320
321 String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo);
322 onClick.append(jsForm);
323 onClick.append(".elements['").append(hiddenFieldName).append("']");
324 onClick.append(".value='").append(clientId).append("';");
325 addHiddenCommandParameter(context, nestingForm, hiddenFieldName);
326 }
327 String target;
328 String caption;
329 String iconSrc;
330 if (item instanceof UINavigationMenuItem) {
331 target = ((UINavigationMenuItem)item).getTarget();
332 caption = ((UINavigationMenuItem)item).getItemLabel();
333 iconSrc = ((UINavigationMenuItem)item).getIcon();
334 } else if (item instanceof FishEyeCommandLink) {
335 target = ((FishEyeCommandLink)item).getTarget();
336 caption = ((FishEyeCommandLink)item).getCaption();
337 iconSrc = ((FishEyeCommandLink)item).getIconSrc();
338 } else {
339 throw new IllegalArgumentException("expected UINavigationMenuItem or FisheyCommandLink");
340 }
341
342
343 if (target != null && target.trim().length() > 0) {
344 onClick.append(jsForm);
345 onClick.append(".target='");
346 onClick.append(target);
347 onClick.append("';");
348 }
349
350
351 onClick.append("if(").append(jsForm).append(".onsubmit){var result=").append(jsForm).append(
352 ".onsubmit(); if( (typeof result == 'undefined') || result ) {" + jsForm + ".submit();}}else{");
353
354
355 onClick.append(jsForm);
356 onClick.append(".submit();}return false;");
357
358
359
360 Map paramMap = new HashMap();
361 paramMap.put(CAPTION_ATTR, caption);
362 paramMap.put(ICON_SRC_ATTR, iconSrc);
363 paramMap.put(ON_CLICK_ATTR, new StringBuffer("function () {").append(onClick).append("}"));
364
365
366 String menuItemId = DojoUtils.renderWidgetInitializationCode(writer, item, DOJO_ITEM_TYPE, paramMap, item.getClientId(context), false);
367 childsMenuStack.push(menuItemId);
368
369
370 }
371
372 protected void writeAttribute(ResponseWriter writer, HtmlFishEyeNavigationMenu fisheye, String name, Object value) throws IOException {
373 if (name != null && value != null) {
374 writer.writeAttribute(name, value, null);
375 }
376 }
377
378 }