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