001: /*
002: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003: *
004: * "The contents of this file are subject to the Mozilla Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License at
007: * http://www.mozilla.org/MPL/
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
011: * License for the specific language governing rights and limitations under
012: * the License.
013: *
014: * The Original Code is ICEfaces 1.5 open source software code, released
015: * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
016: * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
017: * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
018: *
019: * Contributor(s): _____________________.
020: *
021: * Alternatively, the contents of this file may be used under the terms of
022: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
023: * License), in which case the provisions of the LGPL License are
024: * applicable instead of those above. If you wish to allow use of your
025: * version of this file only under the terms of the LGPL License and not to
026: * allow others to use your version of this file under the MPL, indicate
027: * your decision by deleting the provisions above and replace them with
028: * the notice and other provisions required by the LGPL License. If you do
029: * not delete the provisions above, a recipient may use your version of
030: * this file under either the MPL or the LGPL License."
031: *
032: */
033:
034: package com.icesoft.faces.component.menubar;
035:
036: import com.icesoft.faces.component.CSS_DEFAULT;
037: import com.icesoft.faces.component.InvalidComponentTypeException;
038: import com.icesoft.faces.component.ext.HtmlCommandLink;
039: import com.icesoft.faces.component.ext.HtmlGraphicImage;
040: import com.icesoft.faces.component.ext.HtmlOutputText;
041: import com.icesoft.faces.component.ext.HtmlPanelGroup;
042: import com.icesoft.faces.component.ext.taglib.Util;
043: import com.icesoft.faces.context.DOMContext;
044: import com.icesoft.faces.renderkit.dom_html_basic.HTML;
045: import com.icesoft.faces.util.CoreUtils;
046: import com.icesoft.faces.util.DOMUtils;
047: import org.w3c.dom.Element;
048: import org.w3c.dom.Node;
049:
050: import javax.faces.component.NamingContainer;
051: import javax.faces.component.UIComponent;
052: import javax.faces.component.UIParameter;
053: import javax.faces.component.UIViewRoot;
054: import javax.faces.context.FacesContext;
055: import javax.faces.el.MethodBinding;
056: import javax.faces.event.ActionEvent;
057: import javax.faces.event.ActionListener;
058: import java.beans.Beans;
059: import java.io.IOException;
060: import java.util.Iterator;
061: import java.util.Map;
062:
063: public class MenuItemRenderer extends MenuItemRendererBase {
064:
065: private static final String HIDDEN_FIELD_NAME = "cl";
066:
067: private static String SUB = "_sub";
068: private static String KEYWORD_NULL = "null";
069: private static String KEYWORD_THIS = "this";
070: private final String DEFAULT_IMAGEDIR = "/xmlhttp/css/xp/css-images/";
071: private static final String SUBMENU_IMAGE = "submenu.gif";
072: private static String LINK_SUFFIX = "link";
073:
074: public void decode(FacesContext facesContext,
075: UIComponent uiComponent) {
076:
077: validateParameters(facesContext, uiComponent, null);
078: if (isStatic(uiComponent)) {
079: return;
080: }
081: String componentId = uiComponent.getClientId(facesContext);
082: Map requestParameterMap = facesContext.getExternalContext()
083: .getRequestParameterMap();
084: String hiddenFieldName = deriveCommonHiddenFieldName(
085: facesContext, (MenuItem) uiComponent);
086: String hiddenFieldNameInRequestMap = (String) requestParameterMap
087: .get(hiddenFieldName);
088:
089: if (hiddenFieldNameInRequestMap == null
090: || hiddenFieldNameInRequestMap.equals("")) {
091: // this command link did not invoke the submit
092: return;
093: }
094:
095: // debugging
096: //examineRequest(facesContext, uiComponent, requestParameterMap, hiddenFieldName, hiddenFieldNameInRequestMap);
097: String commandLinkClientId = componentId + ":" + LINK_SUFFIX;
098: if (hiddenFieldNameInRequestMap.equals(commandLinkClientId)) {
099: ActionEvent actionEvent = new ActionEvent(uiComponent);
100: uiComponent.queueEvent(actionEvent);
101: }
102: }
103:
104: // this component renders its children, so, this method will be called once
105: // for each top-level menu node. From there, this component will manage
106: // the rendering of all children components. The idea is to end up with
107: // a fairly flat structure. There will exist a master div that contains the
108: // entire menu. Inside that div there will exist a first-order child div for
109: // each top level menu item and there will exist a first-order child div for
110: // each submenu. Inside the submenu div there will exist a div to hold each
111: // menu item in the submenu. Note that there is no nesting of submenu items
112: public void encodeBegin(FacesContext facesContext,
113: UIComponent uiComponent) throws IOException {
114:
115: if (!(uiComponent.getParent() instanceof MenuBar)
116: && !(uiComponent.getParent() instanceof MenuItems)) {
117: throw new InvalidComponentTypeException(
118: "MenuBar expected as parent of top-level MenuItem");
119: }
120: // If static model declaration (in the jsp) is employed then the
121: // immediate parent will be the Menu component
122: // Else if the model declaration is in the bean class then there
123: // is a MenuItems between the MenuItem and the Menu component
124: MenuBar menuComponent = null;
125: if (uiComponent.getParent() instanceof MenuBar) {
126: menuComponent = (MenuBar) uiComponent.getParent();
127: } else if (uiComponent.getParent().getParent() instanceof MenuBar) {
128: menuComponent = (MenuBar) uiComponent.getParent()
129: .getParent();
130: } else {
131: throw new InvalidComponentTypeException("Expecting MenuBar");
132: }
133:
134: // is vertical ?
135: boolean vertical = menuComponent.getOrientation()
136: .equalsIgnoreCase(MenuBar.ORIENTATION_VERTICAL);
137:
138: validateParameters(facesContext, uiComponent,
139: MenuItemBase.class);
140:
141: // first render
142: DOMContext domContext = DOMContext.attachDOMContext(
143: facesContext, uiComponent);
144: String clientId = uiComponent.getClientId(facesContext);
145: if (!domContext.isInitialized()) {
146: Element topLevelDiv = domContext
147: .createRootElement(HTML.DIV_ELEM);
148: topLevelDiv.setAttribute(HTML.ID_ATTR, clientId);
149: }
150: Element topLevelDiv = (Element) domContext.getRootNode();
151: topLevelDiv.setAttribute(HTML.NAME_ATTR, "TOP_LEVEL");
152:
153: String rootItemSubClass = CSS_DEFAULT.MENU_BAR_ITEM_STYLE;
154: if (vertical) {
155: rootItemSubClass = CSS_DEFAULT.MENU_BAR_VERTICAL_SUFFIX_STYLE
156: + rootItemSubClass;
157: }
158: topLevelDiv.setAttribute(HTML.CLASS_ATTR,
159: ((MenuItem) uiComponent).getUserDefinedStyleClass(
160: menuComponent.getItemStyleClass(),
161: rootItemSubClass));
162:
163: if (uiComponent.getChildCount() > 0) {
164: String displayEvent = HTML.ONMOUSEOVER_ATTR;
165: if (vertical) {
166: topLevelDiv.setAttribute(displayEvent,
167: "Ice.Menu.hideOrphanedMenusNotRelatedTo(this);"
168: + expand("this", clientId + "_sub",
169: KEYWORD_THIS));
170: } else {
171: topLevelDiv.setAttribute(displayEvent,
172: "Ice.Menu.hideOrphanedMenusNotRelatedTo(this);"
173: + expand("this", clientId + "_sub",
174: KEYWORD_NULL));
175: }
176: } else {
177: topLevelDiv.setAttribute(HTML.ONMOUSEOVER_ATTR,
178: "Ice.Menu.hideOrphanedMenusNotRelatedTo(this);");
179: }
180:
181: DOMContext.removeChildren(topLevelDiv);
182: Element masterDiv = (Element) topLevelDiv.getParentNode();
183:
184: renderAnchor(facesContext, domContext, 0,
185: (MenuItem) uiComponent, topLevelDiv, menuComponent,
186: vertical);
187:
188: if ((uiComponent.getChildCount() > 0)
189: && (((MenuItem) uiComponent).isChildrenMenuItem())) {
190: renderChildrenRecursive(facesContext, menuComponent,
191: uiComponent, vertical, masterDiv);
192:
193: }
194: }
195:
196: private String expand(String super menu, String submenu,
197: String submenuDiv) {
198: // delimit ids to force resolution from ids to elements
199: if (!(super menu.equalsIgnoreCase(KEYWORD_NULL))
200: && !(super menu.equalsIgnoreCase(KEYWORD_THIS))) {
201: super menu = "$('" + super menu + "')";
202: }
203: if (!(submenu.equalsIgnoreCase(KEYWORD_NULL))
204: && !(submenu.equalsIgnoreCase(KEYWORD_THIS))) {
205: submenu = "$('" + submenu + "')";
206: }
207: if (!(submenuDiv.equalsIgnoreCase(KEYWORD_NULL))
208: && !(submenuDiv.equalsIgnoreCase(KEYWORD_THIS))) {
209: submenuDiv = "$('" + submenuDiv + "')";
210: }
211: return "Ice.Menu.show(" + super menu + "," + submenu + ","
212: + submenuDiv + ");";
213: }
214:
215: protected static String deriveCommonHiddenFieldName(
216: FacesContext facesContext, UIComponent uiComponent) {
217:
218: if (Beans.isDesignTime()) {
219: return "";
220: }
221: UIComponent parentNamingContainer = findForm(uiComponent);
222: String parentClientId = parentNamingContainer
223: .getClientId(facesContext);
224: String hiddenFieldName = parentClientId
225: + NamingContainer.SEPARATOR_CHAR
226: + UIViewRoot.UNIQUE_ID_PREFIX + HIDDEN_FIELD_NAME;
227: return hiddenFieldName;
228: }
229:
230: // this method is used to render topLevel horizontal menu items
231: // horizontal menu items do not have icons or subMenu indicators
232: private Element makeTopLevelAnchor(FacesContext facesContext,
233: MenuItem menuItem, MenuBar menuBar) {
234:
235: DOMContext domContext = DOMContext.getDOMContext(facesContext,
236: menuItem);
237: Element anchor = domContext.createElement(HTML.ANCHOR_ELEM);
238: if (!menuItem.isDisabled()) {
239: anchor.setAttribute(HTML.HREF_ATTR, menuItem.getLink());
240: if (menuItem.getTarget() != null) {
241: anchor.setAttribute(HTML.TARGET_ATTR, menuItem
242: .getTarget());
243: }
244: }
245: // create div
246: Element div = domContext.createElement(HTML.DIV_ELEM);
247:
248: anchor.appendChild(div);
249:
250: // only render icons if noIcons is false
251: if ((!menuBar.getNoIcons().equalsIgnoreCase("true"))
252: && (getIcon(menuItem) != null)) {
253: // do not render icon if it is the default blank image
254: // this only applies to horizontal top level menu items
255: if (!getIcon(menuItem).endsWith(MenuItem.DEFAULT_ICON)) {
256: Element iconImg = domContext
257: .createElement(HTML.IMG_ELEM);
258: iconImg.setAttribute(HTML.SRC_ATTR, getIcon(menuItem));
259: iconImg.setAttribute(HTML.STYLE_ATTR, "border:none;");
260: iconImg
261: .setAttribute(
262: HTML.CLASS_ATTR,
263: menuItem
264: .getUserDefinedStyleClass(
265: menuBar
266: .getItemImageStyleClass(),
267: CSS_DEFAULT.MENU_BAR_ITEM_STYLE
268: + CSS_DEFAULT.MENU_ITEM_IMAGE_STYLE));
269: div.appendChild(iconImg);
270: }
271: }
272:
273: // create a span for text
274: Element span = domContext.createElement(HTML.SPAN_ELEM);
275: if (!menuItem.isDisabled()) {
276: anchor.setAttribute(HTML.STYLE_CLASS_ATTR, "iceLink");
277: } else {
278: anchor.setAttribute(HTML.STYLE_CLASS_ATTR, "iceLink-dis");
279: }
280: span.setAttribute(HTML.CLASS_ATTR, menuItem
281: .getUserDefinedStyleClass(menuBar
282: .getItemLabelStyleClass(),
283: CSS_DEFAULT.MENU_BAR_ITEM_LABEL_STYLE));
284: div.appendChild(span);
285: // create text
286: Node text = domContext.createTextNode(DOMUtils
287: .escapeAnsi(menuItem.getValue().toString()));
288: span.appendChild(text);
289:
290: return anchor;
291: }
292:
293: // this method is used to render top level vertical menu items
294: private Element makeTopLevelVerticalAnchor(
295: FacesContext facesContext, MenuItem menuItem,
296: MenuBar menuBar) {
297:
298: DOMContext domContext = DOMContext.getDOMContext(facesContext,
299: menuItem);
300: Element anchor = domContext.createElement(HTML.ANCHOR_ELEM);
301: if (!menuItem.isDisabled()) {
302: anchor.setAttribute(HTML.HREF_ATTR, menuItem.getLink());
303: if (menuItem.getTarget() != null) {
304: anchor.setAttribute(HTML.TARGET_ATTR, menuItem
305: .getTarget());
306: }
307: }
308: // create div
309: Element div = domContext.createElement(HTML.DIV_ELEM);
310:
311: anchor.appendChild(div);
312:
313: if (menuItem.getChildCount() > 0) {
314: Element subImg = domContext.createElement(HTML.IMG_ELEM);
315: subImg.setAttribute(HTML.SRC_ATTR, CoreUtils
316: .resolveResourceURL(facesContext,
317: getSubMenuImage(menuBar)));
318: subImg.setAttribute(HTML.STYLE_ATTR, "border:none;");
319: subImg.setAttribute(HTML.CLASS_ATTR, menuBar
320: .getSubMenuIndicatorStyleClass());
321: div.appendChild(subImg);
322: }
323:
324: // only render icons if noIcons is false
325: if ((!menuBar.getNoIcons().equalsIgnoreCase("true"))
326: && (getIcon(menuItem) != null)) {
327: Element iconImg = domContext.createElement(HTML.IMG_ELEM);
328: iconImg.setAttribute(HTML.SRC_ATTR, getIcon(menuItem));
329: iconImg.setAttribute(HTML.STYLE_ATTR, "border:none;");
330: iconImg
331: .setAttribute(
332: HTML.CLASS_ATTR,
333: menuItem
334: .getUserDefinedStyleClass(
335: menuBar
336: .getItemImageStyleClass(),
337: CSS_DEFAULT.MENU_BAR_VERTICAL_SUFFIX_STYLE
338: + CSS_DEFAULT.MENU_BAR_ITEM_STYLE
339: + CSS_DEFAULT.MENU_ITEM_IMAGE_STYLE));
340: div.appendChild(iconImg);
341: }
342:
343: // create a span for text
344: Element span = domContext.createElement(HTML.SPAN_ELEM);
345: if (!menuItem.isDisabled()) {
346: anchor.setAttribute(HTML.STYLE_CLASS_ATTR, "iceLink");
347: } else {
348: anchor.setAttribute(HTML.STYLE_CLASS_ATTR, "iceLink-dis");
349: }
350: span
351: .setAttribute(
352: HTML.CLASS_ATTR,
353: menuItem
354: .getUserDefinedStyleClass(
355: menuBar
356: .getItemLabelStyleClass(),
357: CSS_DEFAULT.MENU_BAR_VERTICAL_SUFFIX_STYLE
358: + CSS_DEFAULT.MENU_BAR_ITEM_LABEL_STYLE));
359:
360: div.appendChild(span);
361: // create text
362: Node text = domContext.createTextNode(DOMUtils
363: .escapeAnsi(menuItem.getValue().toString()));
364: span.appendChild(text);
365:
366: return anchor;
367: }
368:
369: private Element makeAnchor(FacesContext facesContext,
370: DOMContext domContext, MenuItem menuItem, MenuBar menuBar) {
371:
372: Element anchor = domContext.createElement(HTML.ANCHOR_ELEM);
373: if (!menuItem.isDisabled()) {
374: anchor.setAttribute(HTML.HREF_ATTR, menuItem.getLink());
375: if (menuItem.getTarget() != null) {
376: anchor.setAttribute(HTML.TARGET_ATTR, menuItem
377: .getTarget());
378: }
379: }
380: // create div
381: Element div = domContext.createElement(HTML.DIV_ELEM);
382:
383: anchor.appendChild(div);
384:
385: if (menuItem.getChildCount() > 0) {
386: Element subImg = domContext.createElement(HTML.IMG_ELEM);
387: subImg.setAttribute(HTML.SRC_ATTR, CoreUtils
388: .resolveResourceURL(facesContext,
389: getSubMenuImage(menuBar)));
390: subImg.setAttribute(HTML.STYLE_ATTR, "border:none;");
391: subImg.setAttribute(HTML.CLASS_ATTR, menuBar
392: .getSubMenuIndicatorStyleClass());
393: div.appendChild(subImg);
394: }
395:
396: // only render icons if noIcons is false
397: if ((!menuBar.getNoIcons().equalsIgnoreCase("true"))
398: && (getIcon(menuItem) != null)) {
399: Element iconImg = domContext.createElement(HTML.IMG_ELEM);
400: iconImg.setAttribute(HTML.SRC_ATTR, getIcon(menuItem));
401: iconImg.setAttribute(HTML.STYLE_ATTR, "border:none;");
402: iconImg.setAttribute(HTML.CLASS_ATTR, menuItem
403: .getImageStyleClass());
404: div.appendChild(iconImg);
405: }
406:
407: // create a span for text
408: Element span = domContext.createElement(HTML.SPAN_ELEM);
409: if (!menuItem.isDisabled()) {
410: anchor.setAttribute(HTML.STYLE_CLASS_ATTR, "iceLink");
411: } else {
412: anchor.setAttribute(HTML.STYLE_CLASS_ATTR, "iceLink-dis");
413: }
414: span.setAttribute(HTML.CLASS_ATTR, menuItem
415: .getLabelStyleClass());
416:
417: div.appendChild(span);
418: // create text
419: Node text = domContext.createTextNode(DOMUtils
420: .escapeAnsi(menuItem.getValue().toString()));
421: span.appendChild(text);
422:
423: return anchor;
424: }
425:
426: private void renderChildrenRecursive(FacesContext facesContext,
427: MenuBar menuComponent, UIComponent uiComponent,
428: boolean vertical, Element masterDiv) {
429: DOMContext domContext = DOMContext.getDOMContext(facesContext,
430: uiComponent);
431: // create the div that will hold all the sub menu items
432: Element submenuDiv = domContext.createElement(HTML.DIV_ELEM);
433: submenuDiv.setAttribute(HTML.NAME_ATTR, "SUBMENU");
434: String subMenuDivId = uiComponent.getClientId(facesContext)
435: + SUB;
436: submenuDiv.setAttribute(HTML.ID_ATTR, subMenuDivId);
437:
438: // if (vertical) {
439: // submenuDiv.setAttribute(HTML.CLASS_ATTR,
440: // CSS_DEFAULT.SUBMENU_VERTICAL_STYLE);
441: // } else {
442: // submenuDiv.setAttribute(HTML.CLASS_ATTR, CSS_DEFAULT.SUBMENU_STYLE);
443: // }
444: submenuDiv.setAttribute(HTML.CLASS_ATTR, menuComponent
445: .getSubMenuStyleClass());
446: submenuDiv.setAttribute(HTML.STYLE_ATTR, "display:none");
447: masterDiv.appendChild(submenuDiv);
448: // check if this menuItem is disabled, if it is lets disable the children
449: // render each menuItem in this submenu
450: boolean disabled = ((MenuItem) uiComponent).isDisabled();
451: for (int childIndex = 0; childIndex < uiComponent
452: .getChildCount(); childIndex++) {
453: UIComponent nextSubMenuItem = (UIComponent) uiComponent
454: .getChildren().get(childIndex);
455: if (!(nextSubMenuItem instanceof UIParameter)) {
456: Element subMenuItemDiv = domContext
457: .createElement(HTML.DIV_ELEM);
458: submenuDiv.appendChild(subMenuItemDiv);
459: if (nextSubMenuItem instanceof MenuItemSeparator) {
460: renderSeparatorDiv(domContext, subMenuItemDiv,
461: (MenuItemSeparator) nextSubMenuItem);
462: continue;
463: }
464: subMenuItemDiv.setAttribute(HTML.CLASS_ATTR,
465: ((MenuItem) nextSubMenuItem).getStyleClass());
466: subMenuItemDiv.setAttribute(HTML.NAME_ATTR, "ITEM");
467: String subMenuItemClientId = nextSubMenuItem
468: .getClientId(facesContext);
469: subMenuItemDiv.setAttribute(HTML.ID_ATTR,
470: subMenuItemClientId);
471: if (nextSubMenuItem.getChildCount() > 0
472: && ((MenuItem) nextSubMenuItem)
473: .isChildrenMenuItem()) {
474: subMenuItemDiv.setAttribute(HTML.ONMOUSEOVER_ATTR,
475: "Ice.Menu.hideOrphanedMenusNotRelatedTo(this);"
476: + expand(subMenuDivId,
477: subMenuItemClientId + SUB,
478: KEYWORD_THIS));
479: } else {
480: subMenuItemDiv
481: .setAttribute(HTML.ONMOUSEOVER_ATTR,
482: "Ice.Menu.hideOrphanedMenusNotRelatedTo(this);");
483:
484: }
485: subMenuItemDiv.setAttribute(HTML.ID_ATTR,
486: nextSubMenuItem.getClientId(facesContext));
487: // if parent is disabled apply the disabled attribute value of the parent menuItem to this submenuItem
488: if (disabled) {
489: ((MenuItem) nextSubMenuItem).setDisabled(disabled);
490: }
491: // add a command link if we need one
492: if (nextSubMenuItem instanceof MenuItem) {
493: renderAnchor(facesContext, domContext, childIndex,
494: (MenuItem) nextSubMenuItem, subMenuItemDiv,
495: menuComponent, vertical);
496: }
497: }
498: }
499:
500: // recurse
501: // check if parent is disabled , if it is the child items should also be disabled.
502: // we should not render child MenuItems of a disabled menuItem
503:
504: for (int childIndex = 0; childIndex < uiComponent
505: .getChildCount(); childIndex++) {
506: UIComponent nextSubMenuItem = (UIComponent) uiComponent
507: .getChildren().get(childIndex);
508: if (nextSubMenuItem.getChildCount() > 0) {
509: renderChildrenRecursive(facesContext, menuComponent,
510: nextSubMenuItem, vertical, masterDiv);
511: }
512: }
513: }
514:
515: /**
516: * @param facesContext
517: * @param domContext
518: * @param childIndex
519: * @param nextSubMenuItem
520: * @param subMenuItemDiv
521: */
522: private void renderAnchor(FacesContext facesContext,
523: DOMContext domContext, int childIndex,
524: MenuItem nextSubMenuItem, Element subMenuItemDiv,
525: MenuBar menuComponent, boolean vertical) {
526:
527: // check if the nextSubMenuItem isRendered
528: if (!nextSubMenuItem.isRendered()) {
529: return;
530: }
531:
532: // check if this is a Top Level Menu or MenuItems
533: if ((nextSubMenuItem.getParent() instanceof MenuBar)
534: || ((nextSubMenuItem.getParent() instanceof MenuItems) && (nextSubMenuItem
535: .getParent().getParent() instanceof MenuBar))) {
536: // handle action/actionListeners if attached to top level menuItems
537: if (nextSubMenuItem.hasActionOrActionListener()) {
538: HtmlCommandLink link = new HtmlCommandLink();
539: if (nextSubMenuItem.isDisabled()) {
540: link.setDisabled(true);
541: } else { // only add action and actionlisteners on enabled menuItems
542: MethodBinding action = nextSubMenuItem.getAction();
543: if (action != null) {
544: link.setAction(action);
545: }
546: MethodBinding actionListener = nextSubMenuItem
547: .getActionListener();
548: if (actionListener != null) {
549: link.setActionListener(actionListener);
550: }
551: ActionListener[] actionListeners = nextSubMenuItem
552: .getActionListeners();
553: if (actionListeners != null) {
554: for (int i = 0; i < actionListeners.length; i++) {
555: link
556: .removeActionListener(actionListeners[i]);
557: link.addActionListener(actionListeners[i]);
558: }
559: }
560: }
561: link.setValue(nextSubMenuItem.getValue());
562: link.setParent(nextSubMenuItem);
563: link.setId(LINK_SUFFIX);
564: //link.setStyleClass("");
565: Node lastCursorParent = domContext.getCursorParent();
566: domContext.setCursorParent(subMenuItemDiv);
567: if (vertical) {
568: addChildren(link, nextSubMenuItem, menuComponent);
569: } else {
570: addTopLevelChildren(link, nextSubMenuItem,
571: menuComponent);
572: }
573:
574: ((MenuItem) nextSubMenuItem).addParameter(link);
575: try {
576: link.encodeBegin(facesContext);
577: link.encodeChildren(facesContext);
578: link.encodeEnd(facesContext);
579:
580: } catch (IOException e) {
581: e.printStackTrace();
582: }
583: domContext.setCursorParent(lastCursorParent);
584: } else {
585: // anchor
586: Element anchor = null;
587: if (vertical) {
588: anchor = makeTopLevelVerticalAnchor(facesContext,
589: nextSubMenuItem, menuComponent);
590: } else {
591: anchor = makeTopLevelAnchor(facesContext,
592: nextSubMenuItem, menuComponent);
593: }
594: subMenuItemDiv.appendChild(anchor);
595: }
596: } else if (nextSubMenuItem.hasActionOrActionListener()) {
597: HtmlCommandLink link = new HtmlCommandLink();
598: if (nextSubMenuItem.isDisabled()) {
599: link.setDisabled(true);
600: } else { // only set action and actionListeners on enabled menuItems
601: MethodBinding action = nextSubMenuItem.getAction();
602: if (action != null) {
603: link.setAction(action);
604: }
605: MethodBinding actionListener = nextSubMenuItem
606: .getActionListener();
607: if (actionListener != null) {
608: link.setActionListener(actionListener);
609: }
610: ActionListener[] actionListeners = nextSubMenuItem
611: .getActionListeners();
612: if (actionListeners != null) {
613: for (int i = 0; i < actionListeners.length; i++) {
614: link.removeActionListener(actionListeners[i]);
615: link.addActionListener(actionListeners[i]);
616: }
617: }
618: }
619: link.setValue(nextSubMenuItem.getValue());
620: link.setParent(nextSubMenuItem);
621: link.setId(LINK_SUFFIX);
622:
623: Node lastCursorParent = domContext.getCursorParent();
624: domContext.setCursorParent(subMenuItemDiv);
625: addChildren(link, nextSubMenuItem, menuComponent);
626: ((MenuItem) nextSubMenuItem).addParameter(link);
627: try {
628: link.encodeBegin(facesContext);
629: link.encodeChildren(facesContext);
630: link.encodeEnd(facesContext);
631:
632: } catch (IOException e) {
633: e.printStackTrace();
634: }
635: domContext.setCursorParent(lastCursorParent);
636:
637: } else {
638: // anchor
639: Element anchor = makeAnchor(facesContext, domContext,
640: nextSubMenuItem, menuComponent);
641: subMenuItemDiv.appendChild(anchor);
642: }
643: }
644:
645: // this method is used to add icon and label
646: // to top level horizontal menu items
647: private void addTopLevelChildren(HtmlCommandLink link,
648: MenuItem nextSubMenuItem, MenuBar menuComponent) {
649: HtmlPanelGroup div = new HtmlPanelGroup();
650:
651: if ((!menuComponent.getNoIcons().equalsIgnoreCase("true"))
652: && (getIcon(nextSubMenuItem) != null)) {
653: HtmlGraphicImage image = new HtmlGraphicImage();
654: image.setUrl(getIcon(nextSubMenuItem));
655: image.setStyle("border:none;");
656: image.setStyleClass(nextSubMenuItem.getImageStyleClass());
657: div.getChildren().add(image);
658: }
659:
660: HtmlOutputText outputText = new HtmlOutputText();
661: outputText.setValue(link.getValue());
662: // if (!nextSubMenuItem.isDisabled()) {
663: // outputText.setStyleClass("iceSubMenuRowLabel");
664: // } else {
665: // outputText.setStyleClass("iceSubMenuRowLabel-dis");
666: // }
667: outputText.setStyleClass(nextSubMenuItem.getLabelStyleClass());
668: link.setValue("");
669: div.getChildren().add(outputText);
670:
671: link.getChildren().add(div);
672: }
673:
674: // this method is used to add icon, label and indicator
675: // to top level vertical menu items
676: void addChildren(HtmlCommandLink link, MenuItem nextSubMenuItem,
677: MenuBar menuComponent) {
678: HtmlPanelGroup div = new HtmlPanelGroup();
679: if (nextSubMenuItem.getChildCount() > 0
680: && nextSubMenuItem.isChildrenMenuItem()) {
681: HtmlGraphicImage image = new HtmlGraphicImage();
682: image.setUrl(getSubMenuImage(menuComponent));
683: image.setStyle("border:none;");
684: image.setStyleClass(menuComponent
685: .getSubMenuIndicatorStyleClass());
686: div.getChildren().add(image);
687: }
688:
689: if ((!menuComponent.getNoIcons().equalsIgnoreCase("true"))
690: && (getIcon(nextSubMenuItem) != null)) {
691: HtmlGraphicImage image = new HtmlGraphicImage();
692: image.setUrl(getIcon(nextSubMenuItem));
693: image.setStyle("border:none;");
694: image.setStyleClass(nextSubMenuItem.getImageStyleClass());
695: div.getChildren().add(image);
696: }
697:
698: HtmlOutputText outputText = new HtmlOutputText();
699: outputText.setValue(link.getValue());
700: // if (!nextSubMenuItem.isDisabled()) {
701: // outputText.setStyleClass("iceSubMenuRowLabel");
702: // } else {
703: // outputText.setStyleClass("iceSubMenuRowLabel-dis");
704: // }
705: outputText.setStyleClass(nextSubMenuItem.getLabelStyleClass());
706: link.setValue("");
707: div.getChildren().add(outputText);
708:
709: link.getChildren().add(div);
710: }
711:
712: private void renderSeparatorDiv(DOMContext domContext,
713: Element parent, MenuItemSeparator menuItemSeparator) {
714: Element hr = domContext.createElement("hr");
715: parent.setAttribute(HTML.CLASS_ATTR, menuItemSeparator
716: .getStyleClass());
717: parent.appendChild(hr);
718: }
719:
720: /**
721: * @return SubMenuImage url
722: */
723: private String getSubMenuImage(MenuBar menuComponent) {
724: String customPath = null;
725: if ((customPath = menuComponent.getImageDir()) != null) {
726: return customPath + SUBMENU_IMAGE;
727: }
728: return DEFAULT_IMAGEDIR + SUBMENU_IMAGE;
729: }
730:
731: protected String getTextValue(UIComponent component) {
732: if (component instanceof MenuItem) {
733: return ((MenuItem) component).getValue().toString();
734: }
735: return null;
736: }
737:
738: protected String getIcon(UIComponent component) {
739: if (component instanceof MenuItem) {
740: return ((MenuItem) component).getIcon();
741: }
742: return null;
743: }
744:
745: /* (non-Javadoc)
746: * @see com.icesoft.faces.component.menubar.MenuItemRendererBase
747: * #encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
748: */
749: public void encodeChildren(FacesContext context,
750: UIComponent component) throws IOException {
751: }
752:
753: /**
754: * This method is used for debugging.
755: *
756: * @param facesContext
757: * @param uiComponent
758: * @param requestParameterMap
759: * @param hiddenFieldName
760: */
761: private void examineRequest(FacesContext facesContext,
762: UIComponent uiComponent, Map requestParameterMap,
763: String hiddenFieldName, String hiddenValue) {
764: Iterator entries = requestParameterMap.entrySet().iterator();
765: System.out.println("decoding "
766: + ((MenuItem) uiComponent).getValue());
767: System.out.println("request map");
768: while (entries.hasNext()) {
769: Map.Entry next = (Map.Entry) entries.next();
770: if (!next.getKey().toString().equals("rand")) {
771: System.out.println("[" + next.getKey().toString() + "="
772: + next.getValue() + "]");
773: }
774: }
775: System.out.println("looking for hidden field ["
776: + hiddenFieldName + "]");
777: System.out.println("client id = ["
778: + uiComponent.getClientId(facesContext));
779: System.out
780: .println("################################################ QUEUEING for hidden field ["
781: + hiddenValue + "]");
782: }
783:
784: /* (non-Javadoc)
785: * @see com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer
786: * #encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
787: */
788: public void encodeEnd(FacesContext facesContext,
789: UIComponent uiComponent) throws IOException {
790: DOMContext domContext = DOMContext.getDOMContext(facesContext,
791: uiComponent);
792: super.encodeEnd(facesContext, uiComponent);
793: domContext.streamWrite(facesContext, uiComponent);
794: }
795:
796: }
|