gt:             if (startIndex > numElements - elementsToFit) {
context: /*
   *  
   *
   * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
   * 
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License version
   * 2 only, as published by the Free Software Foundation. 
   * 
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License version 2 for more details (a copy is
   * included at /legal/license.txt). 
   * 
   * You should have received a copy of the GNU General Public License
   * version 2 along with this work; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   * 02110-1301 USA 
   * 
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
   * Clara, CA 95054 or visit www.sun.com if you need additional
   * information or have any questions. 
   */
  
  package javax.microedition.lcdui;
  
  import com.sun.midp.lcdui.EventConstants;
  
  import com.sun.midp.lcdui.*;
  import com.sun.midp.configurator.Constants;
  import com.sun.midp.chameleon.skins.DateEditorSkin;
  import com.sun.midp.chameleon.skins.ChoiceGroupSkin;
  import com.sun.midp.chameleon.layers.ScrollIndLayer;
  import com.sun.midp.chameleon.layers.ScrollablePopupLayer;
  import com.sun.midp.chameleon.skins.ScrollIndSkin;
  import com.sun.midp.chameleon.skins.resources.ScrollIndResourcesConstants;
  
  
  /**
   * This is a popup layer that handles a sub-popup within the date editor,
   * which is also a popup layer.
   */
  class DEPopupLayer extends ScrollablePopupLayer {
      /**
       * Constructs a date editor sub-popup layer, which behaves like a
       * popup-choicegroup, given a string array of elements that constitute
       * the available list of choices to select from.
       *
       * @param editor The DateEditor that triggered this popup layer.
       * @param elements String array holding the list of choices.
       * @param selectedIndex the index to place the initial highlight on.
       * @param circularTraversal true if traversal past the last item should
       *                          jump to the beginning 
       */
      DEPopupLayer(DateEditor editor, String[] elements, int selectedIndex,
                   boolean circularTraversal) {
          super((Image)null, DateEditorSkin.COLOR_POPUPS_BG);
          this.editor = editor;
          
          setContent(elements, selectedIndex);
          this.circularTraversal = circularTraversal;
      }        
  
      /**
       * Populates this sub-popup layer with new elements.
       * The number of elements before and after should be the same
       * if the popup already existed.
       *
       * @param newElements String array holding the list of choices.
       * @param selectedIndex the index to place the initial highlight on.
       */
      protected void setContent(String[] newElements, int selectedIndex) {
          if (newElements != null) {
              numElements = newElements.length;
              elements = new String[numElements];
              System.arraycopy(newElements, 0, elements, 0, numElements);
  
              this.selectedIndex = selectedIndex;
              hilightedIndex = selectedIndex;
          }
          startIndex = 0;
      }
  
      /**
       * Initializes the popup layer.
       */
      protected void initialize() {
          super.initialize();
          viewport = new int[4];
      }        
      
      /**
       * Sets the bounds of the popup layer.
       *
       * @param x the x-coordinate of the popup layer location
       * @param y the y-coordinate of the popup layer location
       * @param w the width of this popup layer in open state
       * @param h the height of this popup layer in open state
       */
      public void setBounds(int x, int y, int w, int h) {
          super.setBounds(x, y, w, h);
          transparent = false;
          
              // set viewport in popup's coordinate system
          viewport[X] = 2;
          viewport[Y] = 0;
          viewport[W] = bounds[W] - 3;
          viewport[H] = bounds[H] - 3;
  
          elementsToFit = viewport[H] / elementHeight;
          if (elementsToFit < numElements) {
              sbVisible = true;
          } else {
              elementsToFit = numElements;
              sbVisible = false;
          }
      }
  
     /**
       * Helper function to determine the itemIndex at the x,y position
       *
       * @param x,y  pointer coordinates
       * @return  item's index since 0, or PRESS_OUT_OF_BOUNDS.
       *
       */
      private int itemIndexAtPointerPosition(int x, int y) {
          int id = PRESS_OUT_OF_BOUNDS; 
          if (containsPoint(x + bounds[X], y + bounds[Y])) {
              id = (int)(y / elementHeight);
          }
          return id;
      }
      
      /**
       * Handles pointer event in the open popup.
       *
       * @param type - The type of this pointer event (pressed, released, dragged)
       * @param x x coordinate
       * @param x y coordinate
       * @return true always, since popupLayers swallow all pointer events
       */
      public boolean pointerInput(int type, int x, int y) {
          boolean consume = true;
          switch (type) {
          case EventConstants.PRESSED:
              itemIndexWhenPressed =  itemIndexAtPointerPosition(x, y);
              if (itemIndexWhenPressed == PRESS_OUT_OF_BOUNDS) {
                  hide();
                  consume = false;
              } else if (itemIndexWhenPressed >= 0 &&
                  // press on valid item
                  hilightedIndex != itemIndexWhenPressed + startIndex) { 
                  hilightedIndex = itemIndexWhenPressed + startIndex;
                  requestRepaint();
              } 
              break;
          case EventConstants.RELEASED:
              int itemIndexWhenReleased = itemIndexAtPointerPosition(x,y);
              
              if (itemIndexWhenReleased == itemIndexWhenPressed) {
                  if (itemIndexWhenPressed >=0) {
                      keyInput(EventConstants.PRESSED, Constants.KEYCODE_SELECT);
                  } else {
                      hide();
                  }
              }
  
              if (itemIndexWhenReleased == PRESS_OUT_OF_BOUNDS) {
                  consume = false;
              }            
              //remember to reset the variables
              itemIndexWhenPressed = PRESS_OUT_OF_BOUNDS; 
              break;
          }
          return consume; 
      }
  
  
      /**
       * Handles key event in the open popup.
       *
       * @param type - The type of this key event (pressed, released)
       * @param code - The code of this key event
       * @return true always, since popupLayers swallow all key events
       */
      public boolean keyInput(int type, int code) {
          if ((type == EventConstants.PRESSED ||
               type == EventConstants.REPEATED) && editor != null) 
          {
              switch (code) {
                  case Constants.KEYCODE_SELECT:
                      editor.keyInput(type, code);
                      break;
                  case Constants.KEYCODE_UP:
                  case Constants.KEYCODE_DOWN:
                  case Constants.KEYCODE_LEFT:
                  case Constants.KEYCODE_RIGHT:
                      traverseInPopup(code);
                      break;
              }
          }
          // PopupLayers always swallow all key events
          return true;
      }
  
      /**
       * Paints popup background (including borders) and scrollbar
       * if it is present.
       * @param g - The graphics object to paint background on
       */
      public void paintBackground(Graphics g) {
          super.paintBackground(g);
          g.setColor(DateEditorSkin.COLOR_BORDER);
          g.drawRect(0, -1, bounds[W] - 1, bounds[H]);
          
          
          if (sbVisible && ScrollIndSkin.MODE == 
                  ScrollIndResourcesConstants.MODE_ARROWS) {
              int sbX = bounds[W] - 6;
              int sbY = 5;
              int sbH = bounds[H] - 12;
              int thumbY = sbY - 4 + 
                  ((((hilightedIndex + 1) * 100) / numElements) * sbH) / 100;
              g.setColor(DateEditorSkin.COLOR_BORDER);
  
              // draw scrollbar
              g.drawLine(sbX, sbY, sbX, sbY + sbH - 1);
              
              // draw scrollbar thumb
              g.fillRect(sbX - (3 / 2), thumbY, 3, 4);
          }
      }
  
      /**
       * Paints the body of the popup layer.
       *
       * @param g The graphics context to paint to
       */
      public void paintBody(Graphics g) {
          boolean hilighted = false;
          int translatedY = 0;
          
          int transY = elementHeight;
          g.translate(2, 0);
          
          endIndex = startIndex + (elementsToFit - 1);
          
          if (hilightedIndex > endIndex) {
              endIndex = hilightedIndex;
              startIndex = endIndex - (elementsToFit - 1);
          }
          
          g.setFont(DateEditorSkin.FONT_POPUPS);
          for (int i = startIndex; i <= endIndex; i++) {
              hilighted = (i == hilightedIndex);
          
              if (hilighted) {
                  g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND);
                  g.fillRect(0, 0, elementWidth - 7, elementHeight);
              }
          
              g.setColor(0);
              g.drawString(elements[i], 2, 0, 0);
              g.translate(0, transY);
              translatedY += transY;
          }
          
          g.translate(-2, -translatedY); 
      }
  
  
      // ********** package private *********** //
  
      /**
       * Gets currently selected index.
       *
       * @return currently selected index
       */
      int getSelectedIndex() {
          return hilightedIndex;
      }
      
      /**
       * Sets currently selected index.
       *
       * @param selId currently selected index
       */
      void setSelectedIndex(int selId) {
          selectedIndex = selId;
      }
      
      /**
       * Set the choice element size (width and height).
       *
       * @param w width of the element
       * @param h height of the element
       */
      void setElementSize(int w, int h) {
          elementWidth = w;
          elementHeight = h;
      }
  
      /**
       * Handle traversal in the open popup.
       *
       * @param code the code of the key event
       * @return true always, since popupLayers swallow all key events
       */
      boolean traverseInPopup(int code) {
          boolean updated = true;
          if (code == Constants.KEYCODE_UP) {
              if (hilightedIndex > 0) {
                  hilightedIndex--;
                  if (hilightedIndex < startIndex) {
                      startIndex--;
                  }
              } else if (circularTraversal) {
                  // jump to the last element
                  hilightedIndex = numElements - 1;
                  startIndex = hilightedIndex - elementsToFit + 1;
              } else {
                  updated = false;
              }
          } else if (code == Constants.KEYCODE_DOWN) {
              if (hilightedIndex < (numElements - 1)) {
                  hilightedIndex++;
                  if (hilightedIndex > endIndex) {
                      startIndex++;
                  }
              } else if (circularTraversal) {
                  // jump to the first element
                  hilightedIndex = 0;
                  startIndex = 0;
              } else {
                  updated = false;
              }
          }
          if (updated) {
              updateScrollIndicator();
              requestRepaint();
          }
  
          return true;
      }
      
      /**
       * show current popup
       * @param sLF popup owner screen 
       */
      public void show(ScreenLFImpl sLF) {
          this.sLF = sLF;
          sLF.lGetCurrentDisplay().showPopup(this);          
          this.open = true;
          
          // update startIndex to let the selected item shown
          hilightedIndex = selectedIndex;
          startIndex = hilightedIndex;
          if (startIndex > numElements - elementsToFit) {
              // startIndex too bottom, adjust it
              startIndex = numElements - elementsToFit;
          }
          if (startIndex < 0) {
              startIndex = 0;
          }
          
          if (ScrollIndSkin.MODE == ScrollIndResourcesConstants.MODE_BAR) {
              setScrollInd(ScrollIndLayer.getInstance(ScrollIndSkin.MODE));
          }
          
          updateScrollIndicator();
      }
  
      /**
       * hide current popup
       */
      public void hide() {
          if (scrollInd != null) {
              scrollInd.setVisible(false);
              sbVisible = false;
              updateScrollIndicator();
              setScrollInd(null);
          }
          if (this.sLF != null) {
              sLF.lGetCurrentDisplay().hidePopup(this);
          }
          editor.requestRepaint();
          // it is necessary, to make sure correctly showing the space occupied by this popup
          this.sLF = null;
          this.open = false;
      }
  
      /**
       * Scroll content inside of the DEPopup.
       * @param scrollType scrollType. Scroll type can be one of the following
       * @see ScrollIndLayer.SCROLL_NONE
       * @see ScrollIndLayer.SCROLL_PAGEUP
       * @see ScrollIndLayer.SCROLL_PAGEDOWN
       * @see ScrollIndLayer.SCROLL_LINEUP
       * @see ScrollIndLayer.SCROLL_LINEDOWN or
       * @see ScrollIndLayer.SCROLL_THUMBTRACK
       * @param thumbPosition
       */
      public void scrollContent(int scrollType, int thumbPosition) {
          switch (scrollType) {
              case ScrollIndLayer.SCROLL_PAGEUP:
                  uScrollViewport(Canvas.UP);
                  break;
              case ScrollIndLayer.SCROLL_PAGEDOWN:
                  uScrollViewport(Canvas.DOWN);
                  break;
              case ScrollIndLayer.SCROLL_LINEUP:
                  uScrollByLine(Canvas.UP);
                  break;
              case ScrollIndLayer.SCROLL_LINEDOWN:
                  uScrollByLine(Canvas.DOWN);
                  break;
              case ScrollIndLayer.SCROLL_THUMBTRACK:
                  uScrollAt(thumbPosition);
                  break;
              default:
                  break;
          }
      }
  
      /**
       * Perform a page flip in the given direction. This method will
       * attempt to scroll the view to show as much of the next page
       * as possible. It uses the locations and bounds of the items on
       * the page to best determine a new location - taking into account
       * items which may lie on page boundaries as well as items which
       * may span several pages.
       *
       * @param dir the direction of the flip, either DOWN or UP
       */
      private void uScrollViewport(int dir) {
          switch (dir) {
          case Canvas.UP:
              startIndex -= elementsToFit - 1; // with top item still visible in new viewport
              if (startIndex < 0) {
                  startIndex = 0;
              }
              break;
          case Canvas.DOWN:
              startIndex += elementsToFit - 1; // with bottom item still visible in new viewport
  