1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: MIT
3
4import { Palette } from "std-widgets.slint";
5import { UsecasesPalette } from "styling.slint";
6
7// copied from common that is not public now
8component LineEditBase inherits Rectangle {
9 in property <string> placeholder-text;
10 in property <length> font-size <=> text-input.font-size;
11 in_out property <string> text <=> text-input.text;
12 in property <brush> placeholder-color;
13 in property <bool> enabled <=> text-input.enabled;
14 in property <bool> has-focus: text-input.has-focus;
15 in property <InputType> input-type <=> text-input.input-type;
16 in property <TextHorizontalAlignment> horizontal-alignment <=> text-input.horizontal-alignment;
17 in property <bool> read-only <=> text-input.read-only;
18 in property <int> font-weight <=> text-input.font-weight;
19 in property <brush> text-color;
20 in property <color> selection-background-color <=> text-input.selection-background-color;
21 in property <color> selection-foreground-color <=> text-input.selection-foreground-color;
22 in property <length> margin;
23
24 callback accepted( /* text */ string);
25 callback edited(/* text */ string);
26
27 public function set-selection-offsets(start: int, end: int) {
28 text-input.set-selection-offsets(start, end);
29 }
30
31 public function select-all() {
32 text-input.select-all();
33 }
34
35 public function clear-selection() {
36 text-input.clear-selection();
37 }
38
39 public function cut() {
40 text-input.cut();
41 }
42
43 public function copy() {
44 text-input.copy();
45 }
46
47 public function paste() {
48 text-input.paste();
49 }
50
51 min-height: text-input.preferred-height;
52 min-width: max(50px, placeholder.min-width);
53 clip: true;
54 forward-focus: text-input;
55
56 placeholder := Text {
57 width: 100%;
58 height: 100%;
59 vertical-alignment: center;
60 text: (root.text == "" && text-input.preedit-text == "") ? root.placeholder-text : "";
61 font-size: text-input.font-size;
62 font-italic: text-input.font-italic;
63 font-weight: text-input.font-weight;
64 font-family: text-input.font-family;
65 color: root.placeholder-color;
66 horizontal-alignment: root.horizontal-alignment;
67 }
68
69 text-input := TextInput {
70 property <length> computed-x;
71
72 x: min(0px, max(parent.width - self.width - self.text-cursor-width, self.computed-x));
73 width: max(parent.width - self.text-cursor-width, self.preferred-width);
74 height: 100%;
75 vertical-alignment: center;
76 single-line: true;
77 color: root.text-color;
78
79 cursor-position-changed(cpos) => {
80 if (cpos.x + self.computed_x < root.margin) {
81 self.computed_x = - cpos.x + root.margin;
82 } else if (cpos.x + self.computed_x > parent.width - root.margin - self.text-cursor-width) {
83 self.computed_x = parent.width - cpos.x - root.margin - self.text-cursor-width;
84 }
85 }
86
87 accepted => { root.accepted(self.text); }
88
89 edited => { root.edited(self.text); }
90 }
91}
92
93export component ExtendedLineEdit {
94 in property <bool> enabled <=> base.enabled;
95 in property <InputType> input-type <=> base.input-type;
96 in property <TextHorizontalAlignment> horizontal-alignment <=> base.horizontal-alignment;
97 in property <bool> read-only <=> base.read-only;
98 in property <length> font-size <=> base.font-size;
99 in property <string> placeholder-text <=> base.placeholder-text;
100 out property <bool> has-focus <=> base.has-focus;
101 in-out property <string> text <=> base.text;
102
103 property <length> style-min-height: UsecasesPalette.use-material ? 56px : 32px;
104
105 callback accepted <=> base.accepted;
106 callback edited <=> base.edited;
107 accessible-role: text-input;
108 accessible-value <=> text;
109
110 public function set-selection-offsets(start: int, end: int) {
111 base.set-selection-offsets(start, end);
112 }
113
114 public function select-all() {
115 base.select-all();
116 }
117
118 public function clear-selection() {
119 base.clear-selection();
120 }
121
122 public function cut() {
123 base.cut();
124 }
125
126 public function copy() {
127 base.copy();
128 }
129
130 public function paste() {
131 base.paste();
132 }
133
134 vertical-stretch: 0;
135 horizontal-stretch: 1;
136 min-width: max(160px, layout.min-width);
137 min-height: max(root.style-min-height, layout.min-height);
138 forward-focus: base;
139
140 states [
141 disabled when !root.enabled : {
142 root.opacity: 0.5;
143 }
144 ]
145
146 background := Rectangle {
147 border-radius: UsecasesPalette.use-material ? 4px : 8px;
148 background: UsecasesPalette.use-material ? transparent : Palette.control-background;
149 border-width: root.has-focus && UsecasesPalette.use-material ? 2px : 1px;
150 border-color: UsecasesPalette.control-divider;
151
152 layout := HorizontalLayout {
153 padding-left: 16px;
154 padding-right: 16px;
155 spacing: 8px;
156
157 HorizontalLayout {
158 @children
159 }
160
161 base := LineEditBase {
162 font-size: 15 * 0.0769rem;
163 font-weight: 400;
164 selection-background-color: Palette.selection-background;
165 selection-foreground-color: Palette.accent-foreground;
166 text-color: Palette.foreground;
167 placeholder-color: UsecasesPalette.placeholder-foreground;
168 margin: layout.padding-left + layout.padding-right;
169 }
170 }
171
172 if root.has-focus && root.enabled : Rectangle {
173 width: parent.width + 2px;
174 height: parent.height + 2px;
175 border-radius: parent.border-radius + 2px;
176 border-color: UsecasesPalette.state-focus;
177 border-width: 1px;
178 }
179 }
180}
181