Package com.esri.gpt.control.view

Source Code of com.esri.gpt.control.view.PageCursorPanel

/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. 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 com.esri.gpt.control.view;

import com.esri.gpt.framework.jsf.FacesContextBroker;
import com.esri.gpt.framework.jsf.MessageBroker;
import com.esri.gpt.framework.request.PageCursor;
import com.esri.gpt.framework.util.Val;

import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UISelectItem;
import javax.faces.component.html.HtmlCommandLink;
import javax.faces.component.html.HtmlOutputLabel;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.component.html.HtmlPanelGrid;
import javax.faces.component.html.HtmlPanelGroup;
import javax.faces.component.html.HtmlSelectOneListbox;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;

/**
* Provides support for binding a page cursor associated with a query result to
* an HtmlPanelGroup.
* <p>
* The cursor requires message resource keys. All resource keys used are
* prefixed with the supplied resourceKeyPrefix property (the default
* value is "general.pageCursor.").
* <p>
* The following resource keys are used by the cursor:
* <br>nomatch results first previous next last
* <p>
* Examples:
* <br/>catalog.general.pageCursor.nomatch  = No matching records were located.
* <br/>catalog.general.pageCursor.results  = Results {0}-{1} of {2} record(s)
* <br/>catalog.general.pageCursor.first    = First
* <br/>catalog.general.pageCursor.previous = <
* <br/>catalog.general.pageCursor.next     = >
* <br/>catalog.general.pageCursor.last     = Last
* <p>
* The "results" resource key is record (not page based) and
* takes the following 3 arguments:
* <br/>The starting record for the current page, the ending record for the
* current page and the total number of records.
* <p>
*/
public class PageCursorPanel {

// class variables =============================================================
/** Default list of results per page. */
private static final Integer[] _defaultResultsPerPage =
  new Integer[]{5, 10, 20, 50};
// instance variables ==========================================================
private String _actionListenerExpression = "";
private String _changeListenerExpression = "";
private HtmlPanelGroup _bottomHtmlPanelGroup;
private String _commandAttributeName;
private String _commandAttributeValue;
private String _currentStyleClass;
private String _cursorPageAttributeName;
private PageCursor _pageCursor;
private String _resourceKeyPrefix;
private String _resultStyleClass;
private HtmlPanelGroup _topHtmlPanelGroup;

// constructors ================================================================
/** Default constructor. */
public PageCursorPanel() {
  this.setCommandAttributeName("command");
  this.setCommandAttributeValue("setCursorPage");
  this.setCurrenStyleClass("current");
  this.setCursorPageAttributeName("cursorPage");
  this.setResourceKeyPrefix("general.pageCursor.");
  this.setResultStyleClass("result");
}

// properties ==================================================================
/**
* Gets the expression used to bind generated command links to the controller.
* <br/>Typically the expression will have the following form:
* <br/>#{SomeController.processAction}
* @return the action listener binding expression
*/
public String getActionListenerExpression() {
  return _actionListenerExpression;
}

/**
* Sets the expression used to bind generated command links to the controller.
* <br/>Typically the expression will have the following form:
* <br/>#{SomeController.processAction}
* @param expression the action listener binding expression
*/
public void setActionListenerExpression(String expression) {
  _actionListenerExpression = Val.chkStr(expression);
}

public String getChangeListenerExpression() {
  return _changeListenerExpression;
}

public void setChangeListenerExpression(String expression) {
  _changeListenerExpression = Val.chkStr(expression);
}
/**
* Gets the bound HtmlPanelGroup for the bottom portion of the page.
* <br/>This object is used during the Faces component binding process.
* @return the bound HtmlPanelGroup
*/
public HtmlPanelGroup getBottomHtmlPanelGroup() {
  return _bottomHtmlPanelGroup;
}

/**
* Sets the bound HtmlPanelGroup for the bottom portion of the page.
* <br/>This object is used during the Faces component binding process.
* @param htmlPanelGroup the bound HtmlPanelGroup
*/
public void setBottomHtmlPanelGroup(HtmlPanelGroup htmlPanelGroup) {
  _bottomHtmlPanelGroup = htmlPanelGroup;
}

/**
* Gets the name of the attribute used to indicate the command that
* should be executed.
* <br/>The default value is "command".
* @return the command attribute name
*/
public String getCommandAttributeName() {
  return _commandAttributeName;
}

/**
* Sets the name of the attribute used to indicate the command that
* should be executed.
* <br/>The default value is "command".
* @param name the command attribute name
*/
public void setCommandAttributeName(String name) {
  _commandAttributeName = Val.chkStr(name);
}

/**
* Gets value of the command attribute indicating that a page cursor
* navigation event has occurred.
* <br/>The default value is "setCursorPage".
* @return the command attribute value for a page cursor navigation event
*/
public String getCommandAttributeValue() {
  return _commandAttributeValue;
}

/**
* Sets value of the command attribute indicating that a page cursor
* navigation event has occurred.
* <br/>The default value is "setCursorPage".
* @param value the command attribute value for a page cursor navigation event
*/
public void setCommandAttributeValue(String value) {
  _commandAttributeValue = Val.chkStr(value);
}

/**
* Gets the style class associated with the current page.
* <br/>The default value is "current".
* @return the current page style class
*/
public String getCurrentStyleClass() {
  return _currentStyleClass;
}

/**
* Sets the style class associated with the current page.
* <br/>The default value is "current".
* @param styleClass the current page style class
*/
public void setCurrenStyleClass(String styleClass) {
  _currentStyleClass = Val.chkStr(styleClass);
}

/**
* Gets the name of the attribute used to indicate the cursor page.
* <br/>The default value is "cursorPage".
* @return the cursor page attribute name
*/
public String getCursorPageAttributeName() {
  return _cursorPageAttributeName;
}

/**
* Sets the name of the attribute used to indicate the cursor page.
* <br/>The default value is "cursorPage".
* @param name the cursor page attribute name
*/
public void setCursorPageAttributeName(String name) {
  _cursorPageAttributeName = Val.chkStr(name);
}

/**
* Gets the underlying page cursor.
* <br/>The page cursor UI will be generated from the content of this cursor.
* @return the page cursor
*/
public PageCursor getPageCursor() {
  return _pageCursor;
}

/**
* Sets the underlying page cursor.
* <br/>The page cursor UI will be generated from the content of this cursor.
* <br/>Setting the page cursor triggers the building of the HtmlPanelGroup
* UI components.
* <br/>This method should be invoked immediately following the generation
* of query results.
* @param cursor the page cursor
*/
public void setPageCursor(PageCursor cursor) {
  _pageCursor = cursor;
  build();
}

/**
* Gets the resource key prefix to be used when generating UI components.
* <br/>The default value is "general.pageCursor.".
* @return the resource key prefix
*/
public String getResourceKeyPrefix() {
  return _resourceKeyPrefix;
}

/**
* Sets the resource key prefix to be used when generating UI components.
* <br/>The default value is "general.pageCursor.".
* @param resourceKeyPrefix the resource key prefix
*/
public void setResourceKeyPrefix(String resourceKeyPrefix) {
  _resourceKeyPrefix = Val.chkStr(resourceKeyPrefix);
}

/**
* Gets the style class associated with the result text.
* <br/>The result text takes the form:
* <br/>Results 1-10 of 61 record(s)
* <br/>The default value is "result".
* @return the result text style class
*/
public String getResultStyleClass() {
  return _resultStyleClass;
}

/**
* Sets the style class associated with the result text.
* <br/>The result text takes the form:
* <br/>Results 1-10 of 61 record(s)
* <br/>The default value is "result".
* @param styleClass the result text style class
*/
public void setResultStyleClass(String styleClass) {
  _resultStyleClass = Val.chkStr(styleClass);
}

/**
* Gets the bound HtmlPanelGroup for the top portion of the page.
* <br/>This object is used during the Faces component binding process.
* @return the bound HtmlPanelGroup
*/
public HtmlPanelGroup getTopHtmlPanelGroup() {
  return _topHtmlPanelGroup;
}

/**
* Sets the bound HtmlPanelGroup for the top portion of the page.
* <br/>This object is used during the Faces component binding process.
* @param htmlPanelGroup the bound HtmlPanelGroup
*/
public void setTopHtmlPanelGroup(HtmlPanelGroup htmlPanelGroup) {
  _topHtmlPanelGroup = htmlPanelGroup;
}

// methods =====================================================================
/**
* Builds the components of the top and bottom HtmlPanelGroup based upon the content
* of the PageCursor.
*/
public void build() {
  build(getTopHtmlPanelGroup(), getPageCursor(), false);
  build(getBottomHtmlPanelGroup(), getPageCursor(), true);
}

/**
* Builds the components of an HtmlPanelGroup based upon the content
* of the PageCursor.
* @param navigationPanelGroup the panel group to build
* @param cursor the underlying page cursor
* @param isBottom true if we are building the bottom panel
*/
private void build(HtmlPanelGroup masterPanelGroup,
                    PageCursor cursor,
                    boolean isBottom) {

  // clear existing children, return if there is nothing to build
  if (masterPanelGroup != null) {
    masterPanelGroup.getChildren().clear();
  }
  if ((masterPanelGroup == null) || (cursor == null)) {
    return;
  }

  // don't build the bottom panel if it's not really necessary
  if (isBottom && ((cursor.getEndRecord() - cursor.getStartRecord()) < 4)) {
    return;
  }

  // initialize parameters
  int nPage;
  String sMsg;
  String sRecordsPerPageMsg;
  HtmlCommandLink cmdLink;
  HtmlOutputText outText;
  FacesContextBroker ctxBroker = new FacesContextBroker();
  FacesContext facesContext = ctxBroker.getFacesContext();
  MessageBroker msgBroker = ctxBroker.extractMessageBroker();
  String sKeyPfx = getResourceKeyPrefix();

  // check the cursor
  cursor.checkCurrentPage();
  int nStartPage = cursor.getStartPage();
  int nEndPage = cursor.getEndPage();
  int nTotalPageCount = cursor.getTotalPageCount();

  // add the result text
  Integer[] args = new Integer[3];
  if (nTotalPageCount == 0) {
    sMsg = msgBroker.retrieveMessage(sKeyPfx + "nomatch", args);
  } else {
    args[0] = cursor.getStartRecord();
    args[1] = cursor.getEndRecord();
    args[2] = cursor.getTotalRecordCount();
    sMsg = msgBroker.retrieveMessage(sKeyPfx + "results", args);
  }

  sRecordsPerPageMsg = msgBroker.retrieveMessage(sKeyPfx + "resultsPerPage");

  // create grid to separate navigoation panel from records per page panel
  HtmlPanelGrid panelGrid = new HtmlPanelGrid();
  masterPanelGroup.getChildren().add(panelGrid);
  panelGrid.setBorder(0);
  panelGrid.setColumns(2);
  panelGrid.setWidth("100%");
  panelGrid.setColumnClasses("nav,count");

  // create navigation panel
  HtmlPanelGroup navigationPanelGroup = new HtmlPanelGroup();
  panelGrid.getChildren().add(navigationPanelGroup);

  outText = makeResultText(facesContext, sMsg);
  navigationPanelGroup.getChildren().add(outText);

  int linkCount = 0;

  // add page navigation links
  if (nTotalPageCount > 1) {

    // first and previous pages
    if (cursor.getHasPreviousPage()) {
      if (nStartPage != 1) {
        sMsg = msgBroker.retrieveMessage(sKeyPfx + "first");
        cmdLink = makePageLink(facesContext, 1, sMsg, isBottom, ++linkCount);
        navigationPanelGroup.getChildren().add(cmdLink);
      }
      nPage = cursor.getPreviousPage();
      sMsg = msgBroker.retrieveMessage(sKeyPfx + "previous");
      cmdLink = makePageLink(facesContext, nPage, sMsg, isBottom, ++linkCount);
      navigationPanelGroup.getChildren().add(cmdLink);
    }

    // pages
    for (int i = nStartPage; i <= nEndPage; i++) {
      cmdLink = makePageLink(facesContext, i, "" + i, isBottom, ++linkCount);
      navigationPanelGroup.getChildren().add(cmdLink);
    }

    // next and last pages
    if (cursor.getHasNextPage()) {
      nPage = cursor.getNextPage();
      sMsg = msgBroker.retrieveMessage(sKeyPfx + "next");
      cmdLink = makePageLink(facesContext, nPage, sMsg, isBottom, ++linkCount);
      navigationPanelGroup.getChildren().add(cmdLink);
      if (nEndPage != nTotalPageCount) {
        sMsg = msgBroker.retrieveMessage(sKeyPfx + "last");
        cmdLink = makePageLink(facesContext, nTotalPageCount, sMsg, isBottom, ++linkCount);
        navigationPanelGroup.getChildren().add(cmdLink);
      }
    }
  }

  // create records per page panel
  if (!isBottom && getChangeListenerExpression().length()>0) {
    HtmlPanelGroup resultsPerPagePanelGroup = new HtmlPanelGroup();
    panelGrid.getChildren().add(resultsPerPagePanelGroup);

    // listbox id
    String listBoxId = "recsPerPage";
   
    // Display label
    HtmlOutputLabel resultsPerPageLabel =
      makeResultsLabel(facesContext, sRecordsPerPageMsg);
    resultsPerPagePanelGroup.getChildren().add(resultsPerPageLabel);
    resultsPerPageLabel.setFor(listBoxId);

    // Create lisbox
    HtmlSelectOneListbox listBox = new HtmlSelectOneListbox();
    resultsPerPagePanelGroup.getChildren().add(listBox);
    listBox.setId(listBoxId);

    listBox.setSize(1);
    listBox.setValue(Integer.toString(cursor.getRecordsPerPage()));
    UIComponent form = findForm(masterPanelGroup);
    if (form!=null) {
      String inChangeExpression =
        "document.forms['"+form.getId()+"'].submit(); return false;";
      listBox.setOnchange(inChangeExpression);
    }

    // create listener
    Class[] parms = new Class[]{ValueChangeEvent.class};
    MethodBinding mb =
      FacesContext.getCurrentInstance().getApplication().createMethodBinding(
      getChangeListenerExpression(), parms);
    listBox.setValueChangeListener(mb);

    // create list content
    Set<Integer> rpp =
      new TreeSet<Integer>(Arrays.asList(_defaultResultsPerPage));
    rpp.add(new Integer(cursor.getRecordsPerPage()));

    for (Integer p : rpp) {
      int resultPerPage = p.intValue();
      UISelectItem selectItem = new UISelectItem();
      listBox.getChildren().add(selectItem);
      selectItem.setItemLabel(Integer.toString(resultPerPage));
      selectItem.setItemValue(Integer.toString(resultPerPage));
    }

  }
}

/**
* Calles when record per page has changed.
* @param event event
*/
public void onChange(ValueChangeEvent event) {
  _pageCursor.setRecordsPerPage(
    Val.chkInt(event.getNewValue().toString(),
               _pageCursor.getRecordsPerPage()));
}

/**
* Checks an action event to determine if this is a page cursor navigation event.
* <br/>If so, the current page of the associated page cursor is set.
* <br/>This method will not re-execute a query, it will simply reset the
* current page.
* <br/>To rebuild the underlying UI components, user the setPageCursor() or
* build() methods.
* @param event the associated JSF action event
* @param resetPageIfNot if true, reset the current page to 1 if this was not
*        a page cursor navigation event
* @return <code>true</code> page cursor event detected
*/
public boolean checkActionEvent(ActionEvent event, boolean resetPageIfNot) {

  // determine if the command is a page cursor navigation event
  boolean bWasPageCursorEvent = false;
  if (event != null) {
    UIComponent component = event.getComponent();
    String sName = getCommandAttributeName();
    String sCmd = (String) component.getAttributes().get(sName);
    if (Val.chkStr(sCmd).equalsIgnoreCase(getCommandAttributeValue())) {
      bWasPageCursorEvent = true;

      // determine the page to navigate to
      sName = getCursorPageAttributeName();
      String sPage = (String) component.getAttributes().get(sName);
      int nPage = Val.chkInt(sPage, -1);
      if (nPage < 1) {
        nPage = 1;
      }
      if (getPageCursor() != null) {
        getPageCursor().setCurrentPage(nPage);
      }
    }
  }

  // reset the current page if this was not a page cursor navigation event
  if (!bWasPageCursorEvent && resetPageIfNot) {
    if (getPageCursor() != null) {
      getPageCursor().setCurrentPage(1);
    }
  }
  return bWasPageCursorEvent;
}

/**
* Makes an HtmlCommandLink component for UI page cursor navigation.
* @param facesContext the active Faces context
* @param page the subject page
* @param pageText the text for the subject page
* @return the new HtmlCommandLink component
*/
private HtmlCommandLink makePageLink(FacesContext facesContext,
                                      int page,
                                      String pageText, boolean isBottom, int linkCount) {
  HtmlCommandLink cmd = new HtmlCommandLink();
  String sExpr = getActionListenerExpression();
  Class a[] = {ActionEvent.class};
  MethodBinding mb = facesContext.getApplication().createMethodBinding(sExpr, a);
  cmd.setValue(pageText);
  cmd.setId((isBottom? "bottomLink_":"topLink_")+linkCount);
  cmd.setActionListener(mb);
  cmd.getAttributes().put(getCommandAttributeName(), getCommandAttributeValue());
  cmd.getAttributes().put(getCursorPageAttributeName(), "" + page);
  if (page == getPageCursor().getCurrentPage()) {
    if (getCurrentStyleClass().length() > 0) {
      cmd.setStyleClass(getCurrentStyleClass());
    }
  }
  return cmd;
}

/**
* Makes an HtmlOutputText component for result text display.
* @param facesContext the active Faces context
* @param text the text to display
* @return the new HtmlOutputText component
*/
private HtmlOutputText makeResultText(FacesContext facesContext, String text) {
  HtmlOutputText outText = new HtmlOutputText();
  outText.setEscape(false);
  outText.setValue(text);
  if (getResultStyleClass().length() > 0) {
    outText.setStyleClass(getResultStyleClass());
  }
  return outText;
}


/**
* Makes an HtmlOutputLabel component for result text display.
* @param facesContext the active Faces context
* @param text the text to display
* @return the new HtmlOutputLabel component
*/
private HtmlOutputLabel makeResultsLabel(FacesContext facesContext, String text) {
  HtmlOutputLabel outLabel = new HtmlOutputLabel();
  outLabel.setEscape(false);
  outLabel.setValue(text);
  if (getResultStyleClass().length() > 0) {
    outLabel.setStyleClass(getResultStyleClass());
  }
  return outLabel;
}

/**
* Looks for the parent form.
* @param component child component
* @return form or <code>null</code> if form doesn't exist
*/
private UIComponent findForm(UIComponent component) {
  if (component==null) {
    return null;
  }
  if (component.getFamily().equals(UIForm.COMPONENT_FAMILY)) {
    return component;
  }
  return findForm(component.getParent());
}
}
TOP

Related Classes of com.esri.gpt.control.view.PageCursorPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.