1use alloc::{string::String, vec::Vec};
4
5use azul_core::{
6 callbacks::{CoreCallback, CoreCallbackData, Update},
7 dom::Dom,
8 refany::RefAny,
9 task::OptionTimerId,
10 window::VirtualKeyCode,
11};
12use azul_css::{
13 dynamic_selector::{CssPropertyWithConditions, CssPropertyWithConditionsVec},
14 props::{
15 basic::*,
16 layout::*,
17 property::{CssProperty, *},
18 style::*,
19 },
20 *,
21};
22
23use crate::callbacks::{Callback, CallbackInfo};
24
25const BACKGROUND_COLOR: ColorU = ColorU {
26 r: 255,
27 g: 255,
28 b: 255,
29 a: 255,
30}; const BLACK: ColorU = ColorU {
32 r: 0,
33 g: 0,
34 b: 0,
35 a: 255,
36};
37const TEXT_COLOR: StyleTextColor = StyleTextColor { inner: BLACK }; const COLOR_9B9B9B: ColorU = ColorU {
39 r: 155,
40 g: 155,
41 b: 155,
42 a: 255,
43}; const COLOR_4286F4: ColorU = ColorU {
45 r: 66,
46 g: 134,
47 b: 244,
48 a: 255,
49}; const COLOR_4C4C4C: ColorU = ColorU {
51 r: 76,
52 g: 76,
53 b: 76,
54 a: 255,
55}; const CURSOR_COLOR_BLACK: &[StyleBackgroundContent] = &[StyleBackgroundContent::Color(BLACK)];
58const CURSOR_COLOR: StyleBackgroundContentVec =
59 StyleBackgroundContentVec::from_const_slice(CURSOR_COLOR_BLACK);
60
61const BACKGROUND_THEME_LIGHT: &[StyleBackgroundContent] =
62 &[StyleBackgroundContent::Color(BACKGROUND_COLOR)];
63const BACKGROUND_COLOR_LIGHT: StyleBackgroundContentVec =
64 StyleBackgroundContentVec::from_const_slice(BACKGROUND_THEME_LIGHT);
65
66const SANS_SERIF_STR: &str = "sans-serif";
67const SANS_SERIF: AzString = AzString::from_const_str(SANS_SERIF_STR);
68const SANS_SERIF_FAMILIES: &[StyleFontFamily] = &[StyleFontFamily::System(SANS_SERIF)];
69const SANS_SERIF_FAMILY: StyleFontFamilyVec =
70 StyleFontFamilyVec::from_const_slice(SANS_SERIF_FAMILIES);
71
72const TEXT_CURSOR_TRANSFORM: &[StyleTransform] =
75 &[StyleTransform::Translate(StyleTransformTranslate2D {
76 x: PixelValue::const_px(0),
77 y: PixelValue::const_px(2),
78 })];
79
80static TEXT_CURSOR_PROPS: &[CssPropertyWithConditions] = &[
81 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Absolute)),
82 CssPropertyWithConditions::simple(CssProperty::const_width(LayoutWidth::const_px(1))),
83 CssPropertyWithConditions::simple(CssProperty::const_height(LayoutHeight::const_px(11))),
84 CssPropertyWithConditions::simple(CssProperty::const_background_content(CURSOR_COLOR)),
85 CssPropertyWithConditions::simple(CssProperty::const_opacity(StyleOpacity::const_new(0))),
86 CssPropertyWithConditions::simple(CssProperty::const_transform(
87 StyleTransformVec::from_const_slice(TEXT_CURSOR_TRANSFORM),
88 )),
89];
90
91#[cfg(target_os = "windows")]
94static TEXT_INPUT_CONTAINER_PROPS: &[CssPropertyWithConditions] = &[
95 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Relative)),
96 CssPropertyWithConditions::simple(CssProperty::const_cursor(StyleCursor::Text)),
97 CssPropertyWithConditions::simple(CssProperty::const_box_sizing(LayoutBoxSizing::BorderBox)),
98 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(1))),
99 CssPropertyWithConditions::simple(CssProperty::const_background_content(
100 BACKGROUND_COLOR_LIGHT,
101 )),
102 CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor {
103 inner: COLOR_4C4C4C,
104 })),
105 CssPropertyWithConditions::simple(CssProperty::const_padding_left(
106 LayoutPaddingLeft::const_px(2),
107 )),
108 CssPropertyWithConditions::simple(CssProperty::const_padding_right(
109 LayoutPaddingRight::const_px(2),
110 )),
111 CssPropertyWithConditions::simple(CssProperty::const_padding_top(LayoutPaddingTop::const_px(
112 1,
113 ))),
114 CssPropertyWithConditions::simple(CssProperty::const_padding_bottom(
115 LayoutPaddingBottom::const_px(1),
116 )),
117 CssPropertyWithConditions::simple(CssProperty::const_border_top_width(
119 LayoutBorderTopWidth::const_px(1),
120 )),
121 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_width(
122 LayoutBorderBottomWidth::const_px(1),
123 )),
124 CssPropertyWithConditions::simple(CssProperty::const_border_left_width(
125 LayoutBorderLeftWidth::const_px(1),
126 )),
127 CssPropertyWithConditions::simple(CssProperty::const_border_right_width(
128 LayoutBorderRightWidth::const_px(1),
129 )),
130 CssPropertyWithConditions::simple(CssProperty::const_border_top_style(StyleBorderTopStyle {
131 inner: BorderStyle::Inset,
132 })),
133 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_style(
134 StyleBorderBottomStyle {
135 inner: BorderStyle::Inset,
136 },
137 )),
138 CssPropertyWithConditions::simple(CssProperty::const_border_left_style(StyleBorderLeftStyle {
139 inner: BorderStyle::Inset,
140 })),
141 CssPropertyWithConditions::simple(CssProperty::const_border_right_style(
142 StyleBorderRightStyle {
143 inner: BorderStyle::Inset,
144 },
145 )),
146 CssPropertyWithConditions::simple(CssProperty::const_border_top_color(StyleBorderTopColor {
147 inner: COLOR_9B9B9B,
148 })),
149 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_color(
150 StyleBorderBottomColor {
151 inner: COLOR_9B9B9B,
152 },
153 )),
154 CssPropertyWithConditions::simple(CssProperty::const_border_left_color(StyleBorderLeftColor {
155 inner: COLOR_9B9B9B,
156 })),
157 CssPropertyWithConditions::simple(CssProperty::const_border_right_color(
158 StyleBorderRightColor {
159 inner: COLOR_9B9B9B,
160 },
161 )),
162 CssPropertyWithConditions::simple(CssProperty::const_overflow_x(LayoutOverflow::Hidden)),
163 CssPropertyWithConditions::simple(CssProperty::const_overflow_y(LayoutOverflow::Hidden)),
164 CssPropertyWithConditions::simple(CssProperty::const_justify_content(
165 LayoutJustifyContent::Center,
166 )),
167 CssPropertyWithConditions::on_hover(CssProperty::const_border_top_color(StyleBorderTopColor {
169 inner: COLOR_4C4C4C,
170 })),
171 CssPropertyWithConditions::on_hover(CssProperty::const_border_bottom_color(
172 StyleBorderBottomColor {
173 inner: COLOR_4C4C4C,
174 },
175 )),
176 CssPropertyWithConditions::on_hover(CssProperty::const_border_left_color(
177 StyleBorderLeftColor {
178 inner: COLOR_4C4C4C,
179 },
180 )),
181 CssPropertyWithConditions::on_hover(CssProperty::const_border_right_color(
182 StyleBorderRightColor {
183 inner: COLOR_4C4C4C,
184 },
185 )),
186 CssPropertyWithConditions::on_focus(CssProperty::const_border_top_color(StyleBorderTopColor {
188 inner: COLOR_4286F4,
189 })),
190 CssPropertyWithConditions::on_focus(CssProperty::const_border_bottom_color(
191 StyleBorderBottomColor {
192 inner: COLOR_4286F4,
193 },
194 )),
195 CssPropertyWithConditions::on_focus(CssProperty::const_border_left_color(
196 StyleBorderLeftColor {
197 inner: COLOR_4286F4,
198 },
199 )),
200 CssPropertyWithConditions::on_focus(CssProperty::const_border_right_color(
201 StyleBorderRightColor {
202 inner: COLOR_4286F4,
203 },
204 )),
205];
206
207#[cfg(target_os = "linux")]
208static TEXT_INPUT_CONTAINER_PROPS: &[CssPropertyWithConditions] = &[
209 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Relative)),
210 CssPropertyWithConditions::simple(CssProperty::const_cursor(StyleCursor::Text)),
211 CssPropertyWithConditions::simple(CssProperty::const_box_sizing(LayoutBoxSizing::BorderBox)),
212 CssPropertyWithConditions::simple(CssProperty::const_font_size(StyleFontSize::const_px(11))),
213 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(1))),
214 CssPropertyWithConditions::simple(CssProperty::const_background_content(
215 BACKGROUND_COLOR_LIGHT,
216 )),
217 CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor {
218 inner: COLOR_4C4C4C,
219 })),
220 CssPropertyWithConditions::simple(CssProperty::const_padding_left(
221 LayoutPaddingLeft::const_px(2),
222 )),
223 CssPropertyWithConditions::simple(CssProperty::const_padding_right(
224 LayoutPaddingRight::const_px(2),
225 )),
226 CssPropertyWithConditions::simple(CssProperty::const_padding_top(LayoutPaddingTop::const_px(
227 1,
228 ))),
229 CssPropertyWithConditions::simple(CssProperty::const_padding_bottom(
230 LayoutPaddingBottom::const_px(1),
231 )),
232 CssPropertyWithConditions::simple(CssProperty::const_border_top_width(
234 LayoutBorderTopWidth::const_px(1),
235 )),
236 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_width(
237 LayoutBorderBottomWidth::const_px(1),
238 )),
239 CssPropertyWithConditions::simple(CssProperty::const_border_left_width(
240 LayoutBorderLeftWidth::const_px(1),
241 )),
242 CssPropertyWithConditions::simple(CssProperty::const_border_right_width(
243 LayoutBorderRightWidth::const_px(1),
244 )),
245 CssPropertyWithConditions::simple(CssProperty::const_border_top_style(StyleBorderTopStyle {
246 inner: BorderStyle::Inset,
247 })),
248 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_style(
249 StyleBorderBottomStyle {
250 inner: BorderStyle::Inset,
251 },
252 )),
253 CssPropertyWithConditions::simple(CssProperty::const_border_left_style(StyleBorderLeftStyle {
254 inner: BorderStyle::Inset,
255 })),
256 CssPropertyWithConditions::simple(CssProperty::const_border_right_style(
257 StyleBorderRightStyle {
258 inner: BorderStyle::Inset,
259 },
260 )),
261 CssPropertyWithConditions::simple(CssProperty::const_border_top_color(StyleBorderTopColor {
262 inner: COLOR_9B9B9B,
263 })),
264 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_color(
265 StyleBorderBottomColor {
266 inner: COLOR_9B9B9B,
267 },
268 )),
269 CssPropertyWithConditions::simple(CssProperty::const_border_left_color(StyleBorderLeftColor {
270 inner: COLOR_9B9B9B,
271 })),
272 CssPropertyWithConditions::simple(CssProperty::const_border_right_color(
273 StyleBorderRightColor {
274 inner: COLOR_9B9B9B,
275 },
276 )),
277 CssPropertyWithConditions::simple(CssProperty::const_overflow_x(LayoutOverflow::Hidden)),
278 CssPropertyWithConditions::simple(CssProperty::const_overflow_y(LayoutOverflow::Hidden)),
279 CssPropertyWithConditions::simple(CssProperty::const_text_align(StyleTextAlign::Left)),
280 CssPropertyWithConditions::simple(CssProperty::const_font_size(StyleFontSize::const_px(11))),
281 CssPropertyWithConditions::simple(CssProperty::const_justify_content(
282 LayoutJustifyContent::Center,
283 )),
284 CssPropertyWithConditions::simple(CssProperty::const_font_family(SANS_SERIF_FAMILY)),
285 CssPropertyWithConditions::on_hover(CssProperty::const_border_top_color(StyleBorderTopColor {
287 inner: COLOR_4286F4,
288 })),
289 CssPropertyWithConditions::on_hover(CssProperty::const_border_bottom_color(
290 StyleBorderBottomColor {
291 inner: COLOR_4286F4,
292 },
293 )),
294 CssPropertyWithConditions::on_hover(CssProperty::const_border_left_color(
295 StyleBorderLeftColor {
296 inner: COLOR_4286F4,
297 },
298 )),
299 CssPropertyWithConditions::on_hover(CssProperty::const_border_right_color(
300 StyleBorderRightColor {
301 inner: COLOR_4286F4,
302 },
303 )),
304 CssPropertyWithConditions::on_focus(CssProperty::const_border_top_color(StyleBorderTopColor {
306 inner: COLOR_4286F4,
307 })),
308 CssPropertyWithConditions::on_focus(CssProperty::const_border_bottom_color(
309 StyleBorderBottomColor {
310 inner: COLOR_4286F4,
311 },
312 )),
313 CssPropertyWithConditions::on_focus(CssProperty::const_border_left_color(
314 StyleBorderLeftColor {
315 inner: COLOR_4286F4,
316 },
317 )),
318 CssPropertyWithConditions::on_focus(CssProperty::const_border_right_color(
319 StyleBorderRightColor {
320 inner: COLOR_4286F4,
321 },
322 )),
323];
324
325#[cfg(target_os = "macos")]
326static TEXT_INPUT_CONTAINER_PROPS: &[CssPropertyWithConditions] = &[
327 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Relative)),
328 CssPropertyWithConditions::simple(CssProperty::const_cursor(StyleCursor::Text)),
329 CssPropertyWithConditions::simple(CssProperty::const_box_sizing(LayoutBoxSizing::BorderBox)),
330 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(1))),
331 CssPropertyWithConditions::simple(CssProperty::const_background_content(
332 BACKGROUND_COLOR_LIGHT,
333 )),
334 CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor {
335 inner: COLOR_4C4C4C,
336 })),
337 CssPropertyWithConditions::simple(CssProperty::const_padding_left(
338 LayoutPaddingLeft::const_px(2),
339 )),
340 CssPropertyWithConditions::simple(CssProperty::const_padding_right(
341 LayoutPaddingRight::const_px(2),
342 )),
343 CssPropertyWithConditions::simple(CssProperty::const_padding_top(LayoutPaddingTop::const_px(
344 1,
345 ))),
346 CssPropertyWithConditions::simple(CssProperty::const_padding_bottom(
347 LayoutPaddingBottom::const_px(1),
348 )),
349 CssPropertyWithConditions::simple(CssProperty::const_border_top_width(
351 LayoutBorderTopWidth::const_px(1),
352 )),
353 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_width(
354 LayoutBorderBottomWidth::const_px(1),
355 )),
356 CssPropertyWithConditions::simple(CssProperty::const_border_left_width(
357 LayoutBorderLeftWidth::const_px(1),
358 )),
359 CssPropertyWithConditions::simple(CssProperty::const_border_right_width(
360 LayoutBorderRightWidth::const_px(1),
361 )),
362 CssPropertyWithConditions::simple(CssProperty::const_border_top_style(StyleBorderTopStyle {
363 inner: BorderStyle::Inset,
364 })),
365 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_style(
366 StyleBorderBottomStyle {
367 inner: BorderStyle::Inset,
368 },
369 )),
370 CssPropertyWithConditions::simple(CssProperty::const_border_left_style(StyleBorderLeftStyle {
371 inner: BorderStyle::Inset,
372 })),
373 CssPropertyWithConditions::simple(CssProperty::const_border_right_style(
374 StyleBorderRightStyle {
375 inner: BorderStyle::Inset,
376 },
377 )),
378 CssPropertyWithConditions::simple(CssProperty::const_border_top_color(StyleBorderTopColor {
379 inner: COLOR_9B9B9B,
380 })),
381 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_color(
382 StyleBorderBottomColor {
383 inner: COLOR_9B9B9B,
384 },
385 )),
386 CssPropertyWithConditions::simple(CssProperty::const_border_left_color(StyleBorderLeftColor {
387 inner: COLOR_9B9B9B,
388 })),
389 CssPropertyWithConditions::simple(CssProperty::const_border_right_color(
390 StyleBorderRightColor {
391 inner: COLOR_9B9B9B,
392 },
393 )),
394 CssPropertyWithConditions::simple(CssProperty::const_overflow_x(LayoutOverflow::Hidden)),
395 CssPropertyWithConditions::simple(CssProperty::const_overflow_y(LayoutOverflow::Hidden)),
396 CssPropertyWithConditions::simple(CssProperty::const_text_align(StyleTextAlign::Left)),
397 CssPropertyWithConditions::simple(CssProperty::const_justify_content(
398 LayoutJustifyContent::Center,
399 )),
400 CssPropertyWithConditions::on_hover(CssProperty::const_border_top_color(StyleBorderTopColor {
402 inner: COLOR_4286F4,
403 })),
404 CssPropertyWithConditions::on_hover(CssProperty::const_border_bottom_color(
405 StyleBorderBottomColor {
406 inner: COLOR_4286F4,
407 },
408 )),
409 CssPropertyWithConditions::on_hover(CssProperty::const_border_left_color(
410 StyleBorderLeftColor {
411 inner: COLOR_4286F4,
412 },
413 )),
414 CssPropertyWithConditions::on_hover(CssProperty::const_border_right_color(
415 StyleBorderRightColor {
416 inner: COLOR_4286F4,
417 },
418 )),
419 CssPropertyWithConditions::on_focus(CssProperty::const_border_top_color(StyleBorderTopColor {
421 inner: COLOR_4286F4,
422 })),
423 CssPropertyWithConditions::on_focus(CssProperty::const_border_bottom_color(
424 StyleBorderBottomColor {
425 inner: COLOR_4286F4,
426 },
427 )),
428 CssPropertyWithConditions::on_focus(CssProperty::const_border_left_color(
429 StyleBorderLeftColor {
430 inner: COLOR_4286F4,
431 },
432 )),
433 CssPropertyWithConditions::on_focus(CssProperty::const_border_right_color(
434 StyleBorderRightColor {
435 inner: COLOR_4286F4,
436 },
437 )),
438];
439
440#[cfg(target_os = "windows")]
443static TEXT_INPUT_LABEL_PROPS: &[CssPropertyWithConditions] = &[
444 CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::InlineBlock)),
445 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
446 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Relative)),
447 CssPropertyWithConditions::simple(CssProperty::const_font_size(StyleFontSize::const_px(11))),
448 CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor {
449 inner: COLOR_4C4C4C,
450 })),
451 CssPropertyWithConditions::simple(CssProperty::const_font_family(SANS_SERIF_FAMILY)),
452];
453
454#[cfg(target_os = "linux")]
455static TEXT_INPUT_LABEL_PROPS: &[CssPropertyWithConditions] = &[
456 CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::InlineBlock)),
457 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
458 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Relative)),
459 CssPropertyWithConditions::simple(CssProperty::const_font_size(StyleFontSize::const_px(11))),
460 CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor {
461 inner: COLOR_4C4C4C,
462 })),
463 CssPropertyWithConditions::simple(CssProperty::const_font_family(SANS_SERIF_FAMILY)),
464];
465
466#[cfg(target_os = "macos")]
467static TEXT_INPUT_LABEL_PROPS: &[CssPropertyWithConditions] = &[
468 CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::InlineBlock)),
469 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
470 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Relative)),
471 CssPropertyWithConditions::simple(CssProperty::const_font_size(StyleFontSize::const_px(11))),
472 CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor {
473 inner: COLOR_4C4C4C,
474 })),
475 CssPropertyWithConditions::simple(CssProperty::const_font_family(SANS_SERIF_FAMILY)),
476];
477
478#[cfg(target_os = "windows")]
481static TEXT_INPUT_PLACEHOLDER_PROPS: &[CssPropertyWithConditions] = &[
482 CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::Block)),
483 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
484 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Absolute)),
485 CssPropertyWithConditions::simple(CssProperty::const_top(LayoutTop::const_px(2))),
486 CssPropertyWithConditions::simple(CssProperty::const_left(LayoutLeft::const_px(2))),
487 CssPropertyWithConditions::simple(CssProperty::const_font_size(StyleFontSize::const_px(11))),
488 CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor {
489 inner: COLOR_4C4C4C,
490 })),
491 CssPropertyWithConditions::simple(CssProperty::const_font_family(SANS_SERIF_FAMILY)),
492 CssPropertyWithConditions::simple(CssProperty::const_opacity(StyleOpacity::const_new(100))),
493];
494
495#[cfg(target_os = "linux")]
496static TEXT_INPUT_PLACEHOLDER_PROPS: &[CssPropertyWithConditions] = &[
497 CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::Block)),
498 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
499 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Absolute)),
500 CssPropertyWithConditions::simple(CssProperty::const_top(LayoutTop::const_px(2))),
501 CssPropertyWithConditions::simple(CssProperty::const_left(LayoutLeft::const_px(2))),
502 CssPropertyWithConditions::simple(CssProperty::const_font_size(StyleFontSize::const_px(11))),
503 CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor {
504 inner: COLOR_4C4C4C,
505 })),
506 CssPropertyWithConditions::simple(CssProperty::const_font_family(SANS_SERIF_FAMILY)),
507 CssPropertyWithConditions::simple(CssProperty::const_opacity(StyleOpacity::const_new(100))),
508];
509
510#[cfg(target_os = "macos")]
511static TEXT_INPUT_PLACEHOLDER_PROPS: &[CssPropertyWithConditions] = &[
512 CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::Block)),
513 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
514 CssPropertyWithConditions::simple(CssProperty::const_position(LayoutPosition::Absolute)),
515 CssPropertyWithConditions::simple(CssProperty::const_top(LayoutTop::const_px(2))),
516 CssPropertyWithConditions::simple(CssProperty::const_left(LayoutLeft::const_px(2))),
517 CssPropertyWithConditions::simple(CssProperty::const_font_size(StyleFontSize::const_px(11))),
518 CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor {
519 inner: COLOR_4C4C4C,
520 })),
521 CssPropertyWithConditions::simple(CssProperty::const_font_family(SANS_SERIF_FAMILY)),
522 CssPropertyWithConditions::simple(CssProperty::const_opacity(StyleOpacity::const_new(100))),
523];
524
525#[derive(Debug, Clone, PartialEq)]
526#[repr(C)]
527pub struct TextInput {
528 pub text_input_state: TextInputStateWrapper,
529 pub placeholder_style: CssPropertyWithConditionsVec,
530 pub container_style: CssPropertyWithConditionsVec,
531 pub label_style: CssPropertyWithConditionsVec,
532}
533
534#[derive(Debug, Clone, PartialEq)]
535#[repr(C)]
536pub struct TextInputState {
537 pub text: U32Vec, pub placeholder: OptionString,
539 pub max_len: usize,
540 pub selection: OptionTextInputSelection,
541 pub cursor_pos: usize,
542}
543
544#[derive(Debug, Clone, PartialEq)]
545#[repr(C)]
546pub struct TextInputStateWrapper {
547 pub inner: TextInputState,
548 pub on_text_input: OptionTextInputOnTextInput,
549 pub on_virtual_key_down: OptionTextInputOnVirtualKeyDown,
550 pub on_focus_lost: OptionTextInputOnFocusLost,
551 pub update_text_input_before_calling_focus_lost_fn: bool,
552 pub update_text_input_before_calling_vk_down_fn: bool,
553 pub cursor_animation: OptionTimerId,
554}
555
556#[derive(Debug, Copy, Clone, PartialEq)]
557#[repr(C)]
558pub struct OnTextInputReturn {
559 pub update: Update,
560 pub valid: TextInputValid,
561}
562
563#[derive(Debug, Copy, Clone, PartialEq)]
564#[repr(C)]
565pub enum TextInputValid {
566 Yes,
567 No,
568}
569
570pub type TextInputOnTextInputCallbackType =
573 extern "C" fn(RefAny, CallbackInfo, TextInputState) -> OnTextInputReturn;
574impl_widget_callback!(
575 TextInputOnTextInput,
576 OptionTextInputOnTextInput,
577 TextInputOnTextInputCallback,
578 TextInputOnTextInputCallbackType
579);
580
581pub type TextInputOnVirtualKeyDownCallbackType =
582 extern "C" fn(RefAny, CallbackInfo, TextInputState) -> OnTextInputReturn;
583impl_widget_callback!(
584 TextInputOnVirtualKeyDown,
585 OptionTextInputOnVirtualKeyDown,
586 TextInputOnVirtualKeyDownCallback,
587 TextInputOnVirtualKeyDownCallbackType
588);
589
590pub type TextInputOnFocusLostCallbackType =
591 extern "C" fn(RefAny, CallbackInfo, TextInputState) -> Update;
592impl_widget_callback!(
593 TextInputOnFocusLost,
594 OptionTextInputOnFocusLost,
595 TextInputOnFocusLostCallback,
596 TextInputOnFocusLostCallbackType
597);
598
599#[derive(Debug, Clone, Hash, PartialEq, Eq)]
600#[repr(C, u8)]
601pub enum TextInputSelection {
602 All,
603 FromTo(TextInputSelectionRange),
604}
605
606azul_css::impl_option!(
607 TextInputSelection,
608 OptionTextInputSelection,
609 copy = false,
610 [Debug, Clone, Hash, PartialEq, Eq]
611);
612
613#[derive(Debug, Clone, Hash, PartialEq, Eq)]
614#[repr(C)]
615pub struct TextInputSelectionRange {
616 pub dir_from: usize,
617 pub dir_to: usize,
618}
619
620impl Default for TextInput {
621 fn default() -> Self {
622 TextInput {
623 text_input_state: TextInputStateWrapper::default(),
624 placeholder_style: CssPropertyWithConditionsVec::from_const_slice(
625 TEXT_INPUT_PLACEHOLDER_PROPS,
626 ),
627 container_style: CssPropertyWithConditionsVec::from_const_slice(
628 TEXT_INPUT_CONTAINER_PROPS,
629 ),
630 label_style: CssPropertyWithConditionsVec::from_const_slice(TEXT_INPUT_LABEL_PROPS),
631 }
632 }
633}
634
635impl Default for TextInputState {
636 fn default() -> Self {
637 TextInputState {
638 text: Vec::new().into(),
639 placeholder: None.into(),
640 max_len: 50,
641 selection: None.into(),
642 cursor_pos: 0,
643 }
644 }
645}
646
647impl TextInputState {
648 pub fn get_text(&self) -> String {
649 self.text
650 .iter()
651 .filter_map(|c| core::char::from_u32(*c))
652 .collect()
653 }
654}
655
656impl Default for TextInputStateWrapper {
657 fn default() -> Self {
658 TextInputStateWrapper {
659 inner: TextInputState::default(),
660 on_text_input: None.into(),
661 on_virtual_key_down: None.into(),
662 on_focus_lost: None.into(),
663 update_text_input_before_calling_focus_lost_fn: true,
664 update_text_input_before_calling_vk_down_fn: true,
665 cursor_animation: None.into(),
666 }
667 }
668}
669
670impl TextInput {
671 pub fn create() -> Self {
672 Self::default()
673 }
674
675 pub fn with_text(mut self, text: AzString) -> Self {
676 self.set_text(text);
677 self
678 }
679
680 pub fn set_text(&mut self, text: AzString) {
681 self.text_input_state.inner.text = text
682 .as_str()
683 .chars()
684 .map(|c| c as u32)
685 .collect::<Vec<_>>()
686 .into();
687 }
688
689 pub fn set_placeholder(&mut self, placeholder: AzString) {
690 self.text_input_state.inner.placeholder = Some(placeholder).into();
691 }
692
693 pub fn with_placeholder(mut self, placeholder: AzString) -> Self {
694 self.set_placeholder(placeholder);
695 self
696 }
697
698 pub fn set_on_text_input<C: Into<TextInputOnTextInputCallback>>(
699 &mut self,
700 refany: RefAny,
701 callback: C,
702 ) {
703 self.text_input_state.on_text_input = Some(TextInputOnTextInput {
704 callback: callback.into(),
705 refany,
706 })
707 .into();
708 }
709
710 pub fn with_on_text_input<C: Into<TextInputOnTextInputCallback>>(
711 mut self,
712 refany: RefAny,
713 callback: C,
714 ) -> Self {
715 self.set_on_text_input(refany, callback);
716 self
717 }
718
719 pub fn set_on_virtual_key_down<C: Into<TextInputOnVirtualKeyDownCallback>>(
720 &mut self,
721 refany: RefAny,
722 callback: C,
723 ) {
724 self.text_input_state.on_virtual_key_down = Some(TextInputOnVirtualKeyDown {
725 callback: callback.into(),
726 refany,
727 })
728 .into();
729 }
730
731 pub fn with_on_virtual_key_down<C: Into<TextInputOnVirtualKeyDownCallback>>(
732 mut self,
733 refany: RefAny,
734 callback: C,
735 ) -> Self {
736 self.set_on_virtual_key_down(refany, callback);
737 self
738 }
739
740 pub fn set_on_focus_lost<C: Into<TextInputOnFocusLostCallback>>(
741 &mut self,
742 refany: RefAny,
743 callback: C,
744 ) {
745 self.text_input_state.on_focus_lost = Some(TextInputOnFocusLost {
746 callback: callback.into(),
747 refany,
748 })
749 .into();
750 }
751
752 pub fn with_on_focus_lost<C: Into<TextInputOnFocusLostCallback>>(
753 mut self,
754 refany: RefAny,
755 callback: C,
756 ) -> Self {
757 self.set_on_focus_lost(refany, callback);
758 self
759 }
760
761 pub fn set_placeholder_style(&mut self, style: CssPropertyWithConditionsVec) {
762 self.placeholder_style = style;
763 }
764
765 pub fn with_placeholder_style(mut self, style: CssPropertyWithConditionsVec) -> Self {
766 self.set_placeholder_style(style);
767 self
768 }
769
770 pub fn set_container_style(&mut self, style: CssPropertyWithConditionsVec) {
771 self.container_style = style;
772 }
773
774 pub fn with_container_style(mut self, style: CssPropertyWithConditionsVec) -> Self {
775 self.set_container_style(style);
776 self
777 }
778
779 pub fn set_label_style(&mut self, style: CssPropertyWithConditionsVec) {
780 self.label_style = style;
781 }
782
783 pub fn with_label_style(mut self, style: CssPropertyWithConditionsVec) -> Self {
784 self.set_label_style(style);
785 self
786 }
787
788 pub fn swap_with_default(&mut self) -> Self {
789 let mut s = Self::default();
790 core::mem::swap(&mut s, self);
791 s
792 }
793
794 pub fn dom(mut self) -> Dom {
795 use azul_core::{
796 callbacks::CoreCallbackData,
797 dom::{EventFilter, FocusEventFilter, HoverEventFilter, IdOrClass::Class, TabIndex},
798 };
799
800 self.text_input_state.inner.cursor_pos = self.text_input_state.inner.text.len();
801
802 let label_text: String = self
803 .text_input_state
804 .inner
805 .text
806 .iter()
807 .filter_map(|s| core::char::from_u32(*s))
808 .collect();
809
810 let placeholder = self
811 .text_input_state
812 .inner
813 .placeholder
814 .as_ref()
815 .map(|s| s.as_str().to_string())
816 .unwrap_or_default();
817
818 let state_ref = RefAny::new(self.text_input_state);
819
820 Dom::create_div()
821 .with_ids_and_classes(vec![Class("__azul-native-text-input-container".into())].into())
822 .with_css_props(self.container_style)
823 .with_tab_index(TabIndex::Auto)
824 .with_dataset(Some(state_ref.clone()).into())
825 .with_callbacks(
826 vec![
827 CoreCallbackData {
828 event: EventFilter::Focus(FocusEventFilter::FocusReceived),
829 refany: state_ref.clone(),
830 callback: CoreCallback {
831 cb: default_on_focus_received as usize,
832 ctx: azul_core::refany::OptionRefAny::None,
833 },
834 },
835 CoreCallbackData {
836 event: EventFilter::Focus(FocusEventFilter::FocusLost),
837 refany: state_ref.clone(),
838 callback: CoreCallback {
839 cb: default_on_focus_lost as usize,
840 ctx: azul_core::refany::OptionRefAny::None,
841 },
842 },
843 CoreCallbackData {
844 event: EventFilter::Focus(FocusEventFilter::TextInput),
845 refany: state_ref.clone(),
846 callback: CoreCallback {
847 cb: default_on_text_input as usize,
848 ctx: azul_core::refany::OptionRefAny::None,
849 },
850 },
851 CoreCallbackData {
852 event: EventFilter::Focus(FocusEventFilter::VirtualKeyDown),
853 refany: state_ref.clone(),
854 callback: CoreCallback {
855 cb: default_on_virtual_key_down as usize,
856 ctx: azul_core::refany::OptionRefAny::None,
857 },
858 },
859 CoreCallbackData {
860 event: EventFilter::Hover(HoverEventFilter::MouseOver),
861 refany: state_ref.clone(),
862 callback: CoreCallback {
863 cb: default_on_mouse_hover as usize,
864 ctx: azul_core::refany::OptionRefAny::None,
865 },
866 },
867 ]
868 .into(),
869 )
870 .with_children(
871 vec![
872 Dom::create_text(placeholder)
873 .with_ids_and_classes(
874 vec![Class("__azul-native-text-input-placeholder".into())].into(),
875 )
876 .with_css_props(self.placeholder_style),
877 Dom::create_text(label_text)
878 .with_ids_and_classes(
879 vec![Class("__azul-native-text-input-label".into())].into(),
880 )
881 .with_css_props(self.label_style)
882 .with_children(
883 vec![Dom::create_div()
884 .with_ids_and_classes(
885 vec![Class("__azul-native-text-input-cursor".into())].into(),
886 )
887 .with_css_props(CssPropertyWithConditionsVec::from_const_slice(
888 TEXT_CURSOR_PROPS,
889 ))]
890 .into(),
891 ),
892 ]
893 .into(),
894 )
895 }
896}
897
898extern "C" fn default_on_focus_received(mut text_input: RefAny, mut info: CallbackInfo) -> Update {
899 let mut text_input = match text_input.downcast_mut::<TextInputStateWrapper>() {
900 Some(s) => s,
901 None => return Update::DoNothing,
902 };
903
904 let text_input = &mut *text_input;
905
906 let placeholder_text_node_id = match info.get_first_child(info.get_hit_node()) {
907 Some(s) => s,
908 None => return Update::DoNothing,
909 };
910
911 if text_input.inner.text.is_empty() {
913 info.set_css_property(
914 placeholder_text_node_id,
915 CssProperty::const_opacity(StyleOpacity::const_new(0)),
916 );
917 }
918
919 text_input.inner.cursor_pos = text_input.inner.text.len();
920
921 Update::DoNothing
922}
923
924extern "C" fn default_on_focus_lost(mut text_input: RefAny, mut info: CallbackInfo) -> Update {
925 let mut text_input = match text_input.downcast_mut::<TextInputStateWrapper>() {
926 Some(s) => s,
927 None => return Update::DoNothing,
928 };
929
930 let text_input = &mut *text_input;
931
932 let placeholder_text_node_id = match info.get_first_child(info.get_hit_node()) {
933 Some(s) => s,
934 None => return Update::DoNothing,
935 };
936
937 if text_input.inner.text.is_empty() {
939 info.set_css_property(
940 placeholder_text_node_id,
941 CssProperty::const_opacity(StyleOpacity::const_new(100)),
942 );
943 }
944
945 let result = {
946 let text_input = &mut *text_input;
948 let onfocuslost = &mut text_input.on_focus_lost;
949 let inner = text_input.inner.clone();
950
951 match onfocuslost.as_mut() {
952 Some(TextInputOnFocusLost { callback, refany }) => {
953 (callback.cb)(refany.clone(), info.clone(), inner)
954 }
955 None => Update::DoNothing,
956 }
957 };
958
959 result
960}
961
962extern "C" fn default_on_text_input(text_input: RefAny, info: CallbackInfo) -> Update {
963 default_on_text_input_inner(text_input, info).unwrap_or(Update::DoNothing)
964}
965
966fn default_on_text_input_inner(mut text_input: RefAny, mut info: CallbackInfo) -> Option<Update> {
967 let mut text_input = text_input.downcast_mut::<TextInputStateWrapper>()?;
968
969 let changeset = info.get_text_changeset()?;
971 let inserted_text = changeset.inserted_text.as_str().to_string();
972
973 if inserted_text.is_empty() {
975 return None;
976 }
977
978 let placeholder_node_id = info.get_first_child(info.get_hit_node())?;
979 let label_node_id = info.get_next_sibling(placeholder_node_id)?;
980 let _cursor_node_id = info.get_first_child(label_node_id)?;
981
982 let result = {
983 let text_input = &mut *text_input;
985 let ontextinput = &mut text_input.on_text_input;
986
987 let mut inner_clone = text_input.inner.clone();
989 inner_clone.cursor_pos = inner_clone.cursor_pos.saturating_add(inserted_text.len());
990 inner_clone.text = {
991 let mut internal = inner_clone.text.clone().into_library_owned_vec();
992 internal.extend(inserted_text.chars().map(|c| c as u32));
993 internal.into()
994 };
995
996 match ontextinput.as_mut() {
997 Some(TextInputOnTextInput { callback, refany }) => {
998 (callback.cb)(refany.clone(), info.clone(), inner_clone)
999 }
1000 None => OnTextInputReturn {
1001 update: Update::DoNothing,
1002 valid: TextInputValid::Yes,
1003 },
1004 }
1005 };
1006
1007 if result.valid == TextInputValid::Yes {
1008 info.set_css_property(
1010 placeholder_node_id,
1011 CssProperty::const_opacity(StyleOpacity::const_new(0)),
1012 );
1013
1014 text_input.inner.text = {
1016 let mut internal = text_input.inner.text.clone().into_library_owned_vec();
1017 internal.extend(inserted_text.chars().map(|c| c as u32));
1018 internal.into()
1019 };
1020 text_input.inner.cursor_pos = text_input
1021 .inner
1022 .cursor_pos
1023 .saturating_add(inserted_text.len());
1024
1025 info.change_node_text(label_node_id, text_input.inner.get_text().into());
1026 }
1027
1028 Some(result.update)
1029}
1030
1031extern "C" fn default_on_virtual_key_down(text_input: RefAny, info: CallbackInfo) -> Update {
1032 default_on_virtual_key_down_inner(text_input, info).unwrap_or(Update::DoNothing)
1033}
1034
1035fn default_on_virtual_key_down_inner(
1036 mut text_input: RefAny,
1037 mut info: CallbackInfo,
1038) -> Option<Update> {
1039 let mut text_input = text_input.downcast_mut::<TextInputStateWrapper>()?;
1040 let keyboard_state = info.get_current_keyboard_state();
1041
1042 let c = keyboard_state.current_virtual_keycode.into_option()?;
1043 let placeholder_node_id = info.get_first_child(info.get_hit_node())?;
1044 let label_node_id = info.get_next_sibling(placeholder_node_id)?;
1045 let _cursor_node_id = info.get_first_child(label_node_id)?;
1046
1047 if c != VirtualKeyCode::Back {
1048 return None;
1049 }
1050
1051 text_input.inner.text = {
1052 let mut internal = text_input.inner.text.clone().into_library_owned_vec();
1053 internal.pop();
1054 internal.into()
1055 };
1056 text_input.inner.cursor_pos = text_input.inner.cursor_pos.saturating_sub(1);
1057
1058 info.change_node_text(label_node_id, text_input.inner.get_text().into());
1059
1060 None
1061}
1062
1063extern "C" fn default_on_mouse_hover(mut text_input: RefAny, _info: CallbackInfo) -> Update {
1064 let _text_input = match text_input.downcast_mut::<TextInputStateWrapper>() {
1065 Some(s) => s,
1066 None => return Update::DoNothing,
1067 };
1068
1069 Update::DoNothing
1072}