protected void processKeyEvent (java.awt.event.KeyEvent e) {

		// TODO: Convert into Actions and put into InputMap/ActionMap?
		if (e.getID()==KeyEvent.KEY_PRESSED) {
			switch (e.getKeyCode()) {
				case KeyEvent.VK_LEFT:
					boolean extend = e.isShiftDown();
					int offs = Math.max(leadSelectionIndex-1, 0);
					changeSelectionByOffset(offs, extend);
					e.consume();
					break;
				case KeyEvent.VK_RIGHT:
					extend = e.isShiftDown();
					offs = Math.min(leadSelectionIndex+1, model.getByteCount()-1);
					changeSelectionByOffset(offs, extend);
					e.consume();
					break;
				case KeyEvent.VK_UP:
					extend = e.isShiftDown();
					offs = Math.max(leadSelectionIndex-16, 0);
					changeSelectionByOffset(offs, extend);
					e.consume();
					break;
				case KeyEvent.VK_DOWN:
					extend = e.isShiftDown();
					offs = Math.min(leadSelectionIndex+16, model.getByteCount()-1);
					changeSelectionByOffset(offs, extend);
					e.consume();
					break;
				case KeyEvent.VK_PAGE_DOWN:
					extend = e.isShiftDown();
					int visibleRowCount = getVisibleRect().height/getRowHeight();
					offs = Math.min(leadSelectionIndex+visibleRowCount*16,
									model.getByteCount()-1);
					changeSelectionByOffset(offs, extend);
					e.consume();
					break;
				case KeyEvent.VK_PAGE_UP:
					extend = e.isShiftDown();
					visibleRowCount = getVisibleRect().height/getRowHeight();
					offs = Math.max(leadSelectionIndex-visibleRowCount*16, 0);
					changeSelectionByOffset(offs, extend);
					e.consume();
					break;
				case KeyEvent.VK_HOME:
					extend = e.isShiftDown();
					offs = (leadSelectionIndex/16)*16;
					changeSelectionByOffset(offs, extend);
					e.consume();
					break;
				case KeyEvent.VK_END:
					extend = e.isShiftDown();
					offs = (leadSelectionIndex/16)*16 + 15;
					offs = Math.min(offs, model.getByteCount()-1);
					changeSelectionByOffset(offs, extend);
					e.consume();
					break;
			}
		}

		super.processKeyEvent(e);

	}