|
Administrator
|
Hi Adrian,
This commit "introduced" (actually new file) a NPE in MacroMenuRenderer.java due to if (menuItem.getDisabled() || isDisableIfEmpty(menuItem, context)) { target = null; } in case you have a <condition disabled-style="disabled"> in a menu item, like in (this is the only case) <menu-item name="createOrder" title="${uiLabelMap.OrderCreateOrder}"> <condition disabled-style="disabled"> <and> <not><if-empty field="quote"/></not> <if-compare operator="equals" value="QUO_APPROVED" field="quote.statusId"/> </and> </condition> <link target="loadCartFromQuote"> <parameter param-name="quoteId" from-field="quote.quoteId"/> <parameter param-name="finalizeMode" value="init"/> </link> </menu-item> A simple temporary workaround is to remove "disabled-style="disabled" in the condition. I will commit this temporary workaround, to be removed with you fix. BTW I believe the style associated with "disabled-style="disabled" should be upated Thanks Jacques [hidden email] wrote: > Author: adrianc > Date: Sun Aug 25 18:00:43 2013 > New Revision: 1517353 > > URL: http://svn.apache.org/r1517353 > Log: > Converted menu widget HTML renderer to a macro renderer. > > Added: > ofbiz/trunk/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java > ofbiz/trunk/framework/widget/templates/htmlMenuMacroLibrary.ftl > Modified: > ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java > > Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java > URL: > http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java?rev=1517353&view=auto > ============================================================================== --- > ofbiz/trunk/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java (added) +++ > ofbiz/trunk/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java Sun Aug 25 18:00:43 2013 @@ -0,0 +1,347 @@ > +/******************************************************************************* > + * Licensed to the Apache Software Foundation (ASF) under one > + * or more contributor license agreements. See the NOTICE file > + * distributed with this work for additional information > + * regarding copyright ownership. The ASF licenses this file > + * to you 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. > + *******************************************************************************/ > +package org.ofbiz.widget.menu; > + > +import java.io.IOException; > +import java.io.Reader; > +import java.io.StringReader; > +import java.io.StringWriter; > +import java.math.BigDecimal; > +import java.util.HashMap; > +import java.util.List; > +import java.util.Map; > + > +import javax.servlet.ServletContext; > +import javax.servlet.http.HttpServletRequest; > +import javax.servlet.http.HttpServletResponse; > + > +import org.ofbiz.base.util.Debug; > +import org.ofbiz.base.util.StringUtil; > +import org.ofbiz.base.util.UtilMisc; > +import org.ofbiz.base.util.UtilValidate; > +import org.ofbiz.base.util.template.FreeMarkerWorker; > +import org.ofbiz.webapp.control.RequestHandler; > +import org.ofbiz.webapp.taglib.ContentUrlTag; > +import org.ofbiz.widget.ModelWidget; > +import org.ofbiz.widget.WidgetWorker; > +import org.ofbiz.widget.menu.ModelMenuItem.Image; > +import org.ofbiz.widget.menu.ModelMenuItem.Link; > + > +import freemarker.core.Environment; > +import freemarker.template.Template; > +import freemarker.template.TemplateException; > + > +public class MacroMenuRenderer implements MenuStringRenderer { > + > + public static final String module = MacroMenuRenderer.class.getName(); > + private int macroCount = 999; > + private final Map<Appendable, Environment> environments = new HashMap<Appendable, Environment>(); > + private final Template macroLibrary; > + private final HttpServletRequest request; > + private final HttpServletResponse response; > + > + public MacroMenuRenderer(String macroLibraryPath, HttpServletRequest request, HttpServletResponse response) throws > TemplateException, IOException { + this.macroLibrary = FreeMarkerWorker.getTemplate(macroLibraryPath); > + this.request = request; > + this.response = response; > + } > + > + // Made this a separate method so it can be externalized and reused. > + private Map<String, Object> createImageParameters(Map<String, Object> context, Image image) { > + Map<String, Object> parameters = new HashMap<String, Object>(); > + parameters.put("id", image.getId(context)); > + parameters.put("style", image.getStyle(context)); > + parameters.put("width", image.getWidth(context)); > + parameters.put("height", image.getHeight(context)); > + parameters.put("border", image.getBorder(context)); > + String src = image.getSrc(context); > + if (UtilValidate.isNotEmpty(src) && request != null && response != null) { > + String urlMode = image.getUrlMode(); > + if ("ofbiz".equalsIgnoreCase(urlMode)) { > + boolean fullPath = false; > + boolean secure = false; > + boolean encode = false; > + ServletContext ctx = (ServletContext) request.getAttribute("servletContext"); > + RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_"); > + src = rh.makeLink(request, response, src, fullPath, secure, encode); > + } else if ("content".equalsIgnoreCase(urlMode)) { > + StringBuilder newURL = new StringBuilder(); > + ContentUrlTag.appendContentPrefix(request, newURL); > + newURL.append(src); > + src = newURL.toString(); > + } > + } > + parameters.put("src", src); > + return parameters; > + } > + > + private void executeMacro(Appendable writer, String macro) throws IOException, TemplateException { > + Environment environment = getEnvironment(writer); > + Reader templateReader = new StringReader(macro); > + macroCount++; > + String templateName = toString().concat("_") + macroCount; > + Template template = new Template(templateName, templateReader, FreeMarkerWorker.getDefaultOfbizConfig()); > + templateReader.close(); > + environment.include(template); > + } > + > + private void executeMacro(Appendable writer, String macroName, Map<String, Object> macroParameters) throws IOException, > TemplateException { + StringBuilder sb = new StringBuilder("<@"); > + sb.append(macroName); > + if (macroParameters != null) { > + for (Map.Entry<String, Object> parameter : macroParameters.entrySet()) { > + sb.append(' '); > + sb.append(parameter.getKey()); > + sb.append("="); > + Object value = parameter.getValue(); > + if (value instanceof String) { > + sb.append('"'); > + sb.append(((String) value).replaceAll("\"", "\\\\\"")); > + sb.append('"'); > + } else { > + sb.append(value); > + } > + } > + } > + sb.append(" />"); > + if (Debug.verboseOn()) { > + Debug.logVerbose("Executing macro: " + sb, module); > + } > + executeMacro(writer, sb.toString()); > + } > + > + private Environment getEnvironment(Appendable writer) throws TemplateException, IOException { > + Environment environment = environments.get(writer); > + if (environment == null) { > + Map<String, Object> input = UtilMisc.toMap("key", null); > + environment = FreeMarkerWorker.renderTemplate(macroLibrary, input, writer); > + environments.put(writer, environment); > + } > + return environment; > + } > + > + private boolean isDisableIfEmpty(ModelMenuItem menuItem, Map<String, Object> context) { > + boolean disabled = false; > + String disableIfEmpty = menuItem.getDisableIfEmpty(); > + if (UtilValidate.isNotEmpty(disableIfEmpty)) { > + List<String> keys = StringUtil.split(disableIfEmpty, "|"); > + for (String key : keys) { > + Object obj = context.get(key); > + if (obj == null) { > + disabled = true; > + break; > + } > + } > + } > + return disabled; > + } > + > + private boolean isHideIfSelected(ModelMenuItem menuItem, Map<String, Object> context) { > + ModelMenu menu = menuItem.getModelMenu(); > + String currentMenuItemName = menu.getSelectedMenuItemContextFieldName(context); > + String currentItemName = menuItem.getName(); > + Boolean hideIfSelected = menuItem.getHideIfSelected(); > + return (hideIfSelected != null && hideIfSelected.booleanValue() && currentMenuItemName != null && > currentMenuItemName.equals(currentItemName)); + } > + > + @Override > + public void renderFormatSimpleWrapperClose(Appendable writer, Map<String, Object> context, ModelMenu menu) throws > IOException { + // Nothing to do. > + } > + > + @Override > + public void renderFormatSimpleWrapperOpen(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException > { + // Nothing to do. > + } > + > + @Override > + public void renderFormatSimpleWrapperRows(Appendable writer, Map<String, Object> context, Object menu) throws IOException { > + List<ModelMenuItem> menuItemList = ((ModelMenu) menu).getMenuItemList(); > + for (ModelMenuItem currentMenuItem : menuItemList) { > + renderMenuItem(writer, context, currentMenuItem); > + } > + } > + > + @Override > + public void renderImage(Appendable writer, Map<String, Object> context, Image image) throws IOException { > + Map<String, Object> parameters = createImageParameters(context, image); > + try { > + executeMacro(writer, "renderImage", parameters); > + } catch (TemplateException e) { > + throw new IOException(e); > + } > + } > + > + @Override > + public void renderLink(Appendable writer, Map<String, Object> context, Link link) throws IOException { > + Map<String, Object> parameters = new HashMap<String, Object>(); > + String target = link.getTarget(context); > + ModelMenuItem menuItem = link.getLinkMenuItem(); > + if (menuItem.getDisabled() || isDisableIfEmpty(menuItem, context)) { > + target = null; > + } > + parameters.put("id", link.getId(context)); > + parameters.put("style", link.getStyle(context)); > + parameters.put("name", link.getName(context)); > + parameters.put("text", link.getText(context)); > + parameters.put("targetWindow", link.getTargetWindow(context)); > + String uniqueItemName = menuItem.getModelMenu().getName() + "_" + menuItem.getName() + "_LF_" + UtilMisc.<String> > addToBigDecimalInMap(context, "menuUniqueItemIndex", BigDecimal.ONE); + parameters.put("uniqueItemName", uniqueItemName); > + String linkType = WidgetWorker.determineAutoLinkType(link.getLinkType(), target, link.getUrlMode(), request); > + parameters.put("linkType", linkType); > + String linkUrl = ""; > + String actionUrl = ""; > + StringBuilder targetParameters = new StringBuilder(); > + if ("hidden-form".equals(linkType) || "ajax-window".equals(linkType)) { > + StringBuilder sb = new StringBuilder(); > + WidgetWorker.buildHyperlinkUrl(sb, target, link.getUrlMode(), null, link.getPrefix(context), link.getFullPath(), > link.getSecure(), link.getEncode(), request, response, context); + actionUrl = sb.toString(); > + targetParameters.append("["); > + for (Map.Entry<String, String> parameter : link.getParameterMap(context).entrySet()) { > + if (targetParameters.length() > 1) { > + targetParameters.append(","); > + } > + targetParameters.append("{'name':'"); > + targetParameters.append(parameter.getKey()); > + targetParameters.append("'"); > + targetParameters.append(",'value':'"); > + targetParameters.append(parameter.getValue()); > + targetParameters.append("'}"); > + } > + targetParameters.append("]"); > + > + } > + if (UtilValidate.isNotEmpty(target)) { > + if (!"hidden-form".equals(linkType)) { > + StringBuilder sb = new StringBuilder(); > + WidgetWorker.buildHyperlinkUrl(sb, target, link.getUrlMode(), link.getParameterMap(context), > link.getPrefix(context), link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context); + > linkUrl = sb.toString(); + } > + } > + parameters.put("linkUrl", linkUrl); > + parameters.put("actionUrl", actionUrl); > + parameters.put("parameterList", targetParameters.toString()); > + String imgStr = ""; > + Image img = link.getImage(); > + if (img != null) { > + StringWriter sw = new StringWriter(); > + renderImage(sw, context, img); > + imgStr = sw.toString(); > + } > + parameters.put("imgStr", imgStr); > + try { > + executeMacro(writer, "renderLink", parameters); > + } catch (TemplateException e) { > + throw new IOException(e); > + } > + } > + > + @Override > + public void renderMenuClose(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException { > + Map<String, Object> parameters = null; > + if (ModelWidget.widgetBoundaryCommentsEnabled(context)) { > + parameters = new HashMap<String, Object>(); > + StringBuilder sb = new StringBuilder("End Menu Widget "); > + sb.append(menu.getBoundaryCommentName()); > + parameters.put("boundaryComment", sb.toString()); > + } > + try { > + executeMacro(writer, "renderMenuEnd", parameters); > + } catch (TemplateException e) { > + throw new IOException(e); > + } > + } > + > + @Override > + public void renderMenuItem(Appendable writer, Map<String, Object> context, ModelMenuItem menuItem) throws IOException { > + if (isHideIfSelected(menuItem, context)) > + return; > + Map<String, Object> parameters = new HashMap<String, Object>(); > + String style = menuItem.getWidgetStyle(); > + if (menuItem.isSelected(context)) { > + style = menuItem.getSelectedStyle(); > + if (UtilValidate.isEmpty(style)) { > + style = "selected"; > + } > + } > + if (menuItem.getDisabled() || this.isDisableIfEmpty(menuItem, context)) { > + style = menuItem.getDisabledTitleStyle(); > + } > + if (style == null) { > + style = ""; > + } > + String alignStyle = menuItem.getAlignStyle(); > + if (UtilValidate.isNotEmpty(alignStyle)) { > + style = style.concat(" ").concat(alignStyle); > + } > + parameters.put("style", style); > + parameters.put("toolTip", menuItem.getTooltip(context)); > + String linkStr = ""; > + Link link = menuItem.getLink(); > + if (link != null) { > + StringWriter sw = new StringWriter(); > + renderLink(sw, context, link); > + linkStr = sw.toString(); > + } else { > + linkStr = menuItem.getTitle(context); > + StringUtil.SimpleEncoder simpleEncoder = (StringUtil.SimpleEncoder) context.get("simpleEncoder"); > + if (simpleEncoder != null) { > + linkStr = simpleEncoder.encode(linkStr); > + } > + } > + parameters.put("linkStr", linkStr); > + boolean containsNestedMenus = !menuItem.getMenuItemList().isEmpty(); > + parameters.put("containsNestedMenus", containsNestedMenus); > + try { > + executeMacro(writer, "renderMenuItemBegin", parameters); > + } catch (TemplateException e) { > + throw new IOException(e); > + } > + if (containsNestedMenus) { > + for (ModelMenuItem childMenuItem : menuItem.getMenuItemList()) { > + childMenuItem.renderMenuItemString(writer, context, this); > + } > + } > + parameters.clear(); > + parameters.put("containsNestedMenus", containsNestedMenus); > + try { > + executeMacro(writer, "renderMenuItemEnd", parameters); > + } catch (TemplateException e) { > + throw new IOException(e); > + } > + } > + > + @Override > + public void renderMenuOpen(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException { > + Map<String, Object> parameters = new HashMap<String, Object>(); > + if (ModelWidget.widgetBoundaryCommentsEnabled(context)) { > + StringBuilder sb = new StringBuilder("Begin Menu Widget "); > + sb.append(menu.getBoundaryCommentName()); > + parameters.put("boundaryComment", sb.toString()); > + } > + parameters.put("id", menu.getId()); > + parameters.put("style", menu.getMenuContainerStyle(context)); > + parameters.put("title", menu.getTitle(context)); > + try { > + executeMacro(writer, "renderMenuBegin", parameters); > + } catch (TemplateException e) { > + throw new IOException(e); > + } > + } > +} > > Modified: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java > URL: > http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java?rev=1517353&r1=1517352&r2=1517353&view=diff > ============================================================================== --- > ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java (original) +++ > ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java Sun Aug 25 18:00:43 2013 @@ -38,8 +38,10 @@ > import org.ofbiz.webapp.view.AbstractVie > import org.ofbiz.webapp.view.ViewHandlerException; > import org.ofbiz.widget.form.FormStringRenderer; > import org.ofbiz.widget.form.MacroFormRenderer; > -import org.ofbiz.widget.tree.TreeStringRenderer; > +import org.ofbiz.widget.menu.MacroMenuRenderer; > +import org.ofbiz.widget.menu.MenuStringRenderer; > import org.ofbiz.widget.tree.MacroTreeRenderer; > +import org.ofbiz.widget.tree.TreeStringRenderer; > import org.xml.sax.SAXException; > > import freemarker.template.TemplateException; > @@ -90,15 +92,13 @@ public class MacroScreenViewHandler exte > ScreenStringRenderer screenStringRenderer = new MacroScreenRenderer(UtilProperties.getPropertyValue("widget", > getName() + ".name"), UtilProperties.getPropertyValue("widget", getName() + ".screenrenderer")); FormStringRenderer > formStringRenderer = new MacroFormRenderer(UtilProperties.getPropertyValue("widget", getName() + ".formrenderer"), > request, response); TreeStringRenderer treeStringRenderer = new MacroTreeRenderer(UtilProperties.getPropertyValue("widget", > getName() + ".treerenderer"), writer); > - // TODO: uncomment these lines when the renderers are implemented > - //MenuStringRenderer menuStringRenderer = new MacroMenuRenderer(UtilProperties.getPropertyValue("widget", getName() > + ".menurenderer"), writer); + MenuStringRenderer menuStringRenderer = new > MacroMenuRenderer(UtilProperties.getPropertyValue("widget", getName() + ".menurenderer"), request, response); > > ScreenRenderer screens = new ScreenRenderer(writer, null, screenStringRenderer); > screens.populateContextForRequest(request, response, servletContext); > - // this is the object used to render forms from their definitions > screens.getContext().put("formStringRenderer", formStringRenderer); > screens.getContext().put("treeStringRenderer", treeStringRenderer); > - //screens.getContext().put("menuStringRenderer", menuStringRenderer); > + screens.getContext().put("menuStringRenderer", menuStringRenderer); > screens.getContext().put("simpleEncoder", StringUtil.getEncoder(UtilProperties.getPropertyValue("widget", getName() + > ".encoder"))); screenStringRenderer.renderScreenBegin(writer, screens.getContext()); > screens.render(page); > > Added: ofbiz/trunk/framework/widget/templates/htmlMenuMacroLibrary.ftl > URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/templates/htmlMenuMacroLibrary.ftl?rev=1517353&view=auto > ============================================================================== > --- ofbiz/trunk/framework/widget/templates/htmlMenuMacroLibrary.ftl (added) > +++ ofbiz/trunk/framework/widget/templates/htmlMenuMacroLibrary.ftl Sun Aug 25 18:00:43 2013 > @@ -0,0 +1,72 @@ > +<#-- > +Licensed to the Apache Software Foundation (ASF) under one > +or more contributor license agreements. See the NOTICE file > +distributed with this work for additional information > +regarding copyright ownership. The ASF licenses this file > +to you 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. > +--> > + > +<#macro renderMenuBegin boundaryComment id style title> > + <#if boundaryComment?has_content> > +<!-- ${boundaryComment} --> > + </#if> > + <div<#if id?has_content> id="${id}"</#if><#if style?has_content> class="${style}"</#if>> > + <#if title?has_content> > + <h2>${title}</h2> > + </#if> > + <ul> > + <li> > + <ul> > +</#macro> > + > +<#macro renderMenuEnd boundaryComment> > + </ul> > + </li> > + </ul> > + <br class="clear"/> > + </div> > + <#if boundaryComment?has_content> > +<!-- ${boundaryComment} --> > + </#if> > +</#macro> > + > +<#macro renderImage src id style width height border> > + <img src="${src}"<#if id?has_content> id="${id}"</#if><#if style?has_content> class="${style}"</#if><#if width?has_content> > width="${width}"</#if><#if height?has_content> height="${height}"</#if><#if border?has_content> border="${border}"</#if> /> > +</#macro> + > +<#macro renderLink linkType linkUrl parameterList targetWindow uniqueItemName actionUrl id="" style="" name="" height="" > width="" text="" imgStr=""> + <#if "hidden-form" == linkType> > + <form method="post" action="${actionUrl}"<#if targetWindow?has_content> target="${targetWindow}"</#if> > onsubmit="javascript:submitFormDisableSubmits(this)" name="${uniqueItemName}"><#rt/> + <#list parameterList as parameter> > + <input name="${parameter.name}" value="${parameter.value}" type="hidden"/><#rt/> > + </#list> > + </form><#rt/> > + </#if> > + <a<#if id?has_content> id="${id}"</#if><#if style?has_content> class="${style}"</#if><#if name?has_content> > name="${name}"</#if><#if targetWindow?has_content> target="${targetWindow}"</#if> href="<#if > "hidden-form"==linkType>javascript:document.${uniqueItemName}.submit()<#else>${linkUrl}</#if>"><#if > imgStr?has_content>${imgStr}</#if><#if text?has_content>${text}</#if></a> +</#macro> + +<#macro renderMenuItemBegin style toolTip > linkStr containsNestedMenus> + <li<#if style?has_content> class="${style}"</#if><#if toolTip?has_content> title="${title}"</#if>> > + <#if linkStr?has_content>${linkStr}</#if> > + <#if containsNestedMenus> > + <ul> > + </#if> > +</#macro> > + > +<#macro renderMenuItemEnd containsNestedMenus> > + <#if containsNestedMenus> > + </ul> > + </#if> > + </li> > +</#macro> |
| Free forum by Nabble | Edit this page |
