newVisible.y -= (visible.height - newVisible.height);
newVisible.y -= visible.height - newVisible.height;
    public void actionPerformed(ActionEvent e)    {      String command = (String) getValue(Action.NAME);      boolean extendSelection = command.equals("scrollUpExtendSelection")                                || command.equals("scrollDownExtendSelection");      boolean changeSelection = command.equals("scrollUpChangeSelection")                                || command.equals("scrollDownChangeSelection");      // Disable change lead, unless we are in discontinuous mode.      if (!extendSelection && !changeSelection          && tree.getSelectionModel().getSelectionMode() !=            TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION)        {          changeSelection = true;        }      int rowCount = getRowCount(tree);      if (rowCount > 0 && treeSelectionModel != null)        {          Dimension maxSize = tree.getSize();          TreePath lead = tree.getLeadSelectionPath();          TreePath newPath = null;          Rectangle visible = tree.getVisibleRect();          if (direction == -1) // The RI handles -1 as up.            {              newPath = getClosestPathForLocation(tree, visible.x, visible.y);              if (newPath.equals(lead)) // Corner case, adjust one page up.                {                  visible.y = Math.max(0, visible.y - visible.height);                  newPath = getClosestPathForLocation(tree, visible.x,                                                      visible.y);                }            }          else // +1 is down.            {              visible.y = Math.min(maxSize.height,                                   visible.y + visible.height - 1);              newPath = getClosestPathForLocation(tree, visible.x, visible.y);              if (newPath.equals(lead)) // Corner case, adjust one page down.                {                  visible.y = Math.min(maxSize.height,                                       visible.y + visible.height - 1);                  newPath = getClosestPathForLocation(tree, visible.x,                                                      visible.y);                }            }          // Determine new visible rect.          Rectangle newVisible = getPathBounds(tree, newPath);          newVisible.x = visible.x;          newVisible.width = visible.width;          if (direction == -1)            {              newVisible.height = visible.height;            }          else            {              newVisible.y -= (visible.height - newVisible.height);              newVisible.height = visible.height;            }          if (extendSelection)            {              // Extend selection.              TreePath anchorPath = tree.getAnchorSelectionPath();              if (anchorPath == null)                {                  tree.setSelectionPath(newPath);                }              else                {                  int newIndex = getRowForPath(tree, newPath);                  int anchorIndex = getRowForPath(tree, anchorPath);                  tree.setSelectionInterval(Math.min(anchorIndex, newIndex),                                            Math.max(anchorIndex, newIndex));                  tree.setAnchorSelectionPath(anchorPath);                  tree.setLeadSelectionPath(newPath);                }            }          else if (changeSelection)            {              tree.setSelectionPath(newPath);            }          else // Change lead.            {              tree.setLeadSelectionPath(newPath);            }          tree.scrollRectToVisible(newVisible);        }    }