public void moveViewportDown(int rows, boolean selection) {

		// Do some object checking up front and exit if these aren't set.
		if (!isStateValid()) {
			return;
		}

		// Calculate the position of the viewport if we were to move it down the number of 
		// rows given.
		Point newViewportPos =
			new Point(0, (int) viewport.getViewPosition().getY() + (table.getRowHeight() * rows));
		int viewportBottom = newViewportPos.y + viewport.getHeight();

		// Save off the new viewport pos; this will be our new location unless we need to 
		// adjust it by adding/removing new chunks.
		savePosition = newViewportPos.y;

		// If our proposed new viewport position pushes it beyond the bounds of the table, we have
		// to load a new chunk.
		if (viewportBottom >= table.getHeight()) {

			try {

				// Read in the next chunk and make sure we get some valid lines. If we don't get
				// any valid lines, then we must be at the end of the file so just move the 
				// viewport to the bottom.
				List<String> readLines = reader.readNextChunk();
				if (readLines.size() > 0) {

					// We have valid rows, so add them to the table (at the bottom, because we're 
					// reading the next chunk).
					((FVTableModel) table.getModel()).addRowsToBottom(readLines);

					// If adding that chunk just put us over the chunk limit we want to show, we 
					// have to remove one from the top, and adjust our viewport accordingly.
					if (model.getSize() > model.MAX_VISIBLE_CHUNKS) {
						Chunk chunk = model.remove(0);
						newViewportPos = new Point(0,
							newViewportPos.y - (table.getRowHeight() * chunk.linesInChunk));
						savePosition = newViewportPos.y;

						((FVTableModel) table.getModel()).removeRowsFromTop(chunk.linesInChunk);
					}
				}
				else {
					moveViewportToBottom();
					if (selection) {
						updateSelectionToViewportBottom();
					}
					return;
				}
			}
			catch (IOException e) {
				Msg.error(this,
					"Error creating loading new chunk for viewport increment", e);
			}
		}

		// At this point we should have a valid new viewport position, so set it.
		setPosition(new Point(0, savePosition));
		
		// And if necessary, set new selection to encompass the bottom row that's in the viewport.
		if (selection) {
			updateSelectionToViewportBottom();
		}
	}
Moves the viewport down the number of rows specified. If moving down puts he view below 
the bounds of the first-visible chunk, load the next chunk.

@param rows
@param selection
Ghidra/Framework/Project/src/main/java/ghidra/framework/main/logviewer/ui/ViewportUtility.java