1use crate::bindings;
20use crate::error::{Error, Result};
21
22pub const ALIGN_DEFAULT: u8 = 0;
38pub const ALIGN_TOP_LEFT: u8 = 1;
40pub const ALIGN_TOP_MID: u8 = 2;
42pub const ALIGN_TOP_RIGHT: u8 = 3;
44pub const ALIGN_BOTTOM_LEFT: u8 = 4;
46pub const ALIGN_BOTTOM_MID: u8 = 5;
48pub const ALIGN_BOTTOM_RIGHT: u8 = 6;
50pub const ALIGN_LEFT_MID: u8 = 7;
52pub const ALIGN_RIGHT_MID: u8 = 8;
54pub const ALIGN_CENTER: u8 = 9;
56
57pub const PART_MAIN: u32 = 0x00_0000;
59pub const PART_INDICATOR: u32 = 0x02_0000;
61pub const PART_KNOB: u32 = 0x03_0000;
63pub const PART_ITEMS: u32 = 0x05_0000;
65
66pub const SIZE_CONTENT: i32 = 0x3FFF_FFFF;
70
71pub const STATE_CHECKED: u32 = 0x0001;
73
74pub const GRID_TEMPLATE_LAST: i32 = 0x1FFF_FFFF;
77pub const GRID_CONTENT: i32 = 0x1FFF_FF9A;
80
81pub const fn grid_fr(x: i32) -> i32 {
84 0x1FFF_FF9B + x
85}
86
87pub const GRID_ALIGN_START: u32 = 0;
89pub const GRID_ALIGN_CENTER: u32 = 1;
91pub const GRID_ALIGN_END: u32 = 2;
93pub const GRID_ALIGN_STRETCH: u32 = 3;
95
96#[repr(u32)]
98#[derive(Clone, Copy)]
99pub enum FlexFlow {
100 Row = 0x00,
101 Column = 0x01,
102 RowWrap = 0x04,
103 RowReverse = 0x02,
104 RowWrapReverse = 0x06,
105 ColumnWrap = 0x05,
106 ColumnReverse = 0x03,
107 ColumnWrapReverse = 0x07,
108}
109
110#[repr(u32)]
112#[derive(Clone, Copy)]
113pub enum FlexAlign {
114 Start = 0,
115 End = 1,
116 Center = 2,
117 SpaceEvenly = 3,
118 SpaceAround = 4,
119 SpaceBetween = 5,
120}
121
122#[repr(u32)]
124#[derive(Clone, Copy)]
125pub enum LayoutKind {
126 None = 0,
127 Flex = 1,
128 Grid = 2,
129}
130
131#[repr(u32)]
133#[derive(Clone, Copy)]
134pub enum Palette {
135 Red = 0,
136 Pink = 1,
137 Purple = 2,
138 DeepPurple = 3,
139 Indigo = 4,
140 Blue = 5,
141 LightBlue = 6,
142 Cyan = 7,
143 Teal = 8,
144 Green = 9,
145 LightGreen = 10,
146 Lime = 11,
147 Yellow = 12,
148 Amber = 13,
149 Orange = 14,
150 DeepOrange = 15,
151 Brown = 16,
152 BlueGrey = 17,
153 Grey = 18,
154 None = 0xFF,
155}
156
157pub const TEXT_ALIGN_AUTO: u32 = 0;
159pub const TEXT_ALIGN_LEFT: u32 = 1;
160pub const TEXT_ALIGN_CENTER: u32 = 2;
161pub const TEXT_ALIGN_RIGHT: u32 = 3;
162
163#[repr(C)]
169#[derive(Clone, Copy)]
170pub struct Color {
171 pub blue: u8,
172 pub green: u8,
173 pub red: u8,
174}
175
176impl Color {
177 pub const fn make(r: u8, g: u8, b: u8) -> Self {
179 Self {
180 blue: b,
181 green: g,
182 red: r,
183 }
184 }
185
186 pub const fn white() -> Self {
188 Self::make(255, 255, 255)
189 }
190
191 pub const fn black() -> Self {
193 Self::make(0, 0, 0)
194 }
195
196 pub fn hex(hex: u32) -> Self {
198 Self::make(
199 ((hex >> 16) & 0xFF) as u8,
200 ((hex >> 8) & 0xFF) as u8,
201 (hex & 0xFF) as u8,
202 )
203 }
204
205 pub fn palette_main(p: u32) -> Self {
209 unsafe {
211 let c = bindings::lv_palette_main(p as _);
212 core::mem::transmute(c)
213 }
214 }
215
216 pub fn palette_lighten(p: Palette, level: u8) -> Self {
218 unsafe {
220 let c = bindings::lv_palette_lighten(p as _, level);
221 core::mem::transmute(c)
222 }
223 }
224
225 pub fn palette_darken(p: Palette, level: u8) -> Self {
227 unsafe {
229 let c = bindings::lv_palette_darken(p as _, level);
230 core::mem::transmute(c)
231 }
232 }
233
234 pub fn hex3(hex: u32) -> Self {
236 unsafe {
238 let c = bindings::lv_color_hex3(hex);
239 core::mem::transmute(c)
240 }
241 }
242
243 pub(crate) fn to_raw(self) -> bindings::lv_color_t {
244 unsafe { core::mem::transmute(self) }
246 }
247}
248
249pub const PALETTE_BLUE: u32 = 6;
251
252pub fn font_montserrat_14() -> *const bindings::lv_font_t {
258 unsafe { &bindings::lv_font_montserrat_14 }
259}
260
261pub fn font_montserrat_24() -> *const bindings::lv_font_t {
263 unsafe { &bindings::lv_font_montserrat_24 }
264}
265
266pub fn font_montserrat_32() -> *const bindings::lv_font_t {
268 unsafe { &bindings::lv_font_montserrat_32 }
269}
270
271pub trait Widget: Copy {
283 fn raw(self) -> *mut bindings::lv_obj_t;
288}
289
290pub trait Layout: Widget + Sized {
297 fn size(self, w: i32, h: i32) -> Self {
299 unsafe { bindings::lv_obj_set_size(self.raw(), w, h) };
300 self
301 }
302
303 fn width(self, w: i32) -> Self {
305 unsafe { bindings::lv_obj_set_width(self.raw(), w) };
306 self
307 }
308
309 fn height(self, h: i32) -> Self {
311 unsafe { bindings::lv_obj_set_height(self.raw(), h) };
312 self
313 }
314
315 fn pos(self, x: i32, y: i32) -> Self {
317 unsafe { bindings::lv_obj_set_pos(self.raw(), x, y) };
318 self
319 }
320
321 fn center(self) -> Self {
323 unsafe { bindings::lv_obj_center(self.raw()) };
324 self
325 }
326
327 fn align(self, a: u8, x_ofs: i32, y_ofs: i32) -> Self {
331 unsafe { bindings::lv_obj_align(self.raw(), a as _, x_ofs, y_ofs) };
332 self
333 }
334
335 fn hide(self) -> Self {
337 unsafe { bindings::lv_obj_add_flag(self.raw(), bindings::LV_OBJ_FLAG_HIDDEN) };
338 self
339 }
340
341 fn show(self) -> Self {
343 unsafe { bindings::lv_obj_remove_flag(self.raw(), bindings::LV_OBJ_FLAG_HIDDEN) };
344 self
345 }
346
347 fn visible(self, v: bool) -> Self {
349 if v { self.show() } else { self.hide() }
350 }
351
352 fn add_flag(self, f: u32) -> Self {
354 unsafe { bindings::lv_obj_add_flag(self.raw(), f) };
355 self
356 }
357
358 fn remove_flag(self, f: u32) -> Self {
360 unsafe { bindings::lv_obj_remove_flag(self.raw(), f) };
361 self
362 }
363
364 fn add_state(self, s: u32) -> Self {
366 unsafe { bindings::lv_obj_add_state(self.raw(), s as _) };
367 self
368 }
369
370 fn remove_state(self, s: u32) -> Self {
372 unsafe { bindings::lv_obj_remove_state(self.raw(), s as _) };
373 self
374 }
375
376 fn clickable(self, on: bool) -> Self {
378 if on {
379 self.add_flag(bindings::LV_OBJ_FLAG_CLICKABLE)
380 } else {
381 self.remove_flag(bindings::LV_OBJ_FLAG_CLICKABLE)
382 }
383 }
384
385 fn grid_dsc(self, cols: &'static [i32], rows: &'static [i32]) -> Self {
396 unsafe { bindings::lv_obj_set_grid_dsc_array(self.raw(), cols.as_ptr(), rows.as_ptr()) };
397 self
398 }
399
400 #[allow(clippy::too_many_arguments)]
402 fn grid_cell(
403 self,
404 col_align: u32,
405 col_pos: i32,
406 col_span: i32,
407 row_align: u32,
408 row_pos: i32,
409 row_span: i32,
410 ) -> Self {
411 unsafe {
412 bindings::lv_obj_set_grid_cell(
413 self.raw(),
414 col_align as _,
415 col_pos,
416 col_span,
417 row_align as _,
418 row_pos,
419 row_span,
420 );
421 }
422 self
423 }
424
425 fn flex_flow(self, flow: FlexFlow) -> Self {
427 unsafe { bindings::lv_obj_set_flex_flow(self.raw(), flow as _) };
428 self
429 }
430
431 fn flex_align(self, main: FlexAlign, cross: FlexAlign, track: FlexAlign) -> Self {
434 unsafe { bindings::lv_obj_set_flex_align(self.raw(), main as _, cross as _, track as _) };
435 self
436 }
437
438 fn flex_grow(self, grow: u8) -> Self {
440 unsafe { bindings::lv_obj_set_flex_grow(self.raw(), grow) };
441 self
442 }
443
444 fn layout(self, kind: LayoutKind) -> Self {
446 unsafe { bindings::lv_obj_set_layout(self.raw(), kind as _) };
447 self
448 }
449
450 fn scroll_to_y(self, y: i32, anim: bool) -> Self {
452 unsafe {
453 bindings::lv_obj_scroll_to_y(self.raw(), y, anim);
454 }
455 self
456 }
457
458 fn update_layout(self) -> Self {
460 unsafe { bindings::lv_obj_update_layout(self.raw()) };
461 self
462 }
463
464 fn content_width(self) -> i32 {
466 unsafe { bindings::lv_obj_get_content_width(self.raw()) }
467 }
468
469 fn scroll_bottom(self) -> i32 {
471 unsafe { bindings::lv_obj_get_scroll_bottom(self.raw()) }
472 }
473}
474
475impl<T: Widget> Layout for T {}
476
477pub trait Styleable: Widget + Sized {
484 fn bg_color(self, c: Color) -> Self {
486 unsafe { bindings::lv_obj_set_style_bg_color(self.raw(), c.to_raw(), PART_MAIN) };
487 self
488 }
489
490 fn bg_opa(self, opa: u8) -> Self {
492 unsafe { bindings::lv_obj_set_style_bg_opa(self.raw(), opa, PART_MAIN) };
493 self
494 }
495
496 fn border_color(self, c: Color) -> Self {
498 unsafe { bindings::lv_obj_set_style_border_color(self.raw(), c.to_raw(), PART_MAIN) };
499 self
500 }
501
502 fn border_width(self, w: i32) -> Self {
504 unsafe { bindings::lv_obj_set_style_border_width(self.raw(), w, PART_MAIN) };
505 self
506 }
507
508 fn radius(self, r: i32) -> Self {
510 unsafe { bindings::lv_obj_set_style_radius(self.raw(), r, PART_MAIN) };
511 self
512 }
513
514 fn pad_all(self, p: i32) -> Self {
516 unsafe {
517 let r = self.raw();
518 bindings::lv_obj_set_style_pad_left(r, p, PART_MAIN);
519 bindings::lv_obj_set_style_pad_right(r, p, PART_MAIN);
520 bindings::lv_obj_set_style_pad_top(r, p, PART_MAIN);
521 bindings::lv_obj_set_style_pad_bottom(r, p, PART_MAIN);
522 }
523 self
524 }
525
526 fn pad_hor(self, p: i32) -> Self {
528 unsafe {
529 let r = self.raw();
530 bindings::lv_obj_set_style_pad_left(r, p, PART_MAIN);
531 bindings::lv_obj_set_style_pad_right(r, p, PART_MAIN);
532 }
533 self
534 }
535
536 fn pad_ver(self, p: i32) -> Self {
538 unsafe {
539 let r = self.raw();
540 bindings::lv_obj_set_style_pad_top(r, p, PART_MAIN);
541 bindings::lv_obj_set_style_pad_bottom(r, p, PART_MAIN);
542 }
543 self
544 }
545
546 fn pad_top(self, p: i32) -> Self {
548 unsafe { bindings::lv_obj_set_style_pad_top(self.raw(), p, PART_MAIN) };
549 self
550 }
551 fn pad_bottom(self, p: i32) -> Self {
553 unsafe { bindings::lv_obj_set_style_pad_bottom(self.raw(), p, PART_MAIN) };
554 self
555 }
556 fn pad_left(self, p: i32) -> Self {
558 unsafe { bindings::lv_obj_set_style_pad_left(self.raw(), p, PART_MAIN) };
559 self
560 }
561 fn pad_right(self, p: i32) -> Self {
563 unsafe { bindings::lv_obj_set_style_pad_right(self.raw(), p, PART_MAIN) };
564 self
565 }
566
567 fn pad_gap(self, g: i32) -> Self {
569 unsafe {
570 let r = self.raw();
571 bindings::lv_obj_set_style_pad_row(r, g, PART_MAIN);
572 bindings::lv_obj_set_style_pad_column(r, g, PART_MAIN);
573 }
574 self
575 }
576
577 fn text_color(self, c: Color) -> Self {
579 unsafe { bindings::lv_obj_set_style_text_color(self.raw(), c.to_raw(), PART_MAIN) };
580 self
581 }
582
583 fn text_font(self, f: *const bindings::lv_font_t) -> Self {
585 unsafe { bindings::lv_obj_set_style_text_font(self.raw(), f, PART_MAIN) };
586 self
587 }
588
589 fn add_style(self, style: &Style, selector: u32) -> Self {
595 unsafe { bindings::lv_obj_add_style(self.raw(), style.ptr(), selector) };
596 self
597 }
598
599 fn translate_y(self, v: i32, selector: u32) -> Self {
601 unsafe { bindings::lv_obj_set_style_translate_y(self.raw(), v, selector) };
602 self
603 }
604
605 fn margin_top(self, v: i32, selector: u32) -> Self {
607 unsafe { bindings::lv_obj_set_style_margin_top(self.raw(), v, selector) };
608 self
609 }
610 fn margin_bottom(self, v: i32, selector: u32) -> Self {
612 unsafe { bindings::lv_obj_set_style_margin_bottom(self.raw(), v, selector) };
613 self
614 }
615 fn margin_left(self, v: i32, selector: u32) -> Self {
617 unsafe { bindings::lv_obj_set_style_margin_left(self.raw(), v, selector) };
618 self
619 }
620 fn margin_right(self, v: i32, selector: u32) -> Self {
622 unsafe { bindings::lv_obj_set_style_margin_right(self.raw(), v, selector) };
623 self
624 }
625
626 fn max_height(self, v: i32, selector: u32) -> Self {
628 unsafe { bindings::lv_obj_set_style_max_height(self.raw(), v, selector) };
629 self
630 }
631
632 fn arc_opa(self, opa: u8, selector: u32) -> Self {
634 unsafe { bindings::lv_obj_set_style_arc_opa(self.raw(), opa, selector) };
635 self
636 }
637
638 fn arc_rounded(self, rounded: bool, selector: u32) -> Self {
640 unsafe { bindings::lv_obj_set_style_arc_rounded(self.raw(), rounded, selector) };
641 self
642 }
643
644 fn opa_layered(self, opa: u8, selector: u32) -> Self {
646 unsafe { bindings::lv_obj_set_style_opa_layered(self.raw(), opa, selector) };
647 self
648 }
649
650 fn text_align(self, align: u32, selector: u32) -> Self {
652 unsafe { bindings::lv_obj_set_style_text_align(self.raw(), align as _, selector) };
653 self
654 }
655
656 fn bg_color_sel(self, c: Color, selector: u32) -> Self {
660 unsafe { bindings::lv_obj_set_style_bg_color(self.raw(), c.to_raw(), selector) };
661 self
662 }
663 fn bg_opa_sel(self, opa: u8, selector: u32) -> Self {
665 unsafe { bindings::lv_obj_set_style_bg_opa(self.raw(), opa, selector) };
666 self
667 }
668 fn border_color_sel(self, c: Color, selector: u32) -> Self {
670 unsafe { bindings::lv_obj_set_style_border_color(self.raw(), c.to_raw(), selector) };
671 self
672 }
673 fn text_color_sel(self, c: Color, selector: u32) -> Self {
675 unsafe { bindings::lv_obj_set_style_text_color(self.raw(), c.to_raw(), selector) };
676 self
677 }
678 fn arc_color_sel(self, c: Color, selector: u32) -> Self {
680 unsafe { bindings::lv_obj_set_style_arc_color(self.raw(), c.to_raw(), selector) };
681 self
682 }
683 fn arc_width(self, w: i32, selector: u32) -> Self {
685 unsafe { bindings::lv_obj_set_style_arc_width(self.raw(), w, selector) };
686 self
687 }
688 fn pad_row(self, p: i32) -> Self {
690 unsafe { bindings::lv_obj_set_style_pad_row(self.raw(), p, PART_MAIN) };
691 self
692 }
693 fn pad_column(self, p: i32) -> Self {
695 unsafe { bindings::lv_obj_set_style_pad_column(self.raw(), p, PART_MAIN) };
696 self
697 }
698 fn set_opa(self, opa: u8) -> Self {
700 unsafe { bindings::lv_obj_set_style_opa(self.raw(), opa, PART_MAIN) };
701 self
702 }
703}
704
705impl<T: Widget> Styleable for T {}
706
707#[derive(Clone, Copy)]
716pub struct EventCtx<'a> {
717 raw: *mut bindings::lv_event_t,
718 _ph: core::marker::PhantomData<&'a ()>,
719}
720
721impl<'a> EventCtx<'a> {
722 pub fn target(self) -> Obj {
724 let raw = unsafe { bindings::lv_event_get_target(self.raw) as *mut bindings::lv_obj_t };
729 Obj { raw }
730 }
731
732 pub fn current_target(self) -> Obj {
735 let raw =
736 unsafe { bindings::lv_event_get_current_target(self.raw) as *mut bindings::lv_obj_t };
737 Obj { raw }
738 }
739
740 pub fn code(self) -> bindings::lv_event_code_t {
742 unsafe { bindings::lv_event_get_code(self.raw) }
743 }
744
745 pub fn param_raw(self) -> *mut core::ffi::c_void {
748 unsafe { bindings::lv_event_get_param(self.raw) }
749 }
750}
751
752pub struct EventHandler<T: 'static> {
789 cell: &'static crate::InitCell<T>,
790 user: fn(&T, EventCtx<'_>),
791}
792
793impl<T: 'static> EventHandler<T> {
794 pub const fn new(cell: &'static crate::InitCell<T>, user: fn(&T, EventCtx<'_>)) -> Self {
796 Self { cell, user }
797 }
798}
799
800unsafe impl<T: Send + Sync + 'static> Sync for EventHandler<T> {}
806
807unsafe extern "C" fn event_trampoline_fn(e: *mut bindings::lv_event_t) {
808 let ud = unsafe { bindings::lv_event_get_user_data(e) };
809 if ud.is_null() {
810 return;
811 }
812 let cb: fn(EventCtx<'_>) = unsafe { core::mem::transmute(ud) };
814 cb(EventCtx {
815 raw: e,
816 _ph: core::marker::PhantomData,
817 });
818}
819
820unsafe extern "C" fn event_trampoline_with<T: Send + Sync + 'static>(e: *mut bindings::lv_event_t) {
821 let ud = unsafe { bindings::lv_event_get_user_data(e) } as *const EventHandler<T>;
822 if ud.is_null() {
823 return;
824 }
825 let h = unsafe { &*ud };
827 if let Some(state) = h.cell.try_get() {
828 (h.user)(
829 state,
830 EventCtx {
831 raw: e,
832 _ph: core::marker::PhantomData,
833 },
834 );
835 }
836 }
839
840pub trait EventTarget: Widget + Sized {
847 fn on_fn(self, code: bindings::lv_event_code_t, handler: fn(EventCtx<'_>)) -> Self {
849 let ud = handler as *mut core::ffi::c_void;
850 unsafe { bindings::lv_obj_add_event_cb(self.raw(), Some(event_trampoline_fn), code, ud) };
851 self
852 }
853
854 fn on_clicked(self, handler: fn(EventCtx<'_>)) -> Self {
856 self.on_fn(bindings::LV_EVENT_CLICKED, handler)
857 }
858
859 fn on_value_change(self, handler: fn(EventCtx<'_>)) -> Self {
861 self.on_fn(bindings::LV_EVENT_VALUE_CHANGED, handler)
862 }
863
864 fn on_with<T: Send + Sync + 'static>(
867 self,
868 code: bindings::lv_event_code_t,
869 handler: &'static EventHandler<T>,
870 ) -> Self {
871 let ud = handler as *const EventHandler<T> as *mut core::ffi::c_void;
872 unsafe {
873 bindings::lv_obj_add_event_cb(self.raw(), Some(event_trampoline_with::<T>), code, ud);
874 }
875 self
876 }
877
878 fn on_clicked_with<T: Send + Sync + 'static>(self, handler: &'static EventHandler<T>) -> Self {
880 self.on_with(bindings::LV_EVENT_CLICKED, handler)
881 }
882
883 fn on_value_change_with<T: Send + Sync + 'static>(
885 self,
886 handler: &'static EventHandler<T>,
887 ) -> Self {
888 self.on_with(bindings::LV_EVENT_VALUE_CHANGED, handler)
889 }
890
891 #[doc(hidden)]
895 fn on(
896 self,
897 code: bindings::lv_event_code_t,
898 cb: bindings::lv_event_cb_t,
899 user_data: *mut core::ffi::c_void,
900 ) -> Self {
901 unsafe { bindings::lv_obj_add_event_cb(self.raw(), cb, code, user_data) };
902 self
903 }
904}
905
906impl<T: Widget> EventTarget for T {}
907
908#[derive(Clone, Copy)]
917pub struct Obj {
918 raw: *mut bindings::lv_obj_t,
919}
920
921impl Obj {
922 pub unsafe fn from_raw(raw: *mut bindings::lv_obj_t) -> Self {
927 Self { raw }
928 }
929
930 pub fn as_raw(self) -> *mut bindings::lv_obj_t {
932 self.raw
933 }
934
935 pub fn create(parent: Obj) -> Self {
937 let raw = unsafe { bindings::lv_obj_create(parent.raw) };
938 Self { raw }
939 }
940
941 pub fn del(self) {
943 unsafe { bindings::lv_obj_delete(self.raw) };
944 }
945
946 pub fn clean(self) {
948 unsafe { bindings::lv_obj_clean(self.raw) };
949 }
950
951 pub fn parent(self) -> Self {
953 Self {
954 raw: unsafe { bindings::lv_obj_get_parent(self.raw) },
955 }
956 }
957
958 pub fn child_count(self) -> u32 {
960 unsafe { bindings::lv_obj_get_child_count(self.raw) }
961 }
962
963 pub fn get_width(self) -> i32 {
965 unsafe { bindings::lv_obj_get_width(self.raw) }
966 }
967
968 pub fn get_height(self) -> i32 {
970 unsafe { bindings::lv_obj_get_height(self.raw) }
971 }
972
973 pub fn set_user_data(self, data: *mut core::ffi::c_void) -> Self {
975 unsafe { bindings::lv_obj_set_user_data(self.raw, data) };
976 self
977 }
978
979 pub fn get_user_data(self) -> *mut core::ffi::c_void {
981 unsafe { bindings::lv_obj_get_user_data(self.raw) }
982 }
983
984 pub fn remove_style_all(self) -> Self {
986 unsafe { bindings::lv_obj_remove_style_all(self.raw) };
987 self
988 }
989
990 pub fn get_child(self, idx: i32) -> Obj {
993 let raw = unsafe { bindings::lv_obj_get_child(self.raw, idx) };
994 Obj { raw }
995 }
996
997 pub fn set_size(self, w: i32, h: i32) {
1000 unsafe { bindings::lv_obj_set_size(self.raw, w, h) };
1001 }
1002
1003 pub fn set_pos(self, x: i32, y: i32) {
1005 unsafe { bindings::lv_obj_set_pos(self.raw, x, y) };
1006 }
1007
1008 pub fn set_style_bg_color(self, color: Color, selector: u32) {
1010 unsafe { bindings::lv_obj_set_style_bg_color(self.raw, color.to_raw(), selector) };
1011 }
1012
1013 pub fn set_style_text_color(self, color: Color, selector: u32) {
1015 unsafe { bindings::lv_obj_set_style_text_color(self.raw, color.to_raw(), selector) };
1016 }
1017
1018 pub fn set_style_radius(self, radius: i32, selector: u32) {
1020 unsafe { bindings::lv_obj_set_style_radius(self.raw, radius, selector) };
1021 }
1022
1023 pub fn set_style_text_font(self, font: *const bindings::lv_font_t, selector: u32) {
1025 unsafe { bindings::lv_obj_set_style_text_font(self.raw, font, selector) };
1026 }
1027}
1028
1029impl Widget for Obj {
1030 fn raw(self) -> *mut bindings::lv_obj_t {
1031 self.raw
1032 }
1033}
1034
1035#[derive(Clone, Copy)]
1041pub struct Label {
1042 raw: *mut bindings::lv_obj_t,
1043}
1044
1045impl Label {
1046 pub fn create(parent: impl Widget) -> Self {
1048 let raw = unsafe { bindings::lv_label_create(parent.raw()) };
1049 Self { raw }
1050 }
1051
1052 pub unsafe fn from_raw(raw: *mut bindings::lv_obj_t) -> Self {
1058 Self { raw }
1059 }
1060
1061 pub fn set_text(self, text: &[u8]) {
1063 unsafe { bindings::lv_label_set_text(self.raw, text.as_ptr() as *const _) };
1064 }
1065
1066 pub fn set_text_static(self, text: &'static [u8]) {
1070 unsafe { bindings::lv_label_set_text_static(self.raw, text.as_ptr() as *const _) };
1071 }
1072
1073 pub fn text(self, txt: &[u8]) -> Self {
1075 unsafe { bindings::lv_label_set_text(self.raw, txt.as_ptr() as *const _) };
1076 self
1077 }
1078
1079 pub fn text_static(self, txt: &'static [u8]) -> Self {
1081 unsafe { bindings::lv_label_set_text_static(self.raw, txt.as_ptr() as *const _) };
1082 self
1083 }
1084
1085 pub fn font(self, f: *const bindings::lv_font_t) -> Self {
1087 unsafe { bindings::lv_obj_set_style_text_font(self.raw, f, PART_MAIN) };
1088 self
1089 }
1090
1091 pub fn color(self, c: Color) -> Self {
1093 unsafe { bindings::lv_obj_set_style_text_color(self.raw, c.to_raw(), PART_MAIN) };
1094 self
1095 }
1096
1097 pub fn long_mode(self, mode: bindings::lv_label_long_mode_t) -> Self {
1099 unsafe { bindings::lv_label_set_long_mode(self.raw(), mode) };
1100 self
1101 }
1102}
1103
1104impl Widget for Label {
1105 fn raw(self) -> *mut bindings::lv_obj_t {
1106 self.raw
1107 }
1108}
1109
1110impl core::ops::Deref for Label {
1111 type Target = Obj;
1112 fn deref(&self) -> &Obj {
1113 unsafe { &*(self as *const Label as *const Obj) }
1115 }
1116}
1117
1118#[derive(Clone, Copy)]
1124pub struct Bar {
1125 raw: *mut bindings::lv_obj_t,
1126}
1127
1128impl Bar {
1129 pub fn create(parent: impl Widget) -> Self {
1131 let raw = unsafe { bindings::lv_bar_create(parent.raw()) };
1132 Self { raw }
1133 }
1134
1135 pub fn set_value(self, value: i32, anim: bool) {
1137 unsafe {
1138 #[allow(clippy::unnecessary_cast)]
1139 bindings::lv_bar_set_value(self.raw, value, anim as _);
1140 }
1141 }
1142
1143 pub fn set_range(self, min: i32, max: i32) {
1145 unsafe { bindings::lv_bar_set_range(self.raw, min, max) };
1146 }
1147
1148 pub fn value(self, val: i32) -> Self {
1150 unsafe {
1151 #[allow(clippy::unnecessary_cast)]
1152 bindings::lv_bar_set_value(self.raw, val, true as _);
1153 }
1154 self
1155 }
1156
1157 pub fn value_anim(self, val: i32, anim: bool) -> Self {
1159 unsafe {
1160 #[allow(clippy::unnecessary_cast)]
1161 bindings::lv_bar_set_value(self.raw, val, anim as _);
1162 }
1163 self
1164 }
1165
1166 pub fn range(self, min: i32, max: i32) -> Self {
1168 unsafe { bindings::lv_bar_set_range(self.raw, min, max) };
1169 self
1170 }
1171
1172 pub fn indicator_color(self, c: Color) -> Self {
1174 unsafe { bindings::lv_obj_set_style_bg_color(self.raw, c.to_raw(), PART_INDICATOR) };
1175 self
1176 }
1177
1178 pub fn bar_color(self, c: Color) -> Self {
1180 unsafe { bindings::lv_obj_set_style_bg_color(self.raw, c.to_raw(), PART_MAIN) };
1181 self
1182 }
1183}
1184
1185impl Widget for Bar {
1186 fn raw(self) -> *mut bindings::lv_obj_t {
1187 self.raw
1188 }
1189}
1190
1191impl core::ops::Deref for Bar {
1192 type Target = Obj;
1193 fn deref(&self) -> &Obj {
1194 unsafe { &*(self as *const Bar as *const Obj) }
1195 }
1196}
1197
1198#[derive(Clone, Copy)]
1204pub struct Box {
1205 raw: *mut bindings::lv_obj_t,
1206}
1207
1208impl Box {
1209 pub fn create(parent: impl Widget) -> Self {
1211 let raw = unsafe {
1212 let obj = bindings::lv_obj_create(parent.raw());
1213 bindings::lv_obj_remove_flag(obj, bindings::LV_OBJ_FLAG_SCROLLABLE);
1214 obj
1215 };
1216 Self { raw }
1217 }
1218}
1219
1220impl Widget for Box {
1221 fn raw(self) -> *mut bindings::lv_obj_t {
1222 self.raw
1223 }
1224}
1225
1226impl core::ops::Deref for Box {
1227 type Target = Obj;
1228 fn deref(&self) -> &Obj {
1229 unsafe { &*(self as *const Box as *const Obj) }
1230 }
1231}
1232
1233#[derive(Clone, Copy)]
1243pub struct Button {
1244 raw: *mut bindings::lv_obj_t,
1245}
1246
1247impl Button {
1248 pub fn create(parent: impl Widget) -> Self {
1250 let raw = unsafe { bindings::lv_button_create(parent.raw()) };
1251 Self { raw }
1252 }
1253
1254 pub fn toggle_mode(self, on: bool) -> Self {
1256 if on {
1257 unsafe { bindings::lv_obj_add_flag(self.raw, bindings::LV_OBJ_FLAG_CHECKABLE) };
1258 } else {
1259 unsafe { bindings::lv_obj_remove_flag(self.raw, bindings::LV_OBJ_FLAG_CHECKABLE) };
1260 }
1261 self
1262 }
1263
1264 pub fn checked(self, v: bool) -> Self {
1266 if v {
1267 unsafe { bindings::lv_obj_add_state(self.raw, STATE_CHECKED as _) };
1268 } else {
1269 unsafe { bindings::lv_obj_remove_state(self.raw, STATE_CHECKED as _) };
1270 }
1271 self
1272 }
1273
1274 pub fn is_checked(self) -> bool {
1276 unsafe { bindings::lv_obj_has_state(self.raw, STATE_CHECKED as _) }
1277 }
1278}
1279
1280impl Widget for Button {
1281 fn raw(self) -> *mut bindings::lv_obj_t {
1282 self.raw
1283 }
1284}
1285
1286impl core::ops::Deref for Button {
1287 type Target = Obj;
1288 fn deref(&self) -> &Obj {
1289 unsafe { &*(self as *const Button as *const Obj) }
1290 }
1291}
1292
1293#[derive(Clone, Copy)]
1301pub struct Slider {
1302 raw: *mut bindings::lv_obj_t,
1303}
1304
1305impl Slider {
1306 pub fn create(parent: impl Widget) -> Self {
1308 let raw = unsafe { bindings::lv_slider_create(parent.raw()) };
1309 Self { raw }
1310 }
1311
1312 pub fn value(self, val: i32) -> Self {
1314 unsafe {
1315 #[allow(clippy::unnecessary_cast)]
1316 bindings::lv_slider_set_value(self.raw, val, true as _);
1317 }
1318 self
1319 }
1320
1321 pub fn value_anim(self, val: i32, anim: bool) -> Self {
1323 unsafe {
1324 #[allow(clippy::unnecessary_cast)]
1325 bindings::lv_slider_set_value(self.raw, val, anim as _);
1326 }
1327 self
1328 }
1329
1330 pub fn range(self, min: i32, max: i32) -> Self {
1332 unsafe { bindings::lv_slider_set_range(self.raw, min, max) };
1333 self
1334 }
1335
1336 pub fn get_value(self) -> i32 {
1338 unsafe { bindings::lv_slider_get_value(self.raw) }
1339 }
1340
1341 pub fn indicator_color(self, c: Color) -> Self {
1343 unsafe { bindings::lv_obj_set_style_bg_color(self.raw, c.to_raw(), PART_INDICATOR) };
1344 self
1345 }
1346
1347 pub fn knob_color(self, c: Color) -> Self {
1349 unsafe { bindings::lv_obj_set_style_bg_color(self.raw, c.to_raw(), PART_KNOB) };
1350 self
1351 }
1352}
1353
1354impl Widget for Slider {
1355 fn raw(self) -> *mut bindings::lv_obj_t {
1356 self.raw
1357 }
1358}
1359
1360impl core::ops::Deref for Slider {
1361 type Target = Obj;
1362 fn deref(&self) -> &Obj {
1363 unsafe { &*(self as *const Slider as *const Obj) }
1364 }
1365}
1366
1367#[derive(Clone, Copy)]
1375pub struct Switch {
1376 raw: *mut bindings::lv_obj_t,
1377}
1378
1379impl Switch {
1380 pub fn create(parent: impl Widget) -> Self {
1382 let raw = unsafe { bindings::lv_switch_create(parent.raw()) };
1383 Self { raw }
1384 }
1385
1386 pub fn checked(self, v: bool) -> Self {
1388 if v {
1389 unsafe { bindings::lv_obj_add_state(self.raw, STATE_CHECKED as _) };
1390 } else {
1391 unsafe { bindings::lv_obj_remove_state(self.raw, STATE_CHECKED as _) };
1392 }
1393 self
1394 }
1395
1396 pub fn is_checked(self) -> bool {
1398 unsafe { bindings::lv_obj_has_state(self.raw, STATE_CHECKED as _) }
1399 }
1400}
1401
1402impl Widget for Switch {
1403 fn raw(self) -> *mut bindings::lv_obj_t {
1404 self.raw
1405 }
1406}
1407
1408impl core::ops::Deref for Switch {
1409 type Target = Obj;
1410 fn deref(&self) -> &Obj {
1411 unsafe { &*(self as *const Switch as *const Obj) }
1412 }
1413}
1414
1415#[derive(Clone, Copy)]
1421pub struct Checkbox {
1422 raw: *mut bindings::lv_obj_t,
1423}
1424
1425impl Checkbox {
1426 pub fn create(parent: impl Widget) -> Self {
1428 let raw = unsafe { bindings::lv_checkbox_create(parent.raw()) };
1429 Self { raw }
1430 }
1431
1432 pub fn text(self, txt: &[u8]) -> Self {
1434 unsafe { bindings::lv_checkbox_set_text(self.raw, txt.as_ptr() as *const _) };
1435 self
1436 }
1437
1438 pub fn text_static(self, txt: &'static [u8]) -> Self {
1440 unsafe { bindings::lv_checkbox_set_text_static(self.raw, txt.as_ptr() as *const _) };
1441 self
1442 }
1443
1444 pub fn checked(self, v: bool) -> Self {
1446 if v {
1447 unsafe { bindings::lv_obj_add_state(self.raw, STATE_CHECKED as _) };
1448 } else {
1449 unsafe { bindings::lv_obj_remove_state(self.raw, STATE_CHECKED as _) };
1450 }
1451 self
1452 }
1453
1454 pub fn is_checked(self) -> bool {
1456 unsafe { bindings::lv_obj_has_state(self.raw, STATE_CHECKED as _) }
1457 }
1458}
1459
1460impl Widget for Checkbox {
1461 fn raw(self) -> *mut bindings::lv_obj_t {
1462 self.raw
1463 }
1464}
1465
1466impl core::ops::Deref for Checkbox {
1467 type Target = Obj;
1468 fn deref(&self) -> &Obj {
1469 unsafe { &*(self as *const Checkbox as *const Obj) }
1470 }
1471}
1472
1473#[derive(Clone, Copy)]
1482pub struct Arc {
1483 raw: *mut bindings::lv_obj_t,
1484}
1485
1486impl Arc {
1487 pub fn create(parent: impl Widget) -> Self {
1489 let raw = unsafe { bindings::lv_arc_create(parent.raw()) };
1490 Self { raw }
1491 }
1492
1493 pub fn value(self, val: i32) -> Self {
1495 unsafe { bindings::lv_arc_set_value(self.raw, val) };
1496 self
1497 }
1498
1499 pub fn range(self, min: i32, max: i32) -> Self {
1501 unsafe { bindings::lv_arc_set_range(self.raw, min, max) };
1502 self
1503 }
1504
1505 pub fn bg_angles(self, start: u32, end: u32) -> Self {
1507 unsafe { bindings::lv_arc_set_bg_angles(self.raw, start as _, end as _) };
1508 self
1509 }
1510
1511 pub fn angles(self, start: u32, end: u32) -> Self {
1513 unsafe { bindings::lv_arc_set_angles(self.raw, start as _, end as _) };
1514 self
1515 }
1516
1517 pub fn rotation(self, rot: u32) -> Self {
1519 unsafe { bindings::lv_arc_set_rotation(self.raw, rot as _) };
1520 self
1521 }
1522
1523 pub fn get_value(self) -> i32 {
1525 unsafe { bindings::lv_arc_get_value(self.raw) }
1526 }
1527
1528 pub fn track_color(self, c: Color) -> Self {
1530 unsafe { bindings::lv_obj_set_style_arc_color(self.raw, c.to_raw(), PART_MAIN) };
1531 self
1532 }
1533
1534 pub fn indicator_color(self, c: Color) -> Self {
1536 unsafe { bindings::lv_obj_set_style_arc_color(self.raw, c.to_raw(), PART_INDICATOR) };
1537 self
1538 }
1539
1540 pub fn indicator_width(self, w: i32) -> Self {
1542 unsafe { bindings::lv_obj_set_style_arc_width(self.raw, w, PART_INDICATOR) };
1543 self
1544 }
1545
1546 pub fn knob_color(self, c: Color) -> Self {
1548 unsafe { bindings::lv_obj_set_style_bg_color(self.raw, c.to_raw(), PART_KNOB) };
1549 self
1550 }
1551}
1552
1553impl Widget for Arc {
1554 fn raw(self) -> *mut bindings::lv_obj_t {
1555 self.raw
1556 }
1557}
1558
1559impl core::ops::Deref for Arc {
1560 type Target = Obj;
1561 fn deref(&self) -> &Obj {
1562 unsafe { &*(self as *const Arc as *const Obj) }
1563 }
1564}
1565
1566#[derive(Clone, Copy)]
1576pub struct Msgbox {
1577 raw: *mut bindings::lv_obj_t,
1578}
1579
1580impl Msgbox {
1581 pub fn create(parent: impl Widget) -> Self {
1584 let raw = unsafe { bindings::lv_msgbox_create(parent.raw()) };
1585 Self { raw }
1586 }
1587
1588 pub fn create_modal() -> Self {
1590 let raw = unsafe { bindings::lv_msgbox_create(core::ptr::null_mut()) };
1591 Self { raw }
1592 }
1593
1594 pub fn add_title(self, txt: &[u8]) -> Self {
1596 unsafe { bindings::lv_msgbox_add_title(self.raw, txt.as_ptr() as *const _) };
1597 self
1598 }
1599
1600 pub fn add_text(self, txt: &[u8]) -> Self {
1602 unsafe { bindings::lv_msgbox_add_text(self.raw, txt.as_ptr() as *const _) };
1603 self
1604 }
1605
1606 pub fn add_close_button(self) -> Self {
1608 unsafe { bindings::lv_msgbox_add_close_button(self.raw) };
1609 self
1610 }
1611
1612 pub fn add_footer_button(self, txt: &[u8]) -> Obj {
1615 let btn =
1616 unsafe { bindings::lv_msgbox_add_footer_button(self.raw, txt.as_ptr() as *const _) };
1617 unsafe { Obj::from_raw(btn) }
1618 }
1619
1620 pub fn get_content(self) -> Obj {
1622 let c = unsafe { bindings::lv_msgbox_get_content(self.raw) };
1623 unsafe { Obj::from_raw(c) }
1624 }
1625
1626 pub fn get_header(self) -> Obj {
1628 let h = unsafe { bindings::lv_msgbox_get_header(self.raw) };
1629 unsafe { Obj::from_raw(h) }
1630 }
1631
1632 pub fn get_footer(self) -> Obj {
1634 let f = unsafe { bindings::lv_msgbox_get_footer(self.raw) };
1635 unsafe { Obj::from_raw(f) }
1636 }
1637
1638 pub fn close(self) {
1640 unsafe { bindings::lv_msgbox_close(self.raw) };
1641 }
1642}
1643
1644impl Widget for Msgbox {
1645 fn raw(self) -> *mut bindings::lv_obj_t {
1646 self.raw
1647 }
1648}
1649
1650impl core::ops::Deref for Msgbox {
1651 type Target = Obj;
1652 fn deref(&self) -> &Obj {
1653 unsafe { &*(self as *const Msgbox as *const Obj) }
1654 }
1655}
1656
1657#[derive(Clone, Copy)]
1664pub struct Spinner {
1665 raw: *mut bindings::lv_obj_t,
1666}
1667
1668impl Spinner {
1669 pub fn create(parent: impl Widget) -> Self {
1671 let raw = unsafe { bindings::lv_spinner_create(parent.raw()) };
1672 Self { raw }
1673 }
1674
1675 pub fn anim_params(self, time_ms: u32, angle_deg: u32) -> Self {
1677 unsafe { bindings::lv_spinner_set_anim_params(self.raw, time_ms, angle_deg) };
1678 self
1679 }
1680}
1681
1682impl Widget for Spinner {
1683 fn raw(self) -> *mut bindings::lv_obj_t {
1684 self.raw
1685 }
1686}
1687
1688impl core::ops::Deref for Spinner {
1689 type Target = Obj;
1690 fn deref(&self) -> &Obj {
1691 unsafe { &*(self as *const Spinner as *const Obj) }
1692 }
1693}
1694
1695#[derive(Clone, Copy)]
1702pub struct Led {
1703 raw: *mut bindings::lv_obj_t,
1704}
1705
1706impl Led {
1707 pub fn create(parent: impl Widget) -> Self {
1709 let raw = unsafe { bindings::lv_led_create(parent.raw()) };
1710 Self { raw }
1711 }
1712
1713 pub fn color(self, c: Color) -> Self {
1715 unsafe { bindings::lv_led_set_color(self.raw, c.to_raw()) };
1716 self
1717 }
1718
1719 pub fn brightness(self, bright: u8) -> Self {
1721 unsafe { bindings::lv_led_set_brightness(self.raw, bright) };
1722 self
1723 }
1724
1725 pub fn on(self) -> Self {
1727 unsafe { bindings::lv_led_on(self.raw) };
1728 self
1729 }
1730
1731 pub fn off(self) -> Self {
1733 unsafe { bindings::lv_led_off(self.raw) };
1734 self
1735 }
1736
1737 pub fn toggle(self) -> Self {
1739 unsafe { bindings::lv_led_toggle(self.raw) };
1740 self
1741 }
1742
1743 pub fn get_brightness(self) -> u8 {
1745 unsafe { bindings::lv_led_get_brightness(self.raw) }
1746 }
1747}
1748
1749impl Widget for Led {
1750 fn raw(self) -> *mut bindings::lv_obj_t {
1751 self.raw
1752 }
1753}
1754
1755impl core::ops::Deref for Led {
1756 type Target = Obj;
1757 fn deref(&self) -> &Obj {
1758 unsafe { &*(self as *const Led as *const Obj) }
1759 }
1760}
1761
1762pub const CHART_TYPE_NONE: u32 = 0;
1768pub const CHART_TYPE_LINE: u32 = 1;
1770pub const CHART_TYPE_BAR: u32 = 2;
1772pub const CHART_TYPE_SCATTER: u32 = 3;
1774
1775pub const CHART_AXIS_PRIMARY_Y: u32 = 0x00;
1777pub const CHART_AXIS_SECONDARY_Y: u32 = 0x01;
1779pub const CHART_AXIS_PRIMARY_X: u32 = 0x02;
1781pub const CHART_AXIS_SECONDARY_X: u32 = 0x04;
1783
1784pub const CHART_UPDATE_MODE_SHIFT: u32 = 0;
1786pub const CHART_UPDATE_MODE_CIRCULAR: u32 = 1;
1788
1789#[derive(Clone, Copy)]
1791pub struct Series {
1792 chart: *mut bindings::lv_obj_t,
1793 raw: *mut bindings::lv_chart_series_t,
1794}
1795
1796impl Series {
1797 pub fn next_value(self, v: i32) -> Self {
1799 unsafe { bindings::lv_chart_set_next_value(self.chart, self.raw, v) };
1800 self
1801 }
1802
1803 pub fn set_value_by_idx(self, idx: u32, v: i32) -> Self {
1805 unsafe { bindings::lv_chart_set_series_value_by_id(self.chart, self.raw, idx, v) };
1806 self
1807 }
1808
1809 pub fn as_raw(self) -> *mut bindings::lv_chart_series_t {
1811 self.raw
1812 }
1813}
1814
1815unsafe impl Send for Series {}
1819unsafe impl Sync for Series {}
1820
1821#[derive(Clone, Copy)]
1823pub struct Chart {
1824 raw: *mut bindings::lv_obj_t,
1825}
1826
1827impl Chart {
1828 pub fn create(parent: impl Widget) -> Self {
1830 let raw = unsafe { bindings::lv_chart_create(parent.raw()) };
1831 Self { raw }
1832 }
1833
1834 pub fn chart_type(self, t: u32) -> Self {
1836 unsafe { bindings::lv_chart_set_type(self.raw, t as _) };
1837 self
1838 }
1839
1840 pub fn point_count(self, count: u32) -> Self {
1842 unsafe { bindings::lv_chart_set_point_count(self.raw, count) };
1843 self
1844 }
1845
1846 pub fn range(self, axis: u32, min: i32, max: i32) -> Self {
1848 unsafe { bindings::lv_chart_set_axis_range(self.raw, axis as _, min, max) };
1849 self
1850 }
1851
1852 pub fn update_mode(self, mode: u32) -> Self {
1854 unsafe { bindings::lv_chart_set_update_mode(self.raw, mode as _) };
1855 self
1856 }
1857
1858 pub fn div_line_count(self, hdiv: u8, vdiv: u8) -> Self {
1860 unsafe { bindings::lv_chart_set_div_line_count(self.raw, hdiv as u32, vdiv as u32) };
1861 self
1862 }
1863
1864 pub fn add_series(self, color: Color, axis: u32) -> Series {
1866 let raw = unsafe { bindings::lv_chart_add_series(self.raw, color.to_raw(), axis as _) };
1867 Series {
1868 chart: self.raw,
1869 raw,
1870 }
1871 }
1872
1873 pub fn remove_series(self, s: Series) -> Self {
1875 unsafe { bindings::lv_chart_remove_series(self.raw, s.raw) };
1876 self
1877 }
1878}
1879
1880impl Widget for Chart {
1881 fn raw(self) -> *mut bindings::lv_obj_t {
1882 self.raw
1883 }
1884}
1885
1886impl core::ops::Deref for Chart {
1887 type Target = Obj;
1888 fn deref(&self) -> &Obj {
1889 unsafe { &*(self as *const Chart as *const Obj) }
1890 }
1891}
1892
1893#[derive(Clone, Copy)]
1900pub struct Calendar {
1901 raw: *mut bindings::lv_obj_t,
1902}
1903
1904impl Calendar {
1905 pub fn create(parent: impl Widget) -> Self {
1907 let raw = unsafe { bindings::lv_calendar_create(parent.raw()) };
1908 Self { raw }
1909 }
1910
1911 pub fn today(self, year: u32, month: u32, day: u32) -> Self {
1913 unsafe { bindings::lv_calendar_set_today_date(self.raw, year, month, day) };
1914 self
1915 }
1916
1917 pub fn showed(self, year: u32, month: u32) -> Self {
1919 unsafe { bindings::lv_calendar_set_month_shown(self.raw, year, month) };
1920 self
1921 }
1922
1923 pub fn get_pressed_date(self) -> Option<(u32, u32, u32)> {
1925 let mut date: bindings::lv_calendar_date_t = unsafe { core::mem::zeroed() };
1926 let ok = unsafe { bindings::lv_calendar_get_pressed_date(self.raw, &mut date) };
1927 if ok != 0 {
1929 Some((date.year as u32, date.month as u32, date.day as u32))
1935 } else {
1936 None
1937 }
1938 }
1939
1940 pub fn add_header_arrow(self) -> Obj {
1942 let raw = unsafe { bindings::lv_calendar_add_header_arrow(self.raw) };
1943 unsafe { Obj::from_raw(raw) }
1944 }
1945
1946 pub fn add_header_dropdown(self) -> Obj {
1948 let raw = unsafe { bindings::lv_calendar_add_header_dropdown(self.raw) };
1949 unsafe { Obj::from_raw(raw) }
1950 }
1951
1952 pub fn highlighted_dates(self, dates: &'static [bindings::lv_calendar_date_t]) -> Self {
1955 unsafe {
1956 bindings::lv_calendar_set_highlighted_dates(
1957 self.raw(),
1958 dates.as_ptr().cast_mut(),
1959 dates.len() as _,
1960 );
1961 }
1962 self
1963 }
1964}
1965
1966impl Widget for Calendar {
1967 fn raw(self) -> *mut bindings::lv_obj_t {
1968 self.raw
1969 }
1970}
1971
1972impl core::ops::Deref for Calendar {
1973 type Target = Obj;
1974 fn deref(&self) -> &Obj {
1975 unsafe { &*(self as *const Calendar as *const Obj) }
1976 }
1977}
1978
1979#[derive(Clone, Copy)]
1992pub struct Canvas {
1993 raw: *mut bindings::lv_obj_t,
1994}
1995
1996impl Canvas {
1997 pub fn create(parent: impl Widget) -> Self {
1999 let raw = unsafe { bindings::lv_canvas_create(parent.raw()) };
2000 Self { raw }
2001 }
2002
2003 #[doc(hidden)]
2011 pub unsafe fn buffer(
2012 self,
2013 buf: *mut core::ffi::c_void,
2014 w: i32,
2015 h: i32,
2016 cf: bindings::lv_color_format_t,
2017 ) -> Self {
2018 unsafe { bindings::lv_canvas_set_buffer(self.raw, buf, w, h, cf) };
2019 self
2020 }
2021
2022 pub fn fill_bg(self, color: Color, opa: u8) -> Self {
2024 unsafe { bindings::lv_canvas_fill_bg(self.raw, color.to_raw(), opa) };
2025 self
2026 }
2027
2028 pub fn set_pixel(self, x: i32, y: i32, color: Color) -> Self {
2030 unsafe { bindings::lv_canvas_set_px(self.raw, x, y, color.to_raw(), 255) };
2031 self
2032 }
2033
2034 pub fn raw_obj(self) -> *mut bindings::lv_obj_t {
2038 self.raw
2039 }
2040
2041 pub fn init_layer(self, layer: *mut bindings::lv_layer_t) -> Self {
2044 unsafe { bindings::lv_canvas_init_layer(self.raw(), layer) };
2045 self
2046 }
2047
2048 pub fn finish_layer(self, layer: *mut bindings::lv_layer_t) -> Self {
2051 unsafe { bindings::lv_canvas_finish_layer(self.raw(), layer) };
2052 self
2053 }
2054}
2055
2056impl Widget for Canvas {
2057 fn raw(self) -> *mut bindings::lv_obj_t {
2058 self.raw
2059 }
2060}
2061
2062impl core::ops::Deref for Canvas {
2063 type Target = Obj;
2064 fn deref(&self) -> &Obj {
2065 unsafe { &*(self as *const Canvas as *const Obj) }
2066 }
2067}
2068
2069#[derive(Clone, Copy)]
2075pub struct Table {
2076 raw: *mut bindings::lv_obj_t,
2077}
2078
2079impl Table {
2080 pub fn create(parent: impl Widget) -> Self {
2082 let raw = unsafe { bindings::lv_table_create(parent.raw()) };
2083 Self { raw }
2084 }
2085
2086 pub fn cell_value(self, row: u32, col: u32, txt: &[u8]) -> Self {
2088 unsafe { bindings::lv_table_set_cell_value(self.raw, row, col, txt.as_ptr() as *const _) };
2089 self
2090 }
2091
2092 pub fn row_count(self, n: u32) -> Self {
2094 unsafe { bindings::lv_table_set_row_count(self.raw, n) };
2095 self
2096 }
2097
2098 pub fn column_count(self, n: u32) -> Self {
2100 unsafe { bindings::lv_table_set_column_count(self.raw, n) };
2101 self
2102 }
2103
2104 pub fn column_width(self, col: u32, w: i32) -> Self {
2106 unsafe { bindings::lv_table_set_column_width(self.raw, col, w) };
2107 self
2108 }
2109
2110 pub fn get_row_count(self) -> u32 {
2112 unsafe { bindings::lv_table_get_row_count(self.raw) }
2113 }
2114
2115 pub fn get_column_count(self) -> u32 {
2117 unsafe { bindings::lv_table_get_column_count(self.raw) }
2118 }
2119
2120 pub fn get_column_width(self, col: u32) -> i32 {
2122 unsafe { bindings::lv_table_get_column_width(self.raw, col) }
2123 }
2124
2125 pub fn get_cell_value(self, row: u32, col: u32) -> *const core::ffi::c_char {
2128 unsafe { bindings::lv_table_get_cell_value(self.raw(), row, col) }
2129 }
2130}
2131
2132impl Widget for Table {
2133 fn raw(self) -> *mut bindings::lv_obj_t {
2134 self.raw
2135 }
2136}
2137
2138impl core::ops::Deref for Table {
2139 type Target = Obj;
2140 fn deref(&self) -> &Obj {
2141 unsafe { &*(self as *const Table as *const Obj) }
2142 }
2143}
2144
2145#[derive(Clone, Copy)]
2151pub struct Tabview {
2152 raw: *mut bindings::lv_obj_t,
2153}
2154
2155impl Tabview {
2156 pub fn create(parent: impl Widget) -> Self {
2158 let raw = unsafe { bindings::lv_tabview_create(parent.raw()) };
2159 Self { raw }
2160 }
2161
2162 pub fn add_tab(self, name: &[u8]) -> Obj {
2164 let raw = unsafe { bindings::lv_tabview_add_tab(self.raw, name.as_ptr() as *const _) };
2165 unsafe { Obj::from_raw(raw) }
2166 }
2167
2168 pub fn rename_tab(self, idx: u32, name: &[u8]) -> Self {
2170 unsafe { bindings::lv_tabview_set_tab_text(self.raw, idx, name.as_ptr() as *const _) };
2171 self
2172 }
2173
2174 pub fn set_active(self, idx: u32, anim: bool) -> Self {
2176 unsafe {
2177 #[allow(clippy::unnecessary_cast)]
2178 bindings::lv_tabview_set_active(self.raw, idx, anim as _);
2179 }
2180 self
2181 }
2182
2183 pub fn tab_bar_position(self, dir: bindings::lv_dir_t) -> Self {
2185 unsafe { bindings::lv_tabview_set_tab_bar_position(self.raw, dir) };
2186 self
2187 }
2188
2189 pub fn tab_bar_size(self, size: i32) -> Self {
2191 unsafe { bindings::lv_tabview_set_tab_bar_size(self.raw, size) };
2192 self
2193 }
2194
2195 pub fn get_tab_count(self) -> u32 {
2197 unsafe { bindings::lv_tabview_get_tab_count(self.raw) }
2198 }
2199
2200 pub fn get_tab_active(self) -> u32 {
2202 unsafe { bindings::lv_tabview_get_tab_active(self.raw) }
2203 }
2204
2205 pub fn get_content(self) -> Obj {
2207 let raw = unsafe { bindings::lv_tabview_get_content(self.raw) };
2208 unsafe { Obj::from_raw(raw) }
2209 }
2210}
2211
2212impl Widget for Tabview {
2213 fn raw(self) -> *mut bindings::lv_obj_t {
2214 self.raw
2215 }
2216}
2217
2218impl core::ops::Deref for Tabview {
2219 type Target = Obj;
2220 fn deref(&self) -> &Obj {
2221 unsafe { &*(self as *const Tabview as *const Obj) }
2222 }
2223}
2224
2225#[derive(Clone, Copy)]
2231pub struct List {
2232 raw: *mut bindings::lv_obj_t,
2233}
2234
2235impl List {
2236 pub fn create(parent: impl Widget) -> Self {
2238 let raw = unsafe { bindings::lv_list_create(parent.raw()) };
2239 Self { raw }
2240 }
2241
2242 pub fn add_text(self, text: &[u8]) -> Obj {
2244 let raw = unsafe { bindings::lv_list_add_text(self.raw, text.as_ptr() as *const _) };
2245 unsafe { Obj::from_raw(raw) }
2246 }
2247
2248 pub fn add_button(self, icon: Option<ImageSrc>, text: &[u8]) -> Obj {
2250 let icon_ptr = icon.map_or(core::ptr::null(), ImageSrc::raw_ptr);
2251 let raw =
2252 unsafe { bindings::lv_list_add_button(self.raw, icon_ptr, text.as_ptr() as *const _) };
2253 unsafe { Obj::from_raw(raw) }
2254 }
2255
2256 pub fn get_button_text(self, btn: Obj) -> *const core::ffi::c_char {
2259 unsafe { bindings::lv_list_get_button_text(self.raw(), btn.as_raw()) }
2260 }
2261}
2262
2263impl Widget for List {
2264 fn raw(self) -> *mut bindings::lv_obj_t {
2265 self.raw
2266 }
2267}
2268
2269impl core::ops::Deref for List {
2270 type Target = Obj;
2271 fn deref(&self) -> &Obj {
2272 unsafe { &*(self as *const List as *const Obj) }
2273 }
2274}
2275
2276#[derive(Clone, Copy)]
2283pub struct Textarea {
2284 raw: *mut bindings::lv_obj_t,
2285}
2286
2287impl Textarea {
2288 pub fn create(parent: impl Widget) -> Self {
2290 let raw = unsafe { bindings::lv_textarea_create(parent.raw()) };
2291 Self { raw }
2292 }
2293
2294 pub fn text(self, txt: &[u8]) -> Self {
2296 unsafe { bindings::lv_textarea_set_text(self.raw, txt.as_ptr() as *const _) };
2297 self
2298 }
2299
2300 pub fn add_text(self, txt: &[u8]) -> Self {
2302 unsafe { bindings::lv_textarea_add_text(self.raw, txt.as_ptr() as *const _) };
2303 self
2304 }
2305
2306 pub fn placeholder(self, txt: &[u8]) -> Self {
2308 unsafe { bindings::lv_textarea_set_placeholder_text(self.raw, txt.as_ptr() as *const _) };
2309 self
2310 }
2311
2312 pub fn one_line(self, en: bool) -> Self {
2314 unsafe { bindings::lv_textarea_set_one_line(self.raw, en) };
2315 self
2316 }
2317
2318 pub fn password_mode(self, en: bool) -> Self {
2320 unsafe { bindings::lv_textarea_set_password_mode(self.raw, en) };
2321 self
2322 }
2323
2324 pub fn max_length(self, n: u32) -> Self {
2326 unsafe { bindings::lv_textarea_set_max_length(self.raw, n) };
2327 self
2328 }
2329
2330 pub fn accepted_chars(self, list: &[u8]) -> Self {
2332 unsafe { bindings::lv_textarea_set_accepted_chars(self.raw, list.as_ptr() as *const _) };
2333 self
2334 }
2335
2336 pub fn cursor_pos(self, pos: i32) -> Self {
2338 unsafe { bindings::lv_textarea_set_cursor_pos(self.raw, pos) };
2339 self
2340 }
2341
2342 pub fn cursor_click_pos(self, en: bool) -> Self {
2344 unsafe { bindings::lv_textarea_set_cursor_click_pos(self.raw, en) };
2345 self
2346 }
2347
2348 pub fn get_text_ptr(&self) -> *const core::ffi::c_char {
2351 unsafe { bindings::lv_textarea_get_text(self.raw) }
2352 }
2353
2354 pub fn get_cursor_pos(self) -> u32 {
2356 unsafe { bindings::lv_textarea_get_cursor_pos(self.raw) }
2357 }
2358
2359 pub fn is_password_mode(self) -> bool {
2361 unsafe { bindings::lv_textarea_get_password_mode(self.raw) }
2362 }
2363
2364 pub fn is_one_line(self) -> bool {
2366 unsafe { bindings::lv_textarea_get_one_line(self.raw) }
2367 }
2368
2369 pub fn add_char(self, c: u32) -> Self {
2371 unsafe { bindings::lv_textarea_add_char(self.raw, c) };
2372 self
2373 }
2374
2375 pub fn delete_char(self) -> Self {
2377 unsafe { bindings::lv_textarea_delete_char(self.raw) };
2378 self
2379 }
2380}
2381
2382impl Widget for Textarea {
2383 fn raw(self) -> *mut bindings::lv_obj_t {
2384 self.raw
2385 }
2386}
2387
2388impl core::ops::Deref for Textarea {
2389 type Target = Obj;
2390 fn deref(&self) -> &Obj {
2391 unsafe { &*(self as *const Textarea as *const Obj) }
2392 }
2393}
2394
2395#[derive(Clone, Copy)]
2401pub struct Dropdown {
2402 raw: *mut bindings::lv_obj_t,
2403}
2404
2405impl Dropdown {
2406 pub fn create(parent: impl Widget) -> Self {
2408 let raw = unsafe { bindings::lv_dropdown_create(parent.raw()) };
2409 Self { raw }
2410 }
2411
2412 pub fn options(self, opts: &[u8]) -> Self {
2414 unsafe { bindings::lv_dropdown_set_options(self.raw, opts.as_ptr() as *const _) };
2415 self
2416 }
2417
2418 pub fn options_static(self, opts: &'static [u8]) -> Self {
2420 unsafe { bindings::lv_dropdown_set_options_static(self.raw, opts.as_ptr() as *const _) };
2421 self
2422 }
2423
2424 pub fn add_option(self, opt: &[u8], pos: u32) -> Self {
2426 unsafe { bindings::lv_dropdown_add_option(self.raw, opt.as_ptr() as *const _, pos) };
2427 self
2428 }
2429
2430 pub fn clear_options(self) -> Self {
2432 unsafe { bindings::lv_dropdown_clear_options(self.raw) };
2433 self
2434 }
2435
2436 pub fn selected(self, sel: u32) -> Self {
2438 unsafe { bindings::lv_dropdown_set_selected(self.raw, sel) };
2439 self
2440 }
2441
2442 pub fn dir(self, d: bindings::lv_dir_t) -> Self {
2444 unsafe { bindings::lv_dropdown_set_dir(self.raw, d) };
2445 self
2446 }
2447
2448 pub fn get_selected(self) -> u32 {
2450 unsafe { bindings::lv_dropdown_get_selected(self.raw) }
2451 }
2452
2453 pub fn get_option_count(self) -> u32 {
2455 unsafe { bindings::lv_dropdown_get_option_count(self.raw) }
2456 }
2457
2458 pub fn get_selected_str(self, buf: &mut [u8]) {
2460 unsafe {
2461 bindings::lv_dropdown_get_selected_str(
2462 self.raw,
2463 buf.as_mut_ptr() as *mut _,
2464 buf.len() as u32,
2465 );
2466 }
2467 }
2468
2469 pub fn is_open(self) -> bool {
2471 unsafe { bindings::lv_dropdown_is_open(self.raw) }
2472 }
2473
2474 pub fn open(self) {
2476 unsafe { bindings::lv_dropdown_open(self.raw) };
2477 }
2478
2479 pub fn close(self) {
2481 unsafe { bindings::lv_dropdown_close(self.raw) };
2482 }
2483
2484 pub fn symbol(self, symbol: *const core::ffi::c_void) -> Self {
2487 unsafe { bindings::lv_dropdown_set_symbol(self.raw(), symbol) };
2488 self
2489 }
2490
2491 pub fn get_options(self) -> *const core::ffi::c_char {
2494 unsafe { bindings::lv_dropdown_get_options(self.raw()) }
2495 }
2496}
2497
2498impl Widget for Dropdown {
2499 fn raw(self) -> *mut bindings::lv_obj_t {
2500 self.raw
2501 }
2502}
2503
2504impl core::ops::Deref for Dropdown {
2505 type Target = Obj;
2506 fn deref(&self) -> &Obj {
2507 unsafe { &*(self as *const Dropdown as *const Obj) }
2508 }
2509}
2510
2511pub const ROLLER_MODE_NORMAL: u32 = 0;
2513pub const ROLLER_MODE_INFINITE: u32 = 1;
2515
2516#[derive(Clone, Copy)]
2522pub struct Roller {
2523 raw: *mut bindings::lv_obj_t,
2524}
2525
2526impl Roller {
2527 pub fn create(parent: impl Widget) -> Self {
2529 let raw = unsafe { bindings::lv_roller_create(parent.raw()) };
2530 Self { raw }
2531 }
2532
2533 pub fn options(self, opts: &[u8], mode: u32) -> Self {
2536 unsafe { bindings::lv_roller_set_options(self.raw, opts.as_ptr() as *const _, mode as _) };
2537 self
2538 }
2539
2540 pub fn selected(self, sel: u32, anim: bool) -> Self {
2542 unsafe {
2543 #[allow(clippy::unnecessary_cast)]
2544 bindings::lv_roller_set_selected(self.raw, sel, anim as _);
2545 }
2546 self
2547 }
2548
2549 pub fn visible_row_count(self, rows: u32) -> Self {
2551 unsafe { bindings::lv_roller_set_visible_row_count(self.raw, rows) };
2552 self
2553 }
2554
2555 pub fn get_selected(self) -> u32 {
2557 unsafe { bindings::lv_roller_get_selected(self.raw) }
2558 }
2559
2560 pub fn get_option_count(self) -> u32 {
2562 unsafe { bindings::lv_roller_get_option_count(self.raw) }
2563 }
2564
2565 pub fn get_selected_str(self, buf: &mut [u8]) {
2567 unsafe {
2568 bindings::lv_roller_get_selected_str(
2569 self.raw,
2570 buf.as_mut_ptr() as *mut _,
2571 buf.len() as u32,
2572 );
2573 }
2574 }
2575
2576 pub fn get_options(self) -> *const core::ffi::c_char {
2579 unsafe { bindings::lv_roller_get_options(self.raw()) }
2580 }
2581}
2582
2583impl Widget for Roller {
2584 fn raw(self) -> *mut bindings::lv_obj_t {
2585 self.raw
2586 }
2587}
2588
2589impl core::ops::Deref for Roller {
2590 type Target = Obj;
2591 fn deref(&self) -> &Obj {
2592 unsafe { &*(self as *const Roller as *const Obj) }
2593 }
2594}
2595
2596#[derive(Clone, Copy)]
2602pub struct Spinbox {
2603 raw: *mut bindings::lv_obj_t,
2604}
2605
2606impl Spinbox {
2607 pub fn create(parent: impl Widget) -> Self {
2609 let raw = unsafe { bindings::lv_spinbox_create(parent.raw()) };
2610 Self { raw }
2611 }
2612
2613 pub fn value(self, v: i32) -> Self {
2615 unsafe { bindings::lv_spinbox_set_value(self.raw, v) };
2616 self
2617 }
2618
2619 pub fn range(self, min: i32, max: i32) -> Self {
2621 unsafe { bindings::lv_spinbox_set_range(self.raw, min, max) };
2622 self
2623 }
2624
2625 pub fn step(self, s: u32) -> Self {
2627 unsafe { bindings::lv_spinbox_set_step(self.raw, s) };
2628 self
2629 }
2630
2631 pub fn digit_format(self, digit_count: u32, sep_pos: u32) -> Self {
2637 unsafe { bindings::lv_spinbox_set_digit_format(self.raw, digit_count, sep_pos) };
2638 self
2639 }
2640
2641 pub fn rollover(self, on: bool) -> Self {
2643 unsafe { bindings::lv_spinbox_set_rollover(self.raw, on) };
2644 self
2645 }
2646
2647 pub fn cursor_pos(self, pos: u32) -> Self {
2649 unsafe { bindings::lv_spinbox_set_cursor_pos(self.raw, pos) };
2650 self
2651 }
2652
2653 pub fn get_value(self) -> i32 {
2655 unsafe { bindings::lv_spinbox_get_value(self.raw) }
2656 }
2657
2658 pub fn get_step(self) -> i32 {
2660 unsafe { bindings::lv_spinbox_get_step(self.raw) }
2661 }
2662
2663 pub fn increment(self) -> Self {
2665 unsafe { bindings::lv_spinbox_increment(self.raw) };
2666 self
2667 }
2668
2669 pub fn decrement(self) -> Self {
2671 unsafe { bindings::lv_spinbox_decrement(self.raw) };
2672 self
2673 }
2674}
2675
2676impl Widget for Spinbox {
2677 fn raw(self) -> *mut bindings::lv_obj_t {
2678 self.raw
2679 }
2680}
2681
2682impl core::ops::Deref for Spinbox {
2683 type Target = Obj;
2684 fn deref(&self) -> &Obj {
2685 unsafe { &*(self as *const Spinbox as *const Obj) }
2686 }
2687}
2688
2689pub const KEYBOARD_MODE_TEXT_LOWER: u32 = 0;
2691pub const KEYBOARD_MODE_TEXT_UPPER: u32 = 1;
2693pub const KEYBOARD_MODE_SPECIAL: u32 = 2;
2695pub const KEYBOARD_MODE_NUMBER: u32 = 3;
2697
2698#[derive(Clone, Copy)]
2705pub struct Keyboard {
2706 raw: *mut bindings::lv_obj_t,
2707}
2708
2709impl Keyboard {
2710 pub fn create(parent: impl Widget) -> Self {
2712 let raw = unsafe { bindings::lv_keyboard_create(parent.raw()) };
2713 Self { raw }
2714 }
2715
2716 pub fn attach(self, ta: Textarea) -> Self {
2718 unsafe { bindings::lv_keyboard_set_textarea(self.raw, ta.raw) };
2719 self
2720 }
2721
2722 pub fn mode(self, m: u32) -> Self {
2724 unsafe { bindings::lv_keyboard_set_mode(self.raw, m as _) };
2725 self
2726 }
2727
2728 pub fn popovers(self, en: bool) -> Self {
2730 unsafe { bindings::lv_keyboard_set_popovers(self.raw, en) };
2731 self
2732 }
2733
2734 pub fn get_textarea(self) -> Obj {
2737 let raw = unsafe { bindings::lv_keyboard_get_textarea(self.raw()) };
2738 unsafe { Obj::from_raw(raw) }
2739 }
2740}
2741
2742impl Widget for Keyboard {
2743 fn raw(self) -> *mut bindings::lv_obj_t {
2744 self.raw
2745 }
2746}
2747
2748impl core::ops::Deref for Keyboard {
2749 type Target = Obj;
2750 fn deref(&self) -> &Obj {
2751 unsafe { &*(self as *const Keyboard as *const Obj) }
2752 }
2753}
2754
2755#[derive(Clone, Copy)]
2764pub struct Screen {
2765 raw: *mut bindings::lv_obj_t,
2766}
2767
2768impl Screen {
2769 pub fn create() -> Self {
2771 let raw = unsafe { bindings::lv_obj_create(core::ptr::null_mut()) };
2772 Self { raw }
2773 }
2774
2775 pub fn active() -> Self {
2777 let raw = unsafe { bindings::lv_screen_active() };
2778 Self { raw }
2779 }
2780
2781 pub fn load(self) {
2783 unsafe { bindings::lv_screen_load(self.raw) };
2784 }
2785
2786 pub unsafe fn load_anim(
2794 self,
2795 anim: bindings::lv_screen_load_anim_t,
2796 time_ms: u32,
2797 delay_ms: u32,
2798 auto_del: bool,
2799 ) {
2800 unsafe { bindings::lv_screen_load_anim(self.raw, anim, time_ms, delay_ms, auto_del) };
2801 }
2802}
2803
2804impl Widget for Screen {
2805 fn raw(self) -> *mut bindings::lv_obj_t {
2806 self.raw
2807 }
2808}
2809
2810impl core::ops::Deref for Screen {
2811 type Target = Obj;
2812 fn deref(&self) -> &Obj {
2813 unsafe { &*(self as *const Screen as *const Obj) }
2814 }
2815}
2816
2817#[derive(Clone, Copy)]
2827pub struct Image {
2828 raw: *mut bindings::lv_obj_t,
2829}
2830
2831impl Image {
2832 pub fn create(parent: impl Widget) -> Self {
2834 let raw = unsafe { bindings::lv_image_create(parent.raw()) };
2835 Self { raw }
2836 }
2837
2838 #[doc(hidden)]
2848 pub fn src(self, src: *const core::ffi::c_void) -> Self {
2849 unsafe { bindings::lv_image_set_src(self.raw, src) };
2850 self
2851 }
2852
2853 pub fn rotation(self, angle: i32) -> Self {
2855 unsafe { bindings::lv_image_set_rotation(self.raw, angle) };
2856 self
2857 }
2858
2859 pub fn scale(self, zoom: u32) -> Self {
2861 unsafe { bindings::lv_image_set_scale(self.raw, zoom) };
2862 self
2863 }
2864
2865 pub fn pivot(self, x: i32, y: i32) -> Self {
2867 unsafe { bindings::lv_image_set_pivot(self.raw, x, y) };
2868 self
2869 }
2870}
2871
2872impl Widget for Image {
2873 fn raw(self) -> *mut bindings::lv_obj_t {
2874 self.raw
2875 }
2876}
2877
2878impl core::ops::Deref for Image {
2879 type Target = Obj;
2880 fn deref(&self) -> &Obj {
2881 unsafe { &*(self as *const Image as *const Obj) }
2882 }
2883}
2884
2885pub fn vbox(parent: impl Widget) -> Box {
2891 let b = Box::create(parent);
2892 unsafe {
2893 bindings::lv_obj_set_flex_flow(b.raw, bindings::LV_FLEX_FLOW_COLUMN);
2894 bindings::lv_obj_set_size(b.raw, SIZE_CONTENT, SIZE_CONTENT);
2895 }
2896 b
2897}
2898
2899pub fn hbox(parent: impl Widget) -> Box {
2901 let b = Box::create(parent);
2902 unsafe {
2903 bindings::lv_obj_set_flex_flow(b.raw, bindings::LV_FLEX_FLOW_ROW);
2904 bindings::lv_obj_set_size(b.raw, SIZE_CONTENT, SIZE_CONTENT);
2905 }
2906 b
2907}
2908
2909pub struct Group {
2922 raw: *mut bindings::lv_group_t,
2923}
2924
2925impl Group {
2926 pub fn new() -> Self {
2928 let raw = unsafe { bindings::lv_group_create() };
2929 Self { raw }
2930 }
2931
2932 pub fn as_raw(&self) -> *mut bindings::lv_group_t {
2934 self.raw
2935 }
2936
2937 pub fn set_as_default(&self) -> &Self {
2939 unsafe { bindings::lv_group_set_default(self.raw) };
2940 self
2941 }
2942
2943 pub fn add(&self, obj: impl Widget) -> &Self {
2945 unsafe { bindings::lv_group_add_obj(self.raw, obj.raw()) };
2946 self
2947 }
2948
2949 pub fn remove_all(&self) -> &Self {
2951 unsafe { bindings::lv_group_remove_all_objs(self.raw) };
2952 self
2953 }
2954
2955 pub fn focus_next(&self) -> &Self {
2957 unsafe { bindings::lv_group_focus_next(self.raw) };
2958 self
2959 }
2960
2961 pub fn focus_prev(&self) -> &Self {
2963 unsafe { bindings::lv_group_focus_prev(self.raw) };
2964 self
2965 }
2966
2967 pub fn focus_freeze(&self, freeze: bool) -> &Self {
2969 unsafe { bindings::lv_group_focus_freeze(self.raw, freeze) };
2970 self
2971 }
2972
2973 pub fn focused(&self) -> Option<Obj> {
2976 let raw = unsafe { bindings::lv_group_get_focused(self.raw) };
2977 if raw.is_null() {
2978 None
2979 } else {
2980 Some(unsafe { Obj::from_raw(raw) })
2981 }
2982 }
2983
2984 pub fn edit_mode(&self, enable: bool) -> &Self {
2986 unsafe { bindings::lv_group_set_editing(self.raw, enable) };
2987 self
2988 }
2989
2990 pub fn is_editing(&self) -> bool {
2992 unsafe { bindings::lv_group_get_editing(self.raw) }
2993 }
2994
2995 pub fn obj_count(&self) -> u32 {
2997 unsafe { bindings::lv_group_get_obj_count(self.raw) }
2998 }
2999
3000 pub fn focus_obj(obj: impl Widget) {
3002 unsafe { bindings::lv_group_focus_obj(obj.raw()) };
3003 }
3004
3005 pub fn remove_obj(obj: impl Widget) {
3007 unsafe { bindings::lv_group_remove_obj(obj.raw()) };
3008 }
3009}
3010
3011impl Drop for Group {
3012 fn drop(&mut self) {
3013 if !self.raw.is_null() {
3014 unsafe { bindings::lv_group_delete(self.raw) };
3015 }
3016 }
3017}
3018
3019impl Default for Group {
3020 fn default() -> Self {
3021 Self::new()
3022 }
3023}
3024
3025unsafe impl Send for Group {}
3029unsafe impl Sync for Group {}
3030
3031pub struct Timer {
3044 raw: *mut bindings::lv_timer_t,
3045}
3046
3047impl Timer {
3048 pub fn new(
3055 cb: bindings::lv_timer_cb_t,
3056 period_ms: u32,
3057 user_data: *mut core::ffi::c_void,
3058 ) -> Self {
3059 let raw = unsafe { bindings::lv_timer_create(cb, period_ms, user_data) };
3060 Self { raw }
3061 }
3062
3063 pub fn as_raw(&self) -> *mut bindings::lv_timer_t {
3065 self.raw
3066 }
3067
3068 pub fn period(&self, ms: u32) -> &Self {
3070 unsafe { bindings::lv_timer_set_period(self.raw, ms) };
3071 self
3072 }
3073
3074 pub fn pause(&self) -> &Self {
3076 unsafe { bindings::lv_timer_pause(self.raw) };
3077 self
3078 }
3079
3080 pub fn resume(&self) -> &Self {
3082 unsafe { bindings::lv_timer_resume(self.raw) };
3083 self
3084 }
3085
3086 pub fn repeat_count(&self, count: i32) -> &Self {
3088 unsafe { bindings::lv_timer_set_repeat_count(self.raw, count) };
3089 self
3090 }
3091
3092 pub fn reset(&self) -> &Self {
3094 unsafe { bindings::lv_timer_reset(self.raw) };
3095 self
3096 }
3097
3098 pub fn ready(&self) -> &Self {
3100 unsafe { bindings::lv_timer_ready(self.raw) };
3101 self
3102 }
3103}
3104
3105impl Drop for Timer {
3106 fn drop(&mut self) {
3107 if !self.raw.is_null() {
3108 unsafe { bindings::lv_timer_delete(self.raw) };
3109 }
3110 }
3111}
3112
3113unsafe impl Send for Timer {}
3117unsafe impl Sync for Timer {}
3118
3119pub struct State<T: Copy> {
3147 subject: core::cell::UnsafeCell<bindings::lv_subject_t>,
3148 _pin: core::marker::PhantomPinned,
3149 _phantom: core::marker::PhantomData<T>,
3150}
3151
3152impl<T: Copy + Into<i32> + TryFrom<i32>> State<T> {
3153 pub fn new(initial: T) -> Self {
3155 let mut subject: bindings::lv_subject_t = unsafe { core::mem::zeroed() };
3156 unsafe { bindings::lv_subject_init_int(&mut subject, initial.into()) };
3157 Self {
3158 subject: core::cell::UnsafeCell::new(subject),
3159 _pin: core::marker::PhantomPinned,
3160 _phantom: core::marker::PhantomData,
3161 }
3162 }
3163
3164 pub fn set(&self, value: T) {
3170 unsafe {
3171 bindings::lv_subject_set_int(self.subject.get(), value.into());
3172 }
3173 }
3174
3175 pub fn get(&self) -> T {
3179 let raw = unsafe { bindings::lv_subject_get_int(self.subject.get()) };
3180 T::try_from(raw).unwrap_or_else(|_| {
3181 unsafe { core::mem::zeroed() }
3183 })
3184 }
3185
3186 pub fn subject_ptr(&self) -> *mut bindings::lv_subject_t {
3188 self.subject.get()
3189 }
3190}
3191
3192impl<T: Copy> Drop for State<T> {
3193 fn drop(&mut self) {
3194 unsafe { bindings::lv_subject_deinit(self.subject.get()) };
3195 }
3196}
3197
3198unsafe impl<T: Copy + Send> Send for State<T> {}
3202unsafe impl<T: Copy + Send> Sync for State<T> {}
3203
3204impl Label {
3209 pub fn bind_text<T: Copy + Into<i32> + TryFrom<i32>>(
3214 self,
3215 state: &State<T>,
3216 fmt: &'static [u8],
3217 ) -> Self {
3218 unsafe {
3219 bindings::lv_label_bind_text(self.raw(), state.subject_ptr(), fmt.as_ptr() as *const _);
3220 }
3221 self
3222 }
3223}
3224
3225impl Arc {
3226 pub fn bind_value<T: Copy + Into<i32> + TryFrom<i32>>(self, state: &State<T>) -> Self {
3228 unsafe { bindings::lv_arc_bind_value(self.raw(), state.subject_ptr()) };
3229 self
3230 }
3231}
3232
3233impl Slider {
3234 pub fn bind_value<T: Copy + Into<i32> + TryFrom<i32>>(self, state: &State<T>) -> Self {
3236 unsafe { bindings::lv_slider_bind_value(self.raw(), state.subject_ptr()) };
3237 self
3238 }
3239}
3240
3241impl Roller {
3242 pub fn bind_value<T: Copy + Into<i32> + TryFrom<i32>>(self, state: &State<T>) -> Self {
3244 unsafe { bindings::lv_roller_bind_value(self.raw(), state.subject_ptr()) };
3245 self
3246 }
3247}
3248
3249impl Dropdown {
3250 pub fn bind_value<T: Copy + Into<i32> + TryFrom<i32>>(self, state: &State<T>) -> Self {
3252 unsafe { bindings::lv_dropdown_bind_value(self.raw(), state.subject_ptr()) };
3253 self
3254 }
3255}
3256
3257pub unsafe fn component_from_event(e: *mut bindings::lv_event_t) -> *mut core::ffi::c_void {
3274 unsafe {
3275 let mut target = bindings::lv_event_get_target(e) as *mut bindings::lv_obj_t;
3279 while !target.is_null() {
3280 let ud = bindings::lv_obj_get_user_data(target);
3281 if !ud.is_null() {
3282 return ud;
3283 }
3284 target = bindings::lv_obj_get_parent(target);
3285 }
3286 core::ptr::null_mut()
3287 }
3288}
3289
3290pub const ANIM_REPEAT_INFINITE: u32 = 0xFFFF_FFFF;
3296
3297pub struct Animation {
3309 inner: bindings::lv_anim_t,
3310}
3311
3312impl Animation {
3313 pub fn new() -> Self {
3315 let mut a: bindings::lv_anim_t = unsafe { core::mem::zeroed() };
3316 unsafe { bindings::lv_anim_init(&mut a) };
3317 Self { inner: a }
3318 }
3319
3320 pub fn target(mut self, var: *mut core::ffi::c_void) -> Self {
3322 unsafe { bindings::lv_anim_set_var(&mut self.inner, var) };
3323 self
3324 }
3325
3326 pub fn values(mut self, from: i32, to: i32) -> Self {
3328 unsafe { bindings::lv_anim_set_values(&mut self.inner, from, to) };
3329 self
3330 }
3331
3332 pub fn duration(mut self, ms: u32) -> Self {
3334 unsafe { bindings::lv_anim_set_duration(&mut self.inner, ms) };
3335 self
3336 }
3337
3338 pub fn delay(mut self, ms: u32) -> Self {
3340 unsafe { bindings::lv_anim_set_delay(&mut self.inner, ms) };
3341 self
3342 }
3343
3344 pub fn path(mut self, cb: bindings::lv_anim_path_cb_t) -> Self {
3346 unsafe { bindings::lv_anim_set_path_cb(&mut self.inner, cb) };
3347 self
3348 }
3349
3350 pub fn repeat_count(mut self, count: u32) -> Self {
3352 unsafe { bindings::lv_anim_set_repeat_count(&mut self.inner, count) };
3353 self
3354 }
3355
3356 pub fn repeat_delay(mut self, ms: u32) -> Self {
3358 unsafe { bindings::lv_anim_set_repeat_delay(&mut self.inner, ms) };
3359 self
3360 }
3361
3362 pub fn playback_duration(mut self, ms: u32) -> Self {
3364 unsafe { bindings::lv_anim_set_reverse_duration(&mut self.inner, ms) };
3365 self
3366 }
3367
3368 pub fn playback_delay(mut self, ms: u32) -> Self {
3370 unsafe { bindings::lv_anim_set_reverse_delay(&mut self.inner, ms) };
3371 self
3372 }
3373
3374 pub fn exec_cb(mut self, cb: bindings::lv_anim_exec_xcb_t) -> Self {
3376 unsafe { bindings::lv_anim_set_exec_cb(&mut self.inner, cb) };
3377 self
3378 }
3379
3380 pub fn completed_cb(mut self, cb: bindings::lv_anim_completed_cb_t) -> Self {
3382 unsafe { bindings::lv_anim_set_completed_cb(&mut self.inner, cb) };
3383 self
3384 }
3385
3386 pub fn start(self) {
3389 unsafe { bindings::lv_anim_start(&self.inner) };
3390 }
3391
3392 pub fn stop(var: *mut core::ffi::c_void, exec_cb: bindings::lv_anim_exec_xcb_t) -> bool {
3394 unsafe { bindings::lv_anim_delete(var, exec_cb) }
3395 }
3396}
3397
3398impl Default for Animation {
3399 fn default() -> Self {
3400 Self::new()
3401 }
3402}
3403
3404pub fn path_linear() -> bindings::lv_anim_path_cb_t {
3406 Some(bindings::lv_anim_path_linear)
3407}
3408
3409pub fn path_ease_in() -> bindings::lv_anim_path_cb_t {
3411 Some(bindings::lv_anim_path_ease_in)
3412}
3413
3414pub fn path_ease_out() -> bindings::lv_anim_path_cb_t {
3416 Some(bindings::lv_anim_path_ease_out)
3417}
3418
3419pub fn path_ease_in_out() -> bindings::lv_anim_path_cb_t {
3421 Some(bindings::lv_anim_path_ease_in_out)
3422}
3423
3424pub fn path_overshoot() -> bindings::lv_anim_path_cb_t {
3426 Some(bindings::lv_anim_path_overshoot)
3427}
3428
3429pub fn path_bounce() -> bindings::lv_anim_path_cb_t {
3431 Some(bindings::lv_anim_path_bounce)
3432}
3433
3434pub fn path_step() -> bindings::lv_anim_path_cb_t {
3436 Some(bindings::lv_anim_path_step)
3437}
3438
3439unsafe extern "C" fn anim_set_x_shim(var: *mut core::ffi::c_void, v: i32) {
3442 unsafe { bindings::lv_obj_set_x(var as *mut bindings::lv_obj_t, v) };
3443}
3444
3445unsafe extern "C" fn anim_set_y_shim(var: *mut core::ffi::c_void, v: i32) {
3446 unsafe { bindings::lv_obj_set_y(var as *mut bindings::lv_obj_t, v) };
3447}
3448
3449unsafe extern "C" fn anim_set_width_shim(var: *mut core::ffi::c_void, v: i32) {
3450 unsafe { bindings::lv_obj_set_width(var as *mut bindings::lv_obj_t, v) };
3451}
3452
3453unsafe extern "C" fn anim_set_opa_shim(var: *mut core::ffi::c_void, v: i32) {
3454 unsafe { bindings::lv_obj_set_style_opa(var as *mut bindings::lv_obj_t, v as u8, PART_MAIN) };
3455}
3456
3457pub fn animate_x(obj: impl Widget, to: i32, duration_ms: u32) {
3459 let from = unsafe { bindings::lv_obj_get_x(obj.raw()) };
3460 Animation::new()
3461 .target(obj.raw() as *mut _)
3462 .values(from, to)
3463 .duration(duration_ms)
3464 .path(path_ease_out())
3465 .exec_cb(Some(anim_set_x_shim))
3466 .start();
3467}
3468
3469pub fn animate_y(obj: impl Widget, to: i32, duration_ms: u32) {
3471 let from = unsafe { bindings::lv_obj_get_y(obj.raw()) };
3472 Animation::new()
3473 .target(obj.raw() as *mut _)
3474 .values(from, to)
3475 .duration(duration_ms)
3476 .path(path_ease_out())
3477 .exec_cb(Some(anim_set_y_shim))
3478 .start();
3479}
3480
3481pub fn animate_width(obj: impl Widget, to: i32, duration_ms: u32) {
3483 let from = unsafe { bindings::lv_obj_get_width(obj.raw()) };
3484 Animation::new()
3485 .target(obj.raw() as *mut _)
3486 .values(from, to)
3487 .duration(duration_ms)
3488 .path(path_ease_out())
3489 .exec_cb(Some(anim_set_width_shim))
3490 .start();
3491}
3492
3493pub fn animate_opa(obj: impl Widget, from: u8, to: u8, duration_ms: u32) {
3499 Animation::new()
3500 .target(obj.raw() as *mut _)
3501 .values(from as i32, to as i32)
3502 .duration(duration_ms)
3503 .path(path_ease_in_out())
3504 .exec_cb(Some(anim_set_opa_shim))
3505 .start();
3506}
3507
3508pub struct Style {
3514 inner: bindings::lv_style_t,
3515}
3516
3517impl Default for Style {
3518 fn default() -> Self {
3519 Self::new()
3520 }
3521}
3522
3523impl Style {
3524 pub fn new() -> Self {
3526 let mut s = Self {
3527 inner: unsafe { core::mem::zeroed() },
3528 };
3529 unsafe { bindings::lv_style_init(&mut s.inner) };
3530 s
3531 }
3532
3533 pub fn as_mut_ptr(&mut self) -> *mut bindings::lv_style_t {
3535 &mut self.inner
3536 }
3537
3538 pub fn ptr(&self) -> *mut bindings::lv_style_t {
3543 &self.inner as *const _ as *mut _
3544 }
3545
3546 pub fn arc_color(mut self, c: Color) -> Self {
3548 unsafe { bindings::lv_style_set_arc_color(&mut self.inner, c.to_raw()) };
3549 self
3550 }
3551
3552 pub fn arc_width(mut self, w: i32) -> Self {
3554 unsafe { bindings::lv_style_set_arc_width(&mut self.inner, w) };
3555 self
3556 }
3557
3558 pub fn bg_color(mut self, c: Color) -> Self {
3560 unsafe { bindings::lv_style_set_bg_color(&mut self.inner, c.to_raw()) };
3561 self
3562 }
3563
3564 pub fn bg_opa(mut self, opa: u8) -> Self {
3566 unsafe { bindings::lv_style_set_bg_opa(&mut self.inner, opa) };
3567 self
3568 }
3569
3570 pub fn radius(mut self, r: i32) -> Self {
3572 unsafe { bindings::lv_style_set_radius(&mut self.inner, r) };
3573 self
3574 }
3575
3576 pub fn border_color(mut self, c: Color) -> Self {
3578 unsafe { bindings::lv_style_set_border_color(&mut self.inner, c.to_raw()) };
3579 self
3580 }
3581
3582 pub fn border_width(mut self, w: i32) -> Self {
3584 unsafe { bindings::lv_style_set_border_width(&mut self.inner, w) };
3585 self
3586 }
3587
3588 pub fn pad_all(mut self, p: i32) -> Self {
3590 unsafe {
3591 let s = &mut self.inner;
3592 bindings::lv_style_set_pad_left(s, p);
3593 bindings::lv_style_set_pad_right(s, p);
3594 bindings::lv_style_set_pad_top(s, p);
3595 bindings::lv_style_set_pad_bottom(s, p);
3596 }
3597 self
3598 }
3599
3600 pub fn text_color(mut self, c: Color) -> Self {
3602 unsafe { bindings::lv_style_set_text_color(&mut self.inner, c.to_raw()) };
3603 self
3604 }
3605
3606 pub fn text_font(mut self, f: *const bindings::lv_font_t) -> Self {
3608 unsafe { bindings::lv_style_set_text_font(&mut self.inner, f) };
3609 self
3610 }
3611}
3612
3613unsafe impl Send for Style {}
3615unsafe impl Sync for Style {}
3616
3617impl Drop for Style {
3618 fn drop(&mut self) {
3619 unsafe { bindings::lv_style_reset(&mut self.inner) };
3620 }
3621}
3622
3623unsafe impl Send for Obj {}
3640unsafe impl Sync for Obj {}
3641unsafe impl Send for Label {}
3642unsafe impl Sync for Label {}
3643unsafe impl Send for Bar {}
3644unsafe impl Sync for Bar {}
3645unsafe impl Send for Box {}
3646unsafe impl Sync for Box {}
3647unsafe impl Send for Button {}
3648unsafe impl Sync for Button {}
3649unsafe impl Send for Slider {}
3650unsafe impl Sync for Slider {}
3651unsafe impl Send for Switch {}
3652unsafe impl Sync for Switch {}
3653unsafe impl Send for Checkbox {}
3654unsafe impl Sync for Checkbox {}
3655unsafe impl Send for Arc {}
3656unsafe impl Sync for Arc {}
3657unsafe impl Send for Image {}
3658unsafe impl Sync for Image {}
3659unsafe impl Send for Screen {}
3660unsafe impl Sync for Screen {}
3661unsafe impl Send for Msgbox {}
3662unsafe impl Sync for Msgbox {}
3663unsafe impl Send for Spinner {}
3664unsafe impl Sync for Spinner {}
3665unsafe impl Send for Led {}
3666unsafe impl Sync for Led {}
3667unsafe impl Send for Textarea {}
3668unsafe impl Sync for Textarea {}
3669unsafe impl Send for Dropdown {}
3670unsafe impl Sync for Dropdown {}
3671unsafe impl Send for Roller {}
3672unsafe impl Sync for Roller {}
3673unsafe impl Send for Spinbox {}
3674unsafe impl Sync for Spinbox {}
3675unsafe impl Send for Keyboard {}
3676unsafe impl Sync for Keyboard {}
3677unsafe impl Send for Chart {}
3678unsafe impl Sync for Chart {}
3679unsafe impl Send for Table {}
3680unsafe impl Sync for Table {}
3681unsafe impl Send for Tabview {}
3682unsafe impl Sync for Tabview {}
3683unsafe impl Send for List {}
3684unsafe impl Sync for List {}
3685unsafe impl Send for Canvas {}
3686unsafe impl Sync for Canvas {}
3687unsafe impl Send for Calendar {}
3688unsafe impl Sync for Calendar {}
3689
3690pub struct LvglGuard(());
3696
3697impl Drop for LvglGuard {
3698 fn drop(&mut self) {
3699 unsafe { bindings::ove_lvgl_unlock() };
3700 }
3701}
3702
3703pub fn init() -> Result<()> {
3709 let ret = unsafe { bindings::ove_lvgl_init() };
3710 Error::from_code(ret)
3711}
3712
3713pub fn tick(ms: u32) {
3715 unsafe { bindings::ove_lvgl_tick(ms) };
3716}
3717
3718pub fn handler() {
3720 unsafe { bindings::ove_lvgl_handler() };
3721}
3722
3723pub fn lock() -> LvglGuard {
3725 unsafe { bindings::ove_lvgl_lock() };
3726 LvglGuard(())
3727}
3728
3729pub fn screen_active() -> Obj {
3731 let raw = unsafe { bindings::lv_screen_active() };
3732 unsafe { Obj::from_raw(raw) }
3733}
3734
3735pub mod display {
3741 use super::bindings;
3742
3743 pub fn width() -> i32 {
3745 unsafe { bindings::lv_display_get_horizontal_resolution(core::ptr::null_mut()) }
3746 }
3747
3748 pub fn height() -> i32 {
3750 unsafe { bindings::lv_display_get_vertical_resolution(core::ptr::null_mut()) }
3751 }
3752
3753 pub fn dpi() -> i32 {
3755 unsafe { bindings::lv_display_get_dpi(core::ptr::null_mut()) }
3756 }
3757}
3758
3759pub fn layer_top() -> Obj {
3765 let raw = unsafe { bindings::lv_layer_top() };
3766 unsafe { Obj::from_raw(raw) }
3767}
3768
3769pub fn text_size(text: &[u8], font: *const bindings::lv_font_t) -> (i32, i32) {
3778 debug_assert!(
3779 text.last() == Some(&0),
3780 "text_size: text must be NUL-terminated"
3781 );
3782 let mut p = bindings::lv_point_t { x: 0, y: 0 };
3783 unsafe {
3784 bindings::lv_text_get_size(&mut p, text.as_ptr() as *const _, font, 0, 0, i32::MAX, 0);
3785 }
3786 (p.x, p.y)
3787}
3788
3789impl Animation {
3794 pub fn duration_for_speed(speed: u32) -> u32 {
3797 unsafe { bindings::lv_anim_speed(speed) }
3798 }
3799
3800 pub fn tick_fn<W: Widget>(mut self, obj: W, on_tick: fn(Obj, i32)) -> Self {
3806 unsafe {
3807 bindings::lv_anim_set_var(&mut self.inner, obj.raw() as *mut _);
3808 bindings::lv_anim_set_user_data(&mut self.inner, on_tick as *mut _);
3809 bindings::lv_anim_set_custom_exec_cb(
3810 &mut self.inner,
3811 Some(anim_custom_tick_trampoline),
3812 );
3813 }
3814 self
3815 }
3816}
3817
3818unsafe extern "C" fn anim_custom_tick_trampoline(a: *mut bindings::lv_anim_t, v: i32) {
3819 unsafe {
3820 let ud = bindings::lv_anim_get_user_data(a);
3821 if ud.is_null() {
3822 return;
3823 }
3824 let cb: fn(Obj, i32) = core::mem::transmute(ud);
3828 let var = (*a).var;
3829 cb(
3830 Obj {
3831 raw: var as *mut bindings::lv_obj_t,
3832 },
3833 v,
3834 );
3835 }
3836}
3837
3838unsafe extern "C" fn anim_translate_y_shim(var: *mut core::ffi::c_void, v: i32) {
3840 unsafe {
3841 bindings::lv_obj_set_style_translate_y(var as *mut bindings::lv_obj_t, v, PART_MAIN);
3842 }
3843}
3844
3845unsafe extern "C" fn anim_scroll_y_shim(var: *mut core::ffi::c_void, v: i32) {
3846 unsafe {
3847 bindings::lv_obj_scroll_to_y(var as *mut bindings::lv_obj_t, v, false);
3848 }
3849}
3850
3851unsafe extern "C" fn anim_arc_value_shim(var: *mut core::ffi::c_void, v: i32) {
3852 unsafe {
3853 bindings::lv_arc_set_value(var as *mut bindings::lv_obj_t, v);
3854 }
3855}
3856
3857pub fn animate_translate_y(obj: impl Widget, from: i32, to: i32, duration_ms: u32) {
3860 Animation::new()
3861 .target(obj.raw() as *mut _)
3862 .values(from, to)
3863 .duration(duration_ms)
3864 .path(path_ease_in_out())
3865 .exec_cb(Some(anim_translate_y_shim))
3866 .start();
3867}
3868
3869pub fn animate_scroll_y(obj: impl Widget, from: i32, to: i32, duration_ms: u32) {
3871 Animation::new()
3872 .target(obj.raw() as *mut _)
3873 .values(from, to)
3874 .duration(duration_ms)
3875 .path(path_linear())
3876 .exec_cb(Some(anim_scroll_y_shim))
3877 .start();
3878}
3879
3880pub fn animate_arc_value(arc: Arc, from: i32, to: i32, duration_ms: u32) {
3882 Animation::new()
3883 .target(arc.raw() as *mut _)
3884 .values(from, to)
3885 .duration(duration_ms)
3886 .path(path_ease_in_out())
3887 .exec_cb(Some(anim_arc_value_shim))
3888 .start();
3889}
3890
3891pub fn animate_translate_y_playback(
3894 obj: impl Widget,
3895 from: i32,
3896 to: i32,
3897 forward_ms: u32,
3898 playback_ms: u32,
3899) {
3900 Animation::new()
3901 .target(obj.raw() as *mut _)
3902 .values(from, to)
3903 .duration(forward_ms)
3904 .playback_duration(playback_ms)
3905 .path(path_ease_in_out())
3906 .exec_cb(Some(anim_translate_y_shim))
3907 .repeat_count(ANIM_REPEAT_INFINITE)
3908 .start();
3909}
3910
3911pub fn animate_scroll_y_playback(
3913 obj: impl Widget,
3914 from: i32,
3915 to: i32,
3916 forward_ms: u32,
3917 playback_ms: u32,
3918) {
3919 Animation::new()
3920 .target(obj.raw() as *mut _)
3921 .values(from, to)
3922 .duration(forward_ms)
3923 .playback_duration(playback_ms)
3924 .path(path_linear())
3925 .exec_cb(Some(anim_scroll_y_shim))
3926 .repeat_count(ANIM_REPEAT_INFINITE)
3927 .start();
3928}
3929
3930pub fn animate_arc_value_playback(arc: Arc, from: i32, to: i32, forward_ms: u32, playback_ms: u32) {
3932 Animation::new()
3933 .target(arc.raw() as *mut _)
3934 .values(from, to)
3935 .duration(forward_ms)
3936 .playback_duration(playback_ms)
3937 .path(path_ease_in_out())
3938 .exec_cb(Some(anim_arc_value_shim))
3939 .repeat_count(ANIM_REPEAT_INFINITE)
3940 .start();
3941}
3942
3943pub fn stop_animations(obj: impl Widget) {
3947 unsafe {
3948 bindings::lv_anim_delete(obj.raw() as *mut _, None);
3949 }
3950}
3951
3952pub use crate::cell::{LvCell, LvRefCell};
3957
3958#[derive(Clone, Copy)]
3969pub struct ImageSrc {
3970 raw: *const core::ffi::c_void,
3971}
3972
3973unsafe impl Send for ImageSrc {}
3975unsafe impl Sync for ImageSrc {}
3976
3977impl ImageSrc {
3978 pub fn from_dsc(dsc: *const ImageDsc) -> Self {
3984 Self {
3985 raw: dsc as *const _,
3986 }
3987 }
3988
3989 pub fn from_symbol(sym: &'static [u8]) -> Self {
3991 debug_assert!(sym.last() == Some(&0), "ImageSrc::from_symbol: missing NUL");
3992 Self {
3993 raw: sym.as_ptr() as *const _,
3994 }
3995 }
3996
3997 pub fn from_path(path: &'static [u8]) -> Self {
3999 debug_assert!(path.last() == Some(&0), "ImageSrc::from_path: missing NUL");
4000 Self {
4001 raw: path.as_ptr() as *const _,
4002 }
4003 }
4004
4005 pub(crate) fn raw_ptr(self) -> *const core::ffi::c_void {
4006 self.raw
4007 }
4008}
4009
4010pub type ImageDsc = bindings::lv_image_dsc_t;
4014
4015impl Image {
4016 pub fn source(self, src: ImageSrc) -> Self {
4019 unsafe { bindings::lv_image_set_src(self.raw, src.raw) };
4020 self
4021 }
4022
4023 pub fn inner_align(self, align: u32) -> Self {
4025 unsafe { bindings::lv_image_set_inner_align(self.raw, align as _) };
4026 self
4027 }
4028}
4029
4030#[derive(Clone, Copy)]
4036pub struct ColorFormat(pub bindings::lv_color_format_t);
4037
4038impl ColorFormat {
4039 pub const I1: Self = Self(0x07);
4040 pub const A8: Self = Self(0x0E);
4041 pub const RGB565: Self = Self(0x12);
4042 pub const RGB888: Self = Self(0x0F);
4043 pub const ARGB8888: Self = Self(0x10);
4044 pub const XRGB8888: Self = Self(0x11);
4045
4046 pub const fn bpp(self) -> Option<usize> {
4059 match self.0 {
4060 0x10 | 0x11 => Some(4), 0x0F => Some(3), 0x12 => Some(2), 0x0E => Some(1), 0x07 => Some(0), _ => None,
4066 }
4067 }
4068}
4069
4070pub struct CanvasBuffer<'a> {
4072 ptr: *mut u8,
4073 w: i32,
4074 h: i32,
4075 cf: ColorFormat,
4076 _ph: core::marker::PhantomData<&'a mut [u8]>,
4077}
4078
4079impl<'a> CanvasBuffer<'a> {
4080 pub fn new(buf: &'a mut [u8], w: i32, h: i32, cf: ColorFormat) -> Self {
4088 let bpp = cf.bpp().expect("CanvasBuffer: unknown ColorFormat");
4089 let need = (w as usize) * (h as usize) * bpp;
4090 assert!(
4091 buf.len() == need,
4092 "CanvasBuffer: expected {} bytes, got {}",
4093 need,
4094 buf.len()
4095 );
4096 Self {
4097 ptr: buf.as_mut_ptr(),
4098 w,
4099 h,
4100 cf,
4101 _ph: core::marker::PhantomData,
4102 }
4103 }
4104}
4105
4106impl Canvas {
4107 pub fn set_buffer(self, buf: CanvasBuffer<'_>) -> Self {
4111 unsafe {
4112 bindings::lv_canvas_set_buffer(self.raw, buf.ptr as *mut _, buf.w, buf.h, buf.cf.0);
4113 }
4114 self
4115 }
4116}
4117
4118pub const SCALE_MODE_HORIZONTAL_TOP: u32 = 0x00;
4124pub const SCALE_MODE_HORIZONTAL_BOTTOM: u32 = 0x01;
4125pub const SCALE_MODE_VERTICAL_LEFT: u32 = 0x02;
4126pub const SCALE_MODE_VERTICAL_RIGHT: u32 = 0x04;
4127pub const SCALE_MODE_ROUND_INNER: u32 = 0x08;
4128pub const SCALE_MODE_ROUND_OUTER: u32 = 0x10;
4129
4130#[derive(Clone, Copy)]
4132pub struct Scale {
4133 raw: *mut bindings::lv_obj_t,
4134}
4135
4136#[derive(Clone, Copy)]
4138pub struct ScaleSection {
4139 raw: *mut bindings::lv_scale_section_t,
4140}
4141
4142impl Scale {
4143 pub fn create(parent: impl Widget) -> Self {
4145 let raw = unsafe { bindings::lv_scale_create(parent.raw()) };
4146 Self { raw }
4147 }
4148
4149 pub fn mode(self, mode: u32) -> Self {
4151 unsafe { bindings::lv_scale_set_mode(self.raw, mode as _) };
4152 self
4153 }
4154
4155 pub fn range(self, min: i32, max: i32) -> Self {
4157 unsafe { bindings::lv_scale_set_range(self.raw, min, max) };
4158 self
4159 }
4160
4161 pub fn total_tick_count(self, count: u32) -> Self {
4163 unsafe { bindings::lv_scale_set_total_tick_count(self.raw, count) };
4164 self
4165 }
4166
4167 pub fn major_tick_every(self, nth: u32) -> Self {
4169 unsafe { bindings::lv_scale_set_major_tick_every(self.raw, nth) };
4170 self
4171 }
4172
4173 pub fn angle_range(self, angle: u32) -> Self {
4175 unsafe { bindings::lv_scale_set_angle_range(self.raw, angle) };
4176 self
4177 }
4178
4179 pub fn rotation(self, rot: i32) -> Self {
4181 unsafe { bindings::lv_scale_set_rotation(self.raw, rot as _) };
4182 self
4183 }
4184
4185 pub fn add_section(self) -> ScaleSection {
4187 let raw = unsafe { bindings::lv_scale_add_section(self.raw) };
4188 ScaleSection { raw }
4189 }
4190}
4191
4192impl ScaleSection {
4193 pub fn range(self, min: i32, max: i32) -> Self {
4195 unsafe { bindings::lv_scale_section_set_range(self.raw, min, max) };
4196 self
4197 }
4198
4199 pub fn style(self, part: u32, style: &Style) -> Self {
4204 unsafe { bindings::lv_scale_section_set_style(self.raw, part, style.ptr()) };
4205 self
4206 }
4207}
4208
4209impl Widget for Scale {
4210 fn raw(self) -> *mut bindings::lv_obj_t {
4211 self.raw
4212 }
4213}
4214
4215impl core::ops::Deref for Scale {
4216 type Target = Obj;
4217 fn deref(&self) -> &Obj {
4218 unsafe { &*(self as *const Scale as *const Obj) }
4219 }
4220}
4221
4222unsafe impl Send for Scale {}
4225unsafe impl Sync for Scale {}
4226
4227unsafe extern "C" fn lvgl_timer_trampoline_fn(t: *mut bindings::lv_timer_t) {
4232 let ud = unsafe { bindings::lv_timer_get_user_data(t) };
4233 if ud.is_null() {
4234 return;
4235 }
4236 let cb: fn() = unsafe { core::mem::transmute(ud) };
4238 cb();
4239}
4240
4241impl Timer {
4242 pub fn new_fn(callback: fn(), period_ms: u32) -> Self {
4247 let ud = callback as *mut core::ffi::c_void;
4248 let raw =
4249 unsafe { bindings::lv_timer_create(Some(lvgl_timer_trampoline_fn), period_ms, ud) };
4250 Self { raw }
4251 }
4252}
4253
4254impl<T: Copy + Into<i32> + TryFrom<i32>> State<T> {
4259 pub fn observe(&self, obj: impl Widget) {
4263 unsafe {
4264 bindings::lv_subject_add_observer_obj(
4265 self.subject_ptr(),
4266 None,
4267 obj.raw(),
4268 core::ptr::null_mut(),
4269 );
4270 }
4271 }
4272}