| 1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
| 2 | // SPDX-License-Identifier: MIT |
| 3 | |
| 4 | import { Palette } from "std-widgets.slint" ; |
| 5 | import { UsecasesPalette } from "styling.slint" ; |
| 6 | |
| 7 | // copied from common that is not public now |
| 8 | component 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 | |
| 93 | export 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 | |