All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.icefaces.ace.component.menu.BaseMenuRenderer Maven / Gradle / Ivy

There is a newer version: 4.3.0
Show newest version
/*
 * Original Code Copyright Prime Technology.
 * Subsequent Code Modifications Copyright 2011-2014 ICEsoft Technologies Canada Corp. (c)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * NOTE THIS CODE HAS BEEN MODIFIED FROM ORIGINAL FORM
 *
 * Subsequent Code Modifications have been made and contributed by ICEsoft Technologies Canada Corp. (c).
 *
 * Code Modification 1: Integrated with ICEfaces Advanced Component Environment.
 * Contributors: ICEsoft Technologies Canada Corp. (c)
 *
 * Code Modification 2: [ADD BRIEF DESCRIPTION HERE]
 * Contributors: ______________________
 * Contributors: ______________________
 */
package org.icefaces.ace.component.menu;

import java.io.IOException;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIParameter;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.icefaces.ace.component.menuitem.MenuItem;
import org.icefaces.ace.component.menucolumn.MenuColumn;
import org.icefaces.ace.component.multicolumnsubmenu.MultiColumnSubmenu;
import org.icefaces.ace.component.submenu.Submenu;
import org.icefaces.ace.component.menuseparator.MenuSeparator;
import org.icefaces.ace.renderkit.CoreRenderer;
import org.icefaces.ace.util.ComponentUtils;
import org.icefaces.ace.util.Utils;
import org.icefaces.impl.event.AjaxDisabledList;

import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.component.behavior.ClientBehaviorHolder;
import java.util.*;
import org.icefaces.ace.component.ajax.AjaxBehavior;

public abstract class BaseMenuRenderer extends CoreRenderer {

    @Override
	public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
		AbstractMenu menu = (AbstractMenu) component;

		if(menu.shouldBuildFromModel()) {
			menu.buildMenuFromModel();
		}

