Textbox Behaviour

2021.03.07
Overview
Caret and Selection
Operations
Single-line Movements
Multi-line Movements
Movement-based Commands
Additional Commands
Mouse Input

Overview

This write-up details what could be considered a "full set" of standard core functionality for text input boxes in user interfaces for referential purposes during implementation.

The core components of textbox behaviour are split into three parts: One we can call Movements, which describe a means of moving from one position to the next (eg. one-character-to-the-left), Operations which use a movement to perform an action (eg. select-to) and finally Commmands, most of which will be an operation performing a movement, although they are not limited to this.

Caret and Selection

The caret/selection of a textbox is typically implemented as a pair of integers; both are grouped together as they are part of the same thing. The first integer (we'll refer to this as the head) is the caret's current position; the second integer (the tail) is the other end of the selection — in the case that there is no text selected the head and tail are the same value and only the caret is displayed. In the case that there is text selected the value of both sides differ from one another.

Operations

Textboxes support the following 3 core operations for navigating and editing text; each operation uses a single movement to achieve it's goal — in terms of implementation you could think of each operation implemented as a function which itself takes a movement-function as an argument. As the movements are common between operations this reduces code duplication as each movement only needs to be implemented once to be used by any operation.

The operations are as follows:

Single-line Movements

Single line movements are supported by both single-line textboxes and multi-line text boxes. The core single-line movements are as follows:

If by performing a movement it would result in the position being before the start of the text or after the end of the text, the result should be clamped to the text's bounds.

Multi-line Movements

Multi-line movements are supported only by multi-line text boxes; these are as follows:

In the case of several successive vertical movements the horizontal position should always be as close to the initial horizontal position from the first movement. Vertical movement horizontal positioning should be performed to keep visual consistency rather than character-offset consistency, eg. moving up a line should place the caret as close as possible on the screen to its original horizontal position.

In the case of page-up and page-down the caret should move the distance of the textbox's height. A page-up movement followed by a page-down movement should always result in returning to the original position, with the exception of the case where the page-up movement places the caret at the beginning of the text as there is not a whole textbox-height space above the current position.

Movement-based Commands

By combining the operations and movements described above, the following core commands can be supported:

Both the move-left and move-right commands have a special case: if there is text selected, instead of performing the usual operation of moving one character to the left/right, the caret is instead moved to the corresponding edge of the selected text and the selection is canceled.

Additional Commands

In addition to the movement based commands there are several other commands which do not rely on movement:

Mouse Input

Textboxes typically support mouse input for modifying the selection. There are 3 modes to mouse input, the state of which is determined by the number of clicks that occurred:

When the mouse is pressed down the both sides of the selection are set to the current mouse cursor position. If the mouse is then dragged the head of the selection is moved to that position while the tail remains in place of the original click. If Shift is held when the mouse is clicked the tail of the selection is uneffected and only the head is changed.

The placement of both sides of the selection are based around the granularities specified above, such that, for example, if one were to double click and drag their mouse it would select a word at a time; if one were to triple-click it would select a line at a time.