slint/internal/compiler/widgets/common/lineedit-base.slint
Simon Hausmann 368ec3459b
Improve default accessibility of TextInput elements
Apply similar logic as to LineEdit and TextEdit, so that when folks build their own text input widgets, they're accessible by default. Also fixed the docs while at it to mention default applications.

Amends #7669
2025-02-20 13:44:16 +01:00

125 lines
4.2 KiB
Text

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
export component LineEditBase inherits Rectangle {
in property <string> placeholder-text;
in property <length> font-size <=> text-input.font-size;
in-out property <string> text <=> text-input.text;
in-out property <brush> placeholder-color;
in property <bool> enabled <=> text-input.enabled;
out property <bool> has-focus: text-input.has-focus;
in property <InputType> input-type <=> text-input.input-type;
in property <TextHorizontalAlignment> horizontal-alignment <=> text-input.horizontal-alignment;
in property <bool> read-only <=> text-input.read-only;
in property <int> font-weight <=> text-input.font-weight;
in property <brush> text-color;
in property <color> selection-background-color <=> text-input.selection-background-color;
in property <color> selection-foreground-color <=> text-input.selection-foreground-color;
in property <length> margin;
callback accepted(text: string);
callback edited(text: string);
callback key-pressed(event: KeyEvent) -> EventResult;
callback key-released(event: KeyEvent) -> EventResult;
public function set-selection-offsets(start: int, end: int) {
text-input.set-selection-offsets(start, end);
}
public function select-all() {
text-input.select-all();
}
public function clear-selection() {
text-input.clear-selection();
}
public function cut() {
text-input.cut();
}
public function copy() {
text-input.copy();
}
public function paste() {
text-input.paste();
}
// on width < 1px or if the `TextInput` is clipped it cannot be focused therefore min-width 1px
min-width: 1px;
min-height: text-input.preferred-height;
clip: true;
forward-focus: text-input;
placeholder := Text {
width: 100%;
height: 100%;
vertical-alignment: center;
text: (root.text == "" && text-input.preedit-text == "") ? root.placeholder-text : "";
font-size: text-input.font-size;
font-italic: text-input.font-italic;
font-weight: text-input.font-weight;
font-family: text-input.font-family;
color: root.placeholder-color;
horizontal-alignment: root.horizontal-alignment;
// the label is set on the LineEdit itself
accessible-role: none;
}
ContextMenu {
MenuItem {
title: @tr("Cut");
activated => { text-input.cut(); }
}
MenuItem {
title: @tr("Copy");
activated => { text-input.copy(); }
}
MenuItem {
title: @tr("Paste");
activated => { text-input.paste(); }
}
MenuItem {
title: @tr("Select All");
activated => { text-input.select-all(); }
}
text-input := TextInput {
property <length> computed-x;
x: min(0px, max(parent.width - self.width - self.text-cursor-width, self.computed-x));
width: max(parent.width - self.text-cursor-width, self.preferred-width);
height: 100%;
vertical-alignment: center;
single-line: true;
color: root.text-color;
// Disable TextInput's built-in accessibility support as the widget takes care of that.
accessible-role: none;
cursor-position-changed(cursor-position) => {
if cursor-position.x + self.computed_x < root.margin {
self.computed_x = - cursor-position.x + root.margin;
} else if cursor-position.x + self.computed_x > parent.width - root.margin - self.text-cursor-width {
self.computed_x = parent.width - cursor-position.x - root.margin - self.text-cursor-width;
}
}
accepted => {
root.accepted(self.text);
}
edited => {
root.edited(self.text);
}
key-pressed(event) => {
root.key-pressed(event)
}
key-released(event) => {
root.key-released(event)
}
}
}
}