1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial |
3 | |
4 | import { CosmicFontSettings, CosmicPalette } from "styling.slint" ; |
5 | import { ScrollView } from "scrollview.slint" ; |
6 | |
7 | export component TextEdit { |
8 | in property <TextWrap> wrap <=> text-input.wrap; |
9 | in property <TextHorizontalAlignment> horizontal-alignment <=> text-input.horizontal-alignment; |
10 | in property <bool> read-only <=> text-input.read-only; |
11 | in property <length> font-size <=> text-input.font-size; |
12 | in property <bool> enabled <=> text-input.enabled; |
13 | in-out property <bool> has-focus: text-input.has-focus; |
14 | out property <length> visible-width <=> scroll-view.visible-width; |
15 | out property <length> visible-height <=> scroll-view.visible-height; |
16 | in-out property <string> text <=> text-input.text; |
17 | in-out property <length> viewport-x <=> scroll-view.viewport-x; |
18 | in-out property <length> viewport-y <=> scroll-view.viewport-y; |
19 | in-out property <length> viewport-width <=> scroll-view.viewport-width; |
20 | in-out property <length> viewport-height <=> scroll-view.viewport-height; |
21 | |
22 | callback edited(/* text */ string); |
23 | |
24 | public function set-selection-offsets(start: int, end: int) { |
25 | text-input.set-selection-offsets(start, end); |
26 | } |
27 | |
28 | public function select-all() { |
29 | text-input.select-all(); |
30 | } |
31 | |
32 | public function clear-selection() { |
33 | text-input.clear-selection(); |
34 | } |
35 | |
36 | public function cut() { |
37 | text-input.cut(); |
38 | } |
39 | |
40 | public function copy() { |
41 | text-input.copy(); |
42 | } |
43 | |
44 | public function paste() { |
45 | text-input.paste(); |
46 | } |
47 | |
48 | forward-focus: text-input; |
49 | horizontal-stretch: 1; |
50 | vertical-stretch: 1; |
51 | |
52 | states [ |
53 | disabled when !root.enabled : { |
54 | root.opacity: 0.5; |
55 | } |
56 | ] |
57 | |
58 | background := Rectangle { |
59 | width: 100%; |
60 | height: 100%; |
61 | border-radius: 8px; |
62 | background: CosmicPalette.control-background; |
63 | border-width: 1px; |
64 | border-color: CosmicPalette.control-divider; |
65 | |
66 | scroll-view := ScrollView { |
67 | x: 12px; |
68 | y: 12px; |
69 | width: parent.width - 24px; |
70 | height: parent.height - 24px; |
71 | viewport-width: root.wrap == TextWrap.word-wrap ? self.visible-width : max(self.visible-width, text-input.preferred-width); |
72 | viewport-height: max(self.visible-height, text-input.preferred-height); |
73 | |
74 | text-input := TextInput { |
75 | enabled: true; |
76 | color: CosmicPalette.foreground; |
77 | font-size: CosmicFontSettings.body.font-size; |
78 | font-weight: CosmicFontSettings.body.font-weight; |
79 | selection-background-color: CosmicPalette.selection-background; |
80 | selection-foreground-color: CosmicPalette.accent-foreground; |
81 | single-line: false; |
82 | wrap: word-wrap; |
83 | |
84 | edited => { |
85 | root.edited(self.text); |
86 | } |
87 | |
88 | cursor-position-changed(cpos) => { |
89 | if (cpos.x + root.viewport-x < 12px) { |
90 | root.viewport-x = min(0px, max(parent.visible-width - self.width, - cpos.x + 12px )); |
91 | } else if (cpos.x + root.viewport-x > parent.visible-width - 12px) { |
92 | root.viewport-x = min(0px, max(parent.visible-width - self.width, parent.visible-width - cpos.x - 12px )); |
93 | } |
94 | if (cpos.y + root.viewport-y < 12px) { |
95 | root.viewport-y = min(0px, max(parent.visible-height - self.height, - cpos.y + 12px )); |
96 | } else if (cpos.y + root.viewport-y > parent.visible-height - 12px - 20px) { |
97 | // FIXME: font-height hardcoded to 20px |
98 | root.viewport-y = min(0px, max(parent.visible-height - self.height, parent.visible-height - cpos.y - 12px - 20px)); |
99 | } |
100 | } |
101 | } |
102 | } |
103 | |
104 | if (root.has-focus && root.enabled) : Rectangle { |
105 | width: parent.width + 2px; |
106 | height: parent.height + 2px; |
107 | border-radius: parent.border-radius + 2px; |
108 | border-color: CosmicPalette.state-focus; |
109 | border-width: 1px; |
110 | } |
111 | } |
112 | } |
113 | |