		encodeMarkup(context, menu);
		encodeScript(context, menu);
	}

    protected abstract void encodeMarkup(FacesContext context, AbstractMenu abstractMenu) throws IOException;

    protected abstract void encodeScript(FacesContext context, AbstractMenu abstractMenu) throws IOException;
	
	protected void encodeMenuItem(FacesContext context, MenuItem menuItem) throws IOException {
		encodeMenuItem(context, menuItem, false);
	}

    protected void encodeMenuItem(FacesContext context, MenuItem menuItem, boolean disabledParent) throws IOException {
		String clientId = menuItem.getClientId(context);
        ResponseWriter writer = context.getResponseWriter();
        String icon = menuItem.getIcon();

		if(menuItem.shouldRenderChildren()) {
			renderChildren(context, menuItem);
		}
        else {
            writer.startElement("a", null);
			String helpText = menuItem.getHelpText();
            writer.writeAttribute("id", clientId, null);
			writer.writeAttribute("title", (helpText != null ? helpText : ""), null);
			String accesskey = menuItem.getAccesskey();
			if (accesskey != null) {
				writer.writeAttribute("accesskey", accesskey, null);
				writer.writeAttribute("tabindex", "0", null);
			}
			if (menuItem.isDisabled() || disabledParent) {
				writer.writeAttribute("class", "ui-state-disabled wijmo-wijmenu-link ui-corner-all", null);
			} else {
				writer.writeAttribute("class", "wijmo-wijmenu-link ui-corner-all", null);
				String url = menuItem.getUrl();
				if(url != null) {
					writer.writeAttribute("href", getEncodedURL(context, menuItem.getUrlEncoding(), url, menuItem.getUrlParameters()), null);
					if(menuItem.getOnclick() != null) writer.writeAttribute("onclick", menuItem.getOnclick(), null);
					if(menuItem.getTarget() != null) writer.writeAttribute("target", menuItem.getTarget(), null);
				} else {
					writer.writeAttribute("style", "cursor:pointer;", null);

					UIComponent form = ComponentUtils.findParentForm(context, menuItem);
					if(form == null) {
						throw new FacesException("Menubar must be inside a form element");
					}


					String onclick = getScript(context, menuItem);
					writer.writeAttribute("onclick", onclick, null);
				}
			}

			writer.startElement("span", null);
			writer.writeAttribute("class", "wijmo-wijmenu-text", null);

            if(icon != null) {
                writer.startElement("span", null);
                writer.writeAttribute("class", icon + " wijmo-wijmenu-icon-left", null);
                writer.endElement("span");
            }

			if(menuItem.getValue() != null) {
                writer.startElement("span", null);
                String style = menuItem.getStyle();
                if (style != null && style.trim().length() > 0) {
                    writer.writeAttribute("style", style, "style");
                }
                Utils.writeConcatenatedStyleClasses(writer, "wijmo-wijmenu-text", menuItem.getStyleClass());
                writer.write((String) menuItem.getValue());
                writer.endElement("span");
            }

			writer.endElement("span");

            writer.endElement("a");
		}
	}

	private static String getScript(FacesContext context, MenuItem menuItem) {
		String clientId = menuItem.getClientId(context);
		boolean hasAjaxBehavior = false;

		StringBuilder submitWithBehavioursCommand = new StringBuilder();
		submitWithBehavioursCommand.append("ice.ace.Menubar.submitWithBehaviours(event, this, ["); // dynamically set the id to the node so that it can be handled by the submit functions
		// ClientBehaviors
		Map> behaviorEvents = menuItem.getClientBehaviors();
		if(!behaviorEvents.isEmpty()) {
            List params = Collections.emptyList();
            for(Iterator behaviorIter = behaviorEvents.get("action").iterator(); behaviorIter.hasNext();) {
                ClientBehavior behavior = behaviorIter.next();
                if (behavior instanceof AjaxBehavior)
                    hasAjaxBehavior = true;
                ClientBehaviorContext cbc = ClientBehaviorContext.createClientBehaviorContext(context, menuItem, "action", clientId, params);
                String script = behavior.getScript(cbc);    //could be null if disabled

                if(script != null) {
                    submitWithBehavioursCommand.append(script);
                    if (behaviorIter.hasNext()) {
                        submitWithBehavioursCommand.append(",");
                    }
                }
            }
        }
		submitWithBehavioursCommand.append("]); ");

		StringBuilder submitWithParametersCommand = new StringBuilder();
		if (!hasAjaxBehavior && (menuItem.getActionExpression() != null || menuItem.getActionListeners().length > 0)) {
            submitWithParametersCommand.append("ice.ace.Menubar.submitWithParameters(event, this, '" + clientId + "'");
            for(UIComponent child : menuItem.getChildren()) {
                if(child instanceof UIParameter) {
                    submitWithParametersCommand.append(", '");
                    UIParameter param = (UIParameter) child;
                    submitWithParametersCommand.append(param.getName());
                    submitWithParametersCommand.append("','");
                    submitWithParametersCommand.append(String.valueOf(param.getValue()));
                    submitWithParametersCommand.append("'");
                }
            }
            submitWithParametersCommand.append(");");
        }

		StringBuilder command = hasAjaxBehavior ? submitWithBehavioursCommand : submitWithParametersCommand;
		String customOnclick = menuItem.getOnclick();
		return customOnclick == null ? command.toString() : customOnclick + ";" + command.toString();
	}

	protected void encodeMenuSeparator(FacesContext context, UIComponent menuSeparator) throws IOException {
		ResponseWriter writer = context.getResponseWriter();
		writer.startElement("li", null);
		writer.writeAttribute("id", menuSeparator.getClientId(context), "id");
		writer.endElement("li");
	}

    @Override
	public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException {
		//Do nothing
	}

    @Override
	public boolean getRendersChildren() {
		return true;
	}
	
	protected void encodeMultiColumnSubmenu(FacesContext context, MultiColumnSubmenu submenu) throws IOException {
		encodeMultiColumnSubmenu(context, submenu, false);
	}
	
	protected void encodeMultiColumnSubmenu(FacesContext context, MultiColumnSubmenu submenu, boolean isPlainMultiColumnMenu) throws IOException {
		ResponseWriter writer = context.getResponseWriter();
		String label = submenu.getLabel();
		String icon = submenu.getIcon();
		boolean disabled = submenu.isDisabled();
		
		List menuColumns = new ArrayList();
		for (UIComponent child : submenu.getChildren()) {
			if (child instanceof MenuColumn) menuColumns.add((MenuColumn) child);
		}

		if (!isPlainMultiColumnMenu) {
			writer.startElement("a", null);
			if (disabled) {
				writer.writeAttribute("class", "ui-state-disabled", null);
			} else {
				writer.writeAttribute("style", "cursor:pointer;", null);
			}
			
			if(icon != null) {
				writer.startElement("span", null);
				writer.writeAttribute("class", icon + " wijmo-wijmenu-icon-left", null);
				writer.endElement("span");
			}

			if(label != null) {
				writer.startElement("span", null);
				String style = submenu.getStyle();
				if (style != null && style.trim().length() > 0) {
					writer.writeAttribute("style", style, "style");
				}
				Utils.writeConcatenatedStyleClasses(writer, "wijmo-wijmenu-text", submenu.getStyleClass());
				writer.write(submenu.getLabel());
				writer.endElement("span");
			}

			writer.endElement("a");
		}
		
		if (disabled) return;
		
		int totalChildren = 0;
		Map>> columnMap = new HashMap>>();
		for (MenuColumn menuColumn : menuColumns) {
			columnMap.put(menuColumn, divideColumn(menuColumn));
			for (ArrayList sublist : columnMap.get(menuColumn)) {
				totalChildren += sublist.size();
			}
		}
		int totalWidth = 0;
		for (MenuColumn menuColumn : menuColumns) {
			if (menuColumn.isRendered()) {
				int columnWidth = menuColumn.getWidth();
				int autoflow = menuColumn.getAutoflow();
				int multiplier = 1;
				if (autoflow > 0) {
					multiplier = totalChildren / autoflow;
					if ((totalChildren % autoflow) > 0) multiplier++;
				}
				totalWidth += (columnWidth * multiplier);
			}
		}
		
		if (isPlainMultiColumnMenu) {
			writer.startElement("ul", null);
		} else {
			writer.startElement("div", null);
		}
		writer.writeAttribute("class", "wijmo-wijmenu ui-menu-multicolumn", "class");
		writer.writeAttribute("style", "width: " + totalWidth + "px;", "style");
		Integer top = submenu.getPositionTop();
		if (top != null) {
			writer.writeAttribute("top", top.intValue(), null);
		}
		Integer left = submenu.getPositionLeft();
		if (left != null) {
			writer.writeAttribute("left", submenu.getPositionLeft(), null);
		}
		String relativeTo = submenu.getRelativeTo();
		if (relativeTo != null) {
			writer.writeAttribute("relativeto", relativeTo.toLowerCase(), null);
		}
		
		// header
		writer.startElement("div", null);
		writer.writeAttribute("style", "width: 100%;", null);
		String headerClass = submenu.getHeaderClass();
		headerClass = headerClass == null ? "" : " " + headerClass;
		writer.writeAttribute("class", "ui-menu-multicolumn-header" + headerClass, null);
		UIComponent header = (UIComponent) submenu.getFacet("header");
		if (header != null) {
			encodeParentAndChildren(context, header);
		} else {
			writer.startElement("div", null);
			writer.endElement("div");
		}
		writer.endElement("div");
			
		for (MenuColumn menuColumn : menuColumns) {
			if (menuColumn.isRendered()) {
				for (ArrayList sublist : columnMap.get(menuColumn)) {
					writer.startElement("div", null);
					writer.writeAttribute("style", "width: " + menuColumn.getWidth() + "px;", "style");

					if(sublist.size() > 0) {
						writer.startElement("ul", null);

						boolean disabledSubmenu = false;
						for (UIComponent item : sublist) {
							if(item.isRendered()) {

								if(item instanceof MenuItem) {
									writer.startElement("li", null);
									encodeMenuItem(context, (MenuItem) item, disabledSubmenu);
									writer.endElement("li");
								} else if(item instanceof MenuSeparator) {
									encodeMenuSeparator(context, item);
								} else if(item instanceof Submenu) {
									Submenu sm = (Submenu) item;
									disabledSubmenu = sm.isDisabled();
									encodeFlatSubmenu(context, sm, disabledSubmenu);
								}
								
							}
						}

						writer.endElement("ul");
					}

					writer.endElement("div");
				}
			}
		}
		
		// footer
		writer.startElement("div", null);
		writer.writeAttribute("style", "width: 100%;", null);
		String footerClass = submenu.getFooterClass();
		footerClass = footerClass == null ? "" : " " + footerClass;
		writer.writeAttribute("class", "ui-menu-multicolumn-footer" + footerClass, null);
		UIComponent footer = (UIComponent) submenu.getFacet("footer");
		if (footer != null) {
			encodeParentAndChildren(context, footer);
		} else {
			writer.startElement("div", null);
			writer.endElement("div");
		}
		writer.endElement("div");
		
		if (isPlainMultiColumnMenu) {
			writer.endElement("ul");
		} else {
			writer.endElement("div");
		}
	}

    protected void encodeFlatSubmenu(FacesContext context, Submenu submenu, boolean disabled) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String label = submenu.getLabel();

        writer.startElement("li", null);
        writer.startElement("h3", null);
        if(label != null) {
			if (disabled) {
				writer.writeAttribute("class", "ui-state-disabled", null);
			} else {
				String style = submenu.getStyle();
				if (style != null && style.trim().length() > 0) {
					writer.writeAttribute("style", style, "style");
				}
				Utils.writeConcatenatedStyleClasses(writer, "", submenu.getStyleClass());
			}
            writer.write(label);
        }
        writer.endElement("h3");
        writer.endElement("li");
	}
	
	protected ArrayList> divideColumn(MenuColumn menuColumn) {
	
		ArrayList> columnList = new ArrayList>();
		if (!menuColumn.isRendered()) return columnList;
		int maxRows = menuColumn.getAutoflow();
		if (maxRows == 0) {
			ArrayList column = flattenContents(menuColumn, new ArrayList());
			columnList.add(column);
		} else {
			ArrayList children = flattenContents(menuColumn, new ArrayList());
			
			if (children.size() <= maxRows) {
				columnList.add(children);
			} else {
				int rowCount = 0;
				ArrayList currentColumn = new ArrayList();
				for (UIComponent child : children) {
					rowCount++;
					currentColumn.add(child);
					if (rowCount == maxRows) {
						rowCount = 0;
						columnList.add(currentColumn);
						currentColumn = new ArrayList();
					}
				}
				if (rowCount > 0) {
					columnList.add(currentColumn);
				}
			}
		}
		
		return columnList;
	}
	
	protected ArrayList flattenContents(UIComponent component, ArrayList result) {
		
		for (UIComponent child : component.getChildren()) {
			if (child.isRendered()) {
				if (child instanceof MenuItem || child instanceof MenuSeparator || child instanceof Submenu) {
					result.add(child);
					if (child instanceof Submenu) {
						flattenContents(child, result);
					}
				}
			}
		}
		
		return result;
	}
	
	public static void encodeParentAndChildren(FacesContext facesContext, UIComponent parent) throws IOException {
        parent.encodeBegin(facesContext);
        if (parent.getRendersChildren()) {
            parent.encodeChildren(facesContext);
        } else {
            if (parent.getChildCount() > 0) {
                Iterator children = parent.getChildren().iterator();
                while (children.hasNext()) {
                    UIComponent nextChild = (UIComponent) children.next();
                    if (nextChild.isRendered()) {
                        encodeParentAndChildren(facesContext, nextChild);
                    }
                }
            }
        }
        parent.encodeEnd(facesContext);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy