public void renderScreenletBegin(
      Appendable writer,
      Map<String, Object> context,
      boolean collapsed,
      ModelScreenWidget.Screenlet screenlet)
      throws IOException {
    HttpServletRequest request = (HttpServletRequest) context.get("request");
    HttpServletResponse response = (HttpServletResponse) context.get("response");
    boolean javaScriptEnabled = UtilHttp.isJavaScriptEnabled(request);
    ModelScreenWidget.Menu tabMenu = screenlet.getTabMenu();
    if (tabMenu != null) {
      tabMenu.renderWidgetString(writer, context, this);
    }

    String title = screenlet.getTitle(context);
    boolean collapsible = screenlet.collapsible();
    ModelScreenWidget.Menu navMenu = screenlet.getNavigationMenu();
    ModelScreenWidget.Form navForm = screenlet.getNavigationForm();
    String expandToolTip = "";
    String collapseToolTip = "";
    String fullUrlString = "";
    String menuString = "";
    boolean showMore = false;
    if (UtilValidate.isNotEmpty(title) || navMenu != null || navForm != null || collapsible) {
      showMore = true;
      if (collapsible) {
        this.getNextElementId();
        Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
        Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));
        Map<String, Object> requestParameters = new HashMap<String, Object>(paramMap);
        if (uiLabelMap != null) {
          expandToolTip = (String) uiLabelMap.get("CommonExpand");
          collapseToolTip = (String) uiLabelMap.get("CommonCollapse");
        }
        if (!javaScriptEnabled) {
          requestParameters.put(
              screenlet.getPreferenceKey(context) + "_collapsed", collapsed ? "false" : "true");
          String queryString = UtilHttp.urlEncodeArgs(requestParameters);
          fullUrlString = request.getRequestURI() + "?" + queryString;
        }
      }
      if (!collapsed) {
        StringWriter sb = new StringWriter();
        if (navMenu != null) {
          MenuStringRenderer savedRenderer = (MenuStringRenderer) context.get("menuStringRenderer");
          MenuStringRenderer renderer = new ScreenletMenuRenderer(request, response);
          context.put("menuStringRenderer", renderer);
          navMenu.renderWidgetString(sb, context, this);
          context.put("menuStringRenderer", savedRenderer);
        } else if (navForm != null) {
          renderScreenletPaginateMenu(sb, context, navForm);
        }
        menuString = sb.toString();
      }
    }

    Map<String, Object> parameters = FastMap.newInstance();
    parameters.put("id", screenlet.getId(context));
    parameters.put("title", title);
    parameters.put("collapsible", collapsible);
    parameters.put("saveCollapsed", screenlet.saveCollapsed());
    parameters.put("collapsibleAreaId", screenlet.getId(context) + "_col");
    parameters.put("expandToolTip", expandToolTip);
    parameters.put("collapseToolTip", collapseToolTip);
    parameters.put("fullUrlString", fullUrlString);
    parameters.put("padded", screenlet.padded());
    parameters.put("menuString", menuString);
    parameters.put("showMore", showMore);
    parameters.put("collapsed", collapsed);
    parameters.put("javaScriptEnabled", javaScriptEnabled);
    executeMacro(writer, "renderScreenletBegin", parameters);
  }
  protected void renderScreenletPaginateMenu(
      Appendable writer, Map<String, Object> context, ModelScreenWidget.Form form)
      throws IOException {
    HttpServletResponse response = (HttpServletResponse) context.get("response");
    HttpServletRequest request = (HttpServletRequest) context.get("request");
    ModelForm modelForm = form.getModelForm(context);
    modelForm.runFormActions(context);
    modelForm.preparePager(context);
    String targetService = modelForm.getPaginateTarget(context);
    if (targetService == null) {
      targetService = "${targetService}";
    }

    // get the parametrized pagination index and size fields
    int paginatorNumber = WidgetWorker.getPaginatorNumber(context);
    String viewIndexParam = modelForm.getMultiPaginateIndexField(context);
    String viewSizeParam = modelForm.getMultiPaginateSizeField(context);

    int viewIndex = modelForm.getViewIndex(context);
    int viewSize = modelForm.getViewSize(context);
    int listSize = modelForm.getListSize(context);

    int highIndex = modelForm.getHighIndex(context);
    int actualPageSize = modelForm.getActualPageSize(context);

    // if this is all there seems to be (if listSize < 0, then size is unknown)
    if (actualPageSize >= listSize && listSize >= 0) return;

    // needed for the "Page" and "rows" labels
    Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));
    String ofLabel = "";
    if (uiLabelMap == null) {
      Debug.logWarning("Could not find uiLabelMap in context", module);
    } else {
      ofLabel = uiLabelMap.get("CommonOf");
      ofLabel = ofLabel.toLowerCase();
    }

    // for legacy support, the viewSizeParam is VIEW_SIZE and viewIndexParam is VIEW_INDEX when the
    // fields are "viewSize" and "viewIndex"
    if (viewIndexParam.equals("viewIndex" + "_" + paginatorNumber))
      viewIndexParam = "VIEW_INDEX" + "_" + paginatorNumber;
    if (viewSizeParam.equals("viewSize" + "_" + paginatorNumber))
      viewSizeParam = "VIEW_SIZE" + "_" + paginatorNumber;

    ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
    RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

    Map<String, Object> inputFields = UtilGenerics.toMap(context.get("requestParameters"));
    // strip out any multi form fields if the form is of type multi
    if (modelForm.getType().equals("multi")) {
      inputFields = UtilHttp.removeMultiFormParameters(inputFields);
    }
    String queryString = UtilHttp.urlEncodeArgs(inputFields);
    // strip legacy viewIndex/viewSize params from the query string
    queryString = UtilHttp.stripViewParamsFromQueryString(queryString, "" + paginatorNumber);
    // strip parametrized index/size params from the query string
    HashSet<String> paramNames = new HashSet<String>();
    paramNames.add(viewIndexParam);
    paramNames.add(viewSizeParam);
    queryString = UtilHttp.stripNamedParamsFromQueryString(queryString, paramNames);

    String anchor = "";
    String paginateAnchor = modelForm.getPaginateTargetAnchor();
    if (paginateAnchor != null) anchor = "#" + paginateAnchor;

    // preparing the link text, so that later in the code we can reuse this and just add the
    // viewIndex
    String prepLinkText = "";
    prepLinkText = targetService;
    if (prepLinkText.indexOf("?") < 0) {
      prepLinkText += "?";
    } else if (!prepLinkText.endsWith("?")) {
      prepLinkText += "&amp;";
    }
    if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {
      prepLinkText += queryString + "&amp;";
    }
    prepLinkText += viewSizeParam + "=" + viewSize + "&amp;" + viewIndexParam + "=";

    String linkText;

    // The current screenlet title bar navigation syling requires rendering
    // these links in reverse order
    // Last button
    String lastLinkUrl = "";
    if (highIndex < listSize) {
      int page = (listSize / viewSize);
      linkText = prepLinkText + page + anchor;
      lastLinkUrl = rh.makeLink(request, response, linkText);
    }
    String nextLinkUrl = "";
    if (highIndex < listSize) {
      linkText = prepLinkText + (viewIndex + 1) + anchor;
      // - make the link
      nextLinkUrl = rh.makeLink(request, response, linkText);
    }
    String previousLinkUrl = "";
    if (viewIndex > 0) {
      linkText = prepLinkText + (viewIndex - 1) + anchor;
      previousLinkUrl = rh.makeLink(request, response, linkText);
    }
    String firstLinkUrl = "";
    if (viewIndex > 0) {
      linkText = prepLinkText + 0 + anchor;
      firstLinkUrl = rh.makeLink(request, response, linkText);
    }

    Map<String, Object> parameters = FastMap.newInstance();
    parameters.put("lowIndex", modelForm.getLowIndex(context));
    parameters.put("actualPageSize", actualPageSize);
    parameters.put("ofLabel", ofLabel);
    parameters.put("listSize", listSize);
    parameters.put("paginateLastStyle", modelForm.getPaginateLastStyle());
    parameters.put("lastLinkUrl", lastLinkUrl);
    parameters.put("paginateLastLabel", modelForm.getPaginateLastLabel(context));
    parameters.put("paginateNextStyle", modelForm.getPaginateNextStyle());
    parameters.put("nextLinkUrl", nextLinkUrl);
    parameters.put("paginateNextLabel", modelForm.getPaginateNextLabel(context));
    parameters.put("paginatePreviousStyle", modelForm.getPaginatePreviousStyle());
    parameters.put("paginatePreviousLabel", modelForm.getPaginatePreviousLabel(context));
    parameters.put("previousLinkUrl", previousLinkUrl);
    parameters.put("paginateFirstStyle", modelForm.getPaginateFirstStyle());
    parameters.put("paginateFirstLabel", modelForm.getPaginateFirstLabel(context));
    parameters.put("firstLinkUrl", firstLinkUrl);
    executeMacro(writer, "renderScreenletPaginateMenu", parameters);
  }
  public void renderNextPrev(Appendable writer, Map<String, Object> context) throws IOException {
    String targetService = this.getPaginateTarget(context);
    if (targetService == null) {
      targetService = "${targetService}";
    }

    Map<String, Object> inputFields = UtilGenerics.checkMap(context.get("requestParameters"));
    Map<String, Object> queryStringMap = UtilGenerics.toMap(context.get("queryStringMap"));
    if (UtilValidate.isNotEmpty(queryStringMap)) {
      inputFields.putAll(queryStringMap);
    }

    String queryString = UtilHttp.urlEncodeArgs(inputFields);
    int paginatorNumber = this.getPaginatorNumber(context);
    queryString = UtilHttp.stripViewParamsFromQueryString(queryString, "" + paginatorNumber);

    if (UtilValidate.isEmpty(targetService)) {
      Debug.logWarning("TargetService is empty.", module);
      return;
    }

    int viewIndex = -1;
    try {
      viewIndex = ((Integer) context.get("viewIndex")).intValue();
    } catch (Exception e) {
      viewIndex = 0;
    }

    int viewSize = -1;
    try {
      viewSize = ((Integer) context.get("viewSize")).intValue();
    } catch (Exception e) {
      viewSize = this.getViewSize();
    }

    int listSize = -1;
    try {
      listSize = this.getListSize();
    } catch (Exception e) {
      listSize = -1;
    }

    /*
    int highIndex = -1;
    try {
        highIndex = modelForm.getHighIndex();
    } catch (Exception e) {
        highIndex = 0;
    }

    int lowIndex = -1;
    try {
        lowIndex = modelForm.getLowIndex();
    } catch (Exception e) {
        lowIndex = 0;
    }
     */

    int lowIndex = viewIndex * viewSize;
    int highIndex = (viewIndex + 1) * viewSize;
    int actualPageSize = this.getActualPageSize();
    // if this is all there seems to be (if listSize < 0, then size is unknown)
    if (actualPageSize >= listSize && listSize > 0) {
      return;
    }

    HttpServletRequest request = (HttpServletRequest) context.get("request");
    HttpServletResponse response = (HttpServletResponse) context.get("response");

    ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
    RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

    writer.append("<table border=\"0\" width=\"100%\" cellpadding=\"2\">\n");
    writer.append("  <tr>\n");
    writer.append("    <td align=\"right\">\n");
    writer.append("      <b>\n");
    if (viewIndex > 0) {
      writer.append(" <a href=\"");
      StringBuilder linkText = new StringBuilder(targetService);
      if (linkText.indexOf("?") < 0) linkText.append("?");
      else linkText.append("&amp;");
      // if (queryString != null && !queryString.equals("null")) linkText += queryString + "&";
      if (UtilValidate.isNotEmpty(queryString)) {
        linkText.append(queryString).append("&amp;");
      }
      linkText
          .append("VIEW_SIZE_" + paginatorNumber + "=")
          .append(viewSize)
          .append("&amp;VIEW_INDEX_" + paginatorNumber + "=")
          .append(viewIndex - 1)
          .append("\"");

      // make the link
      writer.append(rh.makeLink(request, response, linkText.toString(), false, false, false));
      String previous =
          UtilProperties.getMessage(
              "CommonUiLabels", "CommonPrevious", (Locale) context.get("locale"));
      writer.append(" class=\"buttontext\">[").append(previous).append("]</a>\n");
    }
    if (listSize > 0) {
      Map<String, Integer> messageMap =
          UtilMisc.toMap(
              "lowCount",
              Integer.valueOf(lowIndex + 1),
              "highCount",
              Integer.valueOf(lowIndex + actualPageSize),
              "total",
              Integer.valueOf(listSize));
      String commonDisplaying =
          UtilProperties.getMessage(
              "CommonUiLabels", "CommonDisplaying", messageMap, (Locale) context.get("locale"));
      writer.append(" <span class=\"tabletext\">").append(commonDisplaying).append("</span> \n");
    }
    if (highIndex < listSize) {
      writer.append(" <a href=\"");
      StringBuilder linkText = new StringBuilder(targetService);
      if (linkText.indexOf("?") < 0) linkText.append("?");
      else linkText.append("&amp;");
      if (UtilValidate.isNotEmpty(queryString)) {
        linkText.append(queryString).append("&amp;");
      }
      linkText
          .append("VIEW_SIZE_" + paginatorNumber + "=")
          .append(viewSize)
          .append("&amp;VIEW_INDEX_" + paginatorNumber + "=")
          .append(viewIndex + 1)
          .append("\"");

      // make the link
      writer.append(rh.makeLink(request, response, linkText.toString(), false, false, false));
      String next =
          UtilProperties.getMessage("CommonUiLabels", "CommonNext", (Locale) context.get("locale"));
      writer.append(" class=\"buttontext\">[").append(next).append("]</a>\n");
    }
    writer.append("      </b>\n");
    writer.append("    </td>\n");
    writer.append("  </tr>\n");
    writer.append("</table>\n");
  }