update method
Updates the component state in response to a message.
Returns the updated component (often this) and an optional command.
Implementation
@override
(ViewportModel, Cmd?) update(Msg msg) {
switch (msg) {
case KeyMsg(:final key):
if (key.matchesSingle(keyMap.pageDown)) {
return (pageDown(), null);
}
if (key.matchesSingle(keyMap.pageUp)) {
return (pageUp(), null);
}
if (key.matchesSingle(keyMap.halfPageDown)) {
return (halfPageDown(), null);
}
if (key.matchesSingle(keyMap.halfPageUp)) {
return (halfPageUp(), null);
}
if (key.matchesSingle(keyMap.down)) {
return (scrollDown(1), null);
}
if (key.matchesSingle(keyMap.up)) {
return (scrollUp(1), null);
}
if (horizontalStep > 0) {
if (!softWrap && key.matchesSingle(keyMap.left)) {
return (scrollLeft(horizontalStep), null);
}
if (!softWrap && key.matchesSingle(keyMap.right)) {
return (scrollRight(horizontalStep), null);
}
}
if (key.matchesSingle(keyMap.copy)) {
final text = getSelectedText();
if (text.isNotEmpty) {
return (this, Cmd.setClipboard(text));
}
}
return (this, null);
case MouseMsg(
:final button,
:final action,
:final x,
:final y,
:final shift,
):
if (button == MouseButton.left) {
final isOutside =
y < 0 || (height != null ? y >= height! : y >= lines.length);
if (isOutside) {
if (action == MouseAction.press) {
return (clearSelection(), null);
}
return (this, null);
}
if (action == MouseAction.press) {
final contentX = x - gutter + xOffset;
final contentY = y + yOffset;
final now = DateTime.now();
// Check for double click
if (lastClickTime != null &&
now.difference(lastClickTime!) <
const Duration(milliseconds: 500) &&
lastClickPos == (contentX, contentY)) {
final (start, end) = _findWordAt(contentX, contentY);
return (
copyWith(
selectionStart: (start, contentY),
selectionEnd: (end, contentY),
lastClickTime: now,
lastClickPos: (contentX, contentY),
),
null,
);
}
// Start selection
return (
copyWith(
selectionStart: (contentX, contentY),
selectionEnd: (contentX, contentY),
lastClickTime: now,
lastClickPos: (contentX, contentY),
),
null,
);
}
if (action == MouseAction.motion && selectionStart != null) {
// Update selection
final contentX = x - gutter + xOffset;
final contentY = y + yOffset;
return (copyWith(selectionEnd: (contentX, contentY)), null);
}
if (action == MouseAction.release && button == MouseButton.left) {
// Finalize selection (keep it for copying)
return (this, null);
}
}
if (!mouseWheelEnabled ||
(action != MouseAction.press && action != MouseAction.wheel)) {
return (this, null);
}
switch (button) {
case MouseButton.wheelUp:
if (!softWrap && shift && horizontalStep > 0) {
return (scrollLeft(horizontalStep), null);
}
return (scrollUp(mouseWheelDelta), null);
case MouseButton.wheelDown:
if (!softWrap && shift && horizontalStep > 0) {
return (scrollRight(horizontalStep), null);
}
return (scrollDown(mouseWheelDelta), null);
case MouseButton.wheelLeft:
if (!softWrap && horizontalStep > 0) {
return (scrollLeft(horizontalStep), null);
}
return (this, null);
case MouseButton.wheelRight:
if (!softWrap && horizontalStep > 0) {
return (scrollRight(horizontalStep), null);
}
return (this, null);
default:
return (this, null);
}
default:
return (this, null);
}
}