|
32 | 32 | foreground_app_name=None |
33 | 33 |
|
34 | 34 |
|
| 35 | + lass WidgetAnimator: |
| 36 | + def __init__(self): |
| 37 | + self.animations = {} # Store animations for each widget |
| 38 | + |
| 39 | + # show_widget and hide_widget could have a (lambda) callback that sets the final state (eg: drawer_open) at the end |
| 40 | + |
| 41 | + def show_widget(self, widget, anim_type="fade", duration=500, delay=0): |
| 42 | + """Show a widget with an animation (fade or slide).""" |
| 43 | + # Clear HIDDEN flag to make widget visible for animation |
| 44 | + widget.remove_flag(lv.obj.FLAG.HIDDEN) |
| 45 | + |
| 46 | + if anim_type == "fade": |
| 47 | + # Create fade-in animation (opacity from 0 to 255) |
| 48 | + anim = lv.anim_t() |
| 49 | + anim.init() |
| 50 | + anim.set_var(widget) |
| 51 | + anim.set_values(0, 255) |
| 52 | + anim.set_time(duration) |
| 53 | + anim.set_delay(delay) |
| 54 | + anim.set_custom_exec_cb(lambda anim, value: widget.set_style_opacity(value, 0)) |
| 55 | + anim.set_path_cb(lv.anim_t.path_ease_in_out) |
| 56 | + # Ensure opacity is reset after animation |
| 57 | + anim.set_completed_cb(lambda *args: widget.set_style_opacity(255, 0)) |
| 58 | + elif anim_type == "slide_down": |
| 59 | + print("doing slide_down") |
| 60 | + # Create slide-down animation (y from -height to original y) |
| 61 | + original_y = widget.get_y() |
| 62 | + height = widget.get_height() |
| 63 | + anim = lv.anim_t() |
| 64 | + anim.init() |
| 65 | + anim.set_var(widget) |
| 66 | + anim.set_values(original_y - height, original_y) |
| 67 | + anim.set_time(duration) |
| 68 | + anim.set_delay(delay) |
| 69 | + anim.set_custom_exec_cb(lambda anim, value: widget.set_y(value)) |
| 70 | + anim.set_path_cb(lv.anim_t.path_ease_in_out) |
| 71 | + # Reset y position after animation |
| 72 | + anim.set_completed_cb(lambda *args: widget.set_y(original_y)) |
| 73 | + elif anim_type == "slide_up": |
| 74 | + # Create slide-up animation (y from +height to original y) |
| 75 | + original_y = widget.get_y() |
| 76 | + height = widget.get_height() |
| 77 | + anim = lv.anim_t() |
| 78 | + anim.init() |
| 79 | + anim.set_var(widget) |
| 80 | + anim.set_values(original_y + height, original_y) |
| 81 | + anim.set_time(duration) |
| 82 | + anim.set_delay(delay) |
| 83 | + anim.set_custom_exec_cb(lambda anim, value: widget.set_y(value)) |
| 84 | + anim.set_path_cb(lv.anim_t.path_ease_in_out) |
| 85 | + # Reset y position after animation |
| 86 | + anim.set_completed_cb(lambda *args: widget.set_y(original_y)) |
| 87 | + |
| 88 | + # Store and start animation |
| 89 | + self.animations[widget] = anim |
| 90 | + anim.start() |
| 91 | + |
| 92 | + def hide_widget(self, widget, anim_type="fade", duration=500, delay=0): |
| 93 | + """Hide a widget with an animation (fade or slide).""" |
| 94 | + if anim_type == "fade": |
| 95 | + # Create fade-out animation (opacity from 255 to 0) |
| 96 | + anim = lv.anim_t() |
| 97 | + anim.init() |
| 98 | + anim.set_var(widget) |
| 99 | + anim.set_values(255, 0) |
| 100 | + anim.set_time(duration) |
| 101 | + anim.set_delay(delay) |
| 102 | + anim.set_custom_exec_cb(lambda anim, value: widget.set_style_opacity(value, 0)) |
| 103 | + anim.set_path_cb(lv.anim_t.path_ease_in_out) |
| 104 | + # Set HIDDEN flag after animation |
| 105 | + anim.set_completed_cb(lambda *args: self.hide_complete_cb(widget, original_y)) |
| 106 | + elif anim_type == "slide_down": |
| 107 | + # Create slide-down animation (y from original y to +height) |
| 108 | + original_y = widget.get_y() |
| 109 | + height = widget.get_height() |
| 110 | + anim = lv.anim_t() |
| 111 | + anim.init() |
| 112 | + anim.set_var(widget) |
| 113 | + anim.set_values(original_y, original_y + height) |
| 114 | + anim.set_time(duration) |
| 115 | + anim.set_delay(delay) |
| 116 | + anim.set_custom_exec_cb(lambda anim, value: widget.set_y(value)) |
| 117 | + anim.set_path_cb(lv.anim_t.path_ease_in_out) |
| 118 | + # Set HIDDEN flag after animation |
| 119 | + anim.set_completed_cb(lambda *args: self.hide_complete_cb(widget, original_y)) |
| 120 | + elif anim_type == "slide_up": |
| 121 | + print("hide with slide_up") |
| 122 | + # Create slide-up animation (y from original y to -height) |
| 123 | + original_y = widget.get_y() |
| 124 | + height = widget.get_height() |
| 125 | + anim = lv.anim_t() |
| 126 | + anim.init() |
| 127 | + anim.set_var(widget) |
| 128 | + anim.set_values(original_y, original_y - height) |
| 129 | + anim.set_time(duration) |
| 130 | + anim.set_delay(delay) |
| 131 | + anim.set_custom_exec_cb(lambda anim, value: widget.set_y(value)) |
| 132 | + anim.set_path_cb(lv.anim_t.path_ease_in_out) |
| 133 | + # Set HIDDEN flag after animation |
| 134 | + anim.set_completed_cb(lambda *args: self.hide_complete_cb(widget, original_y)) |
| 135 | + |
| 136 | + # Store and start animation |
| 137 | + self.animations[widget] = anim |
| 138 | + anim.start() |
| 139 | + |
| 140 | + def hide_complete_cb(self, widget, original_y): |
| 141 | + #print("hide_complete_cb") |
| 142 | + widget.add_flag(lv.obj.FLAG.HIDDEN) |
| 143 | + widget.set_y(original_y) |
| 144 | + |
| 145 | + |
| 146 | + def stop_animation(self, widget): |
| 147 | + """Stop any running animation for the widget.""" |
| 148 | + if widget in self.animations: |
| 149 | + self.animations[widget].delete() |
| 150 | + del self.animations[widget] |
| 151 | + |
| 152 | +animator = WidgetAnimator() |
| 153 | + |
35 | 154 | def get_pointer_xy(): |
36 | 155 | indev = lv.indev_active() |
37 | 156 | if indev: |
@@ -76,13 +195,13 @@ def open_drawer(): |
76 | 195 | if not drawer_open: |
77 | 196 | open_bar() |
78 | 197 | drawer_open=True |
79 | | - drawer.remove_flag(lv.obj.FLAG.HIDDEN) |
| 198 | + animator.show_widget(drawer, anim_type="slide_down", duration=1000, delay=0) |
80 | 199 |
|
81 | 200 | def close_drawer(to_launcher=False): |
82 | 201 | global drawer_open, drawer, foreground_app_name |
83 | 202 | if drawer_open: |
84 | 203 | drawer_open=False |
85 | | - drawer.add_flag(lv.obj.FLAG.HIDDEN) |
| 204 | + animator.hide_widget(drawer, anim_type="slide_up", duration=1000, delay=0) |
86 | 205 | if not to_launcher and not mpos.apps.is_launcher(foreground_app_name): |
87 | 206 | print(f"close_drawer: also closing bar because to_launcher is {to_launcher} and foreground_app_name is {foreground_app_name}") |
88 | 207 | close_bar() |
@@ -259,21 +378,21 @@ def create_drawer(display=None): |
259 | 378 | drawer.set_size(lv.pct(100),lv.pct(90)) |
260 | 379 | drawer.set_pos(0,NOTIFICATION_BAR_HEIGHT) |
261 | 380 | drawer.set_scroll_dir(lv.DIR.NONE) |
262 | | - drawer.set_style_pad_all(0, 0) |
| 381 | + drawer.set_style_pad_all(15, 0) |
263 | 382 | drawer.set_style_border_width(0, 0) |
264 | 383 | drawer.set_style_radius(0, 0) |
265 | 384 | drawer.add_flag(lv.obj.FLAG.HIDDEN) |
266 | 385 | #drawer.add_flag(lv.obj.FLAG.GESTURE_BUBBLE) # no gestures are received... maybe not supported by SDL Pointer Driver... |
267 | 386 | drawer.add_event_cb(drawer_swipe_cb, lv.EVENT.PRESSED, None) |
268 | 387 | drawer.add_event_cb(drawer_swipe_cb, lv.EVENT.RELEASED, None) |
269 | 388 | slider_label=lv.label(drawer) |
270 | | - slider_label.set_text(f"{100}%") # TODO: restore this from configuration |
| 389 | + slider_label.set_text(f"{100}%") # TODO: restore this from configuration? |
271 | 390 | slider_label.align(lv.ALIGN.TOP_MID,0,lv.pct(4)) |
272 | 391 | slider=lv.slider(drawer) |
273 | 392 | slider.set_range(1,100) |
274 | 393 | slider.set_value(100,False) |
275 | 394 | slider.set_width(lv.pct(80)) |
276 | | - slider.align_to(slider_label,lv.ALIGN.OUT_BOTTOM_MID,0,lv.pct(6)) |
| 395 | + slider.align_to(slider_label,lv.ALIGN.OUT_BOTTOM_MID,0,10) |
277 | 396 | def slider_event(e): |
278 | 397 | value=slider.get_value() |
279 | 398 | slider_label.set_text(f"{value}%") |
@@ -631,3 +750,5 @@ def handle_top_swipe(): |
631 | 750 | #rect.add_flag(lv.obj.FLAG.GESTURE_BUBBLE) # Allow dragging |
632 | 751 | #rect.add_event_cb(drag_event_cb, lv.EVENT.PRESSING, None) |
633 | 752 | rect.add_event_cb(top_swipe_cb, lv.EVENT.RELEASED, None) |
| 753 | + |
| 754 | + |
0 commit comments