Skip to content

Commit 06d98ce

Browse files
Camera app: cleanup, add animations
1 parent 8e0063c commit 06d98ce

File tree

2 files changed

+35
-94
lines changed

2 files changed

+35
-94
lines changed

internal_filesystem/apps/com.micropythonos.camera/assets/camera_app.py

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,6 @@ def create_basic_tab(self, tab, prefs):
849849

850850
def create_advanced_tab(self, tab, prefs):
851851
"""Create Advanced settings tab."""
852-
#tab.set_scrollbar_mode(lv.SCROLLBAR_MODE.AUTO)
853852
tab.set_flex_flow(lv.FLEX_FLOW.COLUMN)
854853
tab.set_style_pad_all(1, 0)
855854

@@ -860,27 +859,23 @@ def create_advanced_tab(self, tab, prefs):
860859

861860
# Manual Exposure Value (dependent)
862861
aec_value = prefs.get_int("aec_value", 300)
863-
me_slider, label, cont = self.create_slider(tab, "Manual Exposure", 0, 1200, aec_value, "aec_value")
862+
me_slider, label, me_cont = self.create_slider(tab, "Manual Exposure", 0, 1200, aec_value, "aec_value")
864863
self.ui_controls["aec_value"] = me_slider
865864

866865
# Auto Exposure Level (dependent)
867866
ae_level = prefs.get_int("ae_level", 0)
868-
ae_slider, label, cont = self.create_slider(tab, "Auto Exposure Level", -2, 2, ae_level, "ae_level")
867+
ae_slider, label, ae_cont = self.create_slider(tab, "Auto Exposure Level", -2, 2, ae_level, "ae_level")
869868
self.ui_controls["ae_level"] = ae_slider
870869

871870
# Add dependency handler
872871
def exposure_ctrl_changed(e=None):
873872
is_auto = aec_checkbox.get_state() & lv.STATE.CHECKED
874873
if is_auto:
875-
me_slider.add_state(lv.STATE.DISABLED)
876-
me_slider.set_style_opa(128, 0)
877-
ae_slider.remove_state(lv.STATE.DISABLED)
878-
ae_slider.set_style_opa(255, 0)
874+
mpos.ui.anim.smooth_hide(me_cont, duration=1000)
875+
mpos.ui.anim.smooth_show(ae_cont, delay=1000)
879876
else:
880-
me_slider.remove_state(lv.STATE.DISABLED)
881-
me_slider.set_style_opa(255, 0)
882-
ae_slider.add_state(lv.STATE.DISABLED)
883-
ae_slider.set_style_opa(128, 0)
877+
mpos.ui.anim.smooth_hide(ae_cont, duration=1000)
878+
mpos.ui.anim.smooth_show(me_cont, delay=1000)
884879

885880
aec_checkbox.add_event_cb(exposure_ctrl_changed, lv.EVENT.VALUE_CHANGED, None)
886881
exposure_ctrl_changed()
@@ -897,24 +892,19 @@ def exposure_ctrl_changed(e=None):
897892

898893
# Manual Gain Value (dependent)
899894
agc_gain = prefs.get_int("agc_gain", 0)
900-
slider, label, cont = self.create_slider(tab, "Manual Gain", 0, 30, agc_gain, "agc_gain")
895+
slider, label, agc_cont = self.create_slider(tab, "Manual Gain", 0, 30, agc_gain, "agc_gain")
901896
self.ui_controls["agc_gain"] = slider
902897

903-
if gain_ctrl:
904-
slider.add_state(lv.STATE.DISABLED)
905-
slider.set_style_opa(128, 0)
906-
907-
def gain_ctrl_changed(e):
898+
def gain_ctrl_changed(e=None):
908899
is_auto = agc_checkbox.get_state() & lv.STATE.CHECKED
909900
gain_slider = self.ui_controls["agc_gain"]
910901
if is_auto:
911-
gain_slider.add_state(lv.STATE.DISABLED)
912-
gain_slider.set_style_opa(128, 0)
902+
mpos.ui.anim.smooth_hide(agc_cont, duration=1000)
913903
else:
914-
gain_slider.remove_state(lv.STATE.DISABLED)
915-
gain_slider.set_style_opa(255, 0)
904+
mpos.ui.anim.smooth_show(agc_cont, duration=1000)
916905

917906
agc_checkbox.add_event_cb(gain_ctrl_changed, lv.EVENT.VALUE_CHANGED, None)
907+
gain_ctrl_changed()
918908

919909
# Gain Ceiling
920910
gainceiling_options = [
@@ -935,21 +925,17 @@ def gain_ctrl_changed(e):
935925
("Auto", 0), ("Sunny", 1), ("Cloudy", 2), ("Office", 3), ("Home", 4)
936926
]
937927
wb_mode = prefs.get_int("wb_mode", 0)
938-
dropdown, cont = self.create_dropdown(tab, "WB Mode:", wb_mode_options, wb_mode, "wb_mode")
939-
self.ui_controls["wb_mode"] = dropdown
928+
wb_dropdown, wb_cont = self.create_dropdown(tab, "WB Mode:", wb_mode_options, wb_mode, "wb_mode")
929+
self.ui_controls["wb_mode"] = wb_dropdown
940930

941-
if whitebal:
942-
dropdown.add_state(lv.STATE.DISABLED)
943-
944-
def whitebal_changed(e):
931+
def whitebal_changed(e=None):
945932
is_auto = wbcheckbox.get_state() & lv.STATE.CHECKED
946-
wb_dropdown = self.ui_controls["wb_mode"]
947933
if is_auto:
948-
wb_dropdown.add_state(lv.STATE.DISABLED)
934+
mpos.ui.anim.smooth_hide(wb_cont, duration=1000)
949935
else:
950-
wb_dropdown.remove_state(lv.STATE.DISABLED)
951-
936+
mpos.ui.anim.smooth_show(wb_cont, duration=1000)
952937
wbcheckbox.add_event_cb(whitebal_changed, lv.EVENT.VALUE_CHANGED, None)
938+
whitebal_changed()
953939

954940
# AWB Gain
955941
awb_gain = prefs.get_bool("awb_gain", True)
@@ -974,36 +960,16 @@ def create_expert_tab(self, tab, prefs):
974960
tab.set_flex_flow(lv.FLEX_FLOW.COLUMN)
975961
tab.set_style_pad_all(1, 0)
976962

977-
# Note: Sensor detection isn't performed right now
978-
# For now, show sharpness/denoise with note
979-
supports_sharpness = True # Assume yes
980-
981963
# Sharpness
982964
sharpness = prefs.get_int("sharpness", 0)
983965
slider, label, cont = self.create_slider(tab, "Sharpness", -3, 3, sharpness, "sharpness")
984966
self.ui_controls["sharpness"] = slider
985967

986-
if not supports_sharpness:
987-
slider.add_state(lv.STATE.DISABLED)
988-
slider.set_style_opa(128, 0)
989-
note = lv.label(cont)
990-
note.set_text("(Not available on this sensor)")
991-
note.set_style_text_color(lv.color_hex(0x808080), 0)
992-
note.align(lv.ALIGN.TOP_RIGHT, 0, 0)
993-
994968
# Denoise
995969
denoise = prefs.get_int("denoise", 0)
996970
slider, label, cont = self.create_slider(tab, "Denoise", 0, 8, denoise, "denoise")
997971
self.ui_controls["denoise"] = slider
998972

999-
if not supports_sharpness:
1000-
slider.add_state(lv.STATE.DISABLED)
1001-
slider.set_style_opa(128, 0)
1002-
note = lv.label(cont)
1003-
note.set_text("(Not available on this sensor)")
1004-
note.set_style_text_color(lv.color_hex(0x808080), 0)
1005-
note.align(lv.ALIGN.TOP_RIGHT, 0, 0)
1006-
1007973
# JPEG Quality
1008974
# Disabled because JPEG is not used right now
1009975
#quality = prefs.get_int("quality", 85)

internal_filesystem/lib/mpos/ui/anim.py

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,18 @@ class WidgetAnimator:
4141
# show_widget and hide_widget could have a (lambda) callback that sets the final state (eg: drawer_open) at the end
4242
@staticmethod
4343
def show_widget(widget, anim_type="fade", duration=500, delay=0):
44-
"""Show a widget with an animation (fade or slide)."""
45-
4644
lv.anim_delete(widget, None) # stop all ongoing animations to prevent visual glitches
47-
widget.remove_flag(lv.obj.FLAG.HIDDEN) # Clear HIDDEN flag to make widget visible for animation
45+
anim = lv.anim_t()
46+
anim.init()
47+
anim.set_var(widget)
48+
anim.set_delay(delay)
49+
anim.set_duration(duration)
50+
# Clear HIDDEN flag to make widget visible for animation:
51+
anim.set_start_cb(lambda *args: safe_widget_access(lambda: widget.remove_flag(lv.obj.FLAG.HIDDEN)))
4852

4953
if anim_type == "fade":
5054
# Create fade-in animation (opacity from 0 to 255)
51-
anim = lv.anim_t()
52-
anim.init()
53-
anim.set_var(widget)
5455
anim.set_values(0, 255)
55-
anim.set_duration(duration)
56-
anim.set_delay(delay)
5756
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_style_opa(value, 0)))
5857
anim.set_path_cb(lv.anim_t.path_ease_in_out)
5958
# Ensure opacity is reset after animation
@@ -63,50 +62,38 @@ def show_widget(widget, anim_type="fade", duration=500, delay=0):
6362
# Create slide-down animation (y from -height to original y)
6463
original_y = widget.get_y()
6564
height = widget.get_height()
66-
anim = lv.anim_t()
67-
anim.init()
68-
anim.set_var(widget)
6965
anim.set_values(original_y - height, original_y)
70-
anim.set_duration(duration)
71-
anim.set_delay(delay)
7266
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_y(value)))
7367
anim.set_path_cb(lv.anim_t.path_ease_in_out)
7468
# Reset y position after animation
7569
anim.set_completed_cb(lambda *args: safe_widget_access(lambda: widget.set_y(original_y)))
76-
elif anim_type == "slide_up":
70+
else: # "slide_up":
7771
# Create slide-up animation (y from +height to original y)
7872
# Seems to cause scroll bars to be added somehow if done to a keyboard at the bottom of the screen...
7973
original_y = widget.get_y()
8074
height = widget.get_height()
81-
anim = lv.anim_t()
82-
anim.init()
83-
anim.set_var(widget)
8475
anim.set_values(original_y + height, original_y)
85-
anim.set_duration(duration)
86-
anim.set_delay(delay)
8776
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_y(value)))
8877
anim.set_path_cb(lv.anim_t.path_ease_in_out)
8978
# Reset y position after animation
9079
anim.set_completed_cb(lambda *args: safe_widget_access(lambda: widget.set_y(original_y)))
9180

92-
# Store and start animation
93-
#self.animations[widget] = anim
9481
anim.start()
9582
return anim
9683

9784
@staticmethod
9885
def hide_widget(widget, anim_type="fade", duration=500, delay=0, hide=True):
9986
lv.anim_delete(widget, None) # stop all ongoing animations to prevent visual glitches
87+
anim = lv.anim_t()
88+
anim.init()
89+
anim.set_var(widget)
90+
anim.set_duration(duration)
91+
anim.set_delay(delay)
10092

10193
"""Hide a widget with an animation (fade or slide)."""
10294
if anim_type == "fade":
10395
# Create fade-out animation (opacity from 255 to 0)
104-
anim = lv.anim_t()
105-
anim.init()
106-
anim.set_var(widget)
10796
anim.set_values(255, 0)
108-
anim.set_duration(duration)
109-
anim.set_delay(delay)
11097
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_style_opa(value, 0)))
11198
anim.set_path_cb(lv.anim_t.path_ease_in_out)
11299
# Set HIDDEN flag after animation
@@ -116,34 +103,22 @@ def hide_widget(widget, anim_type="fade", duration=500, delay=0, hide=True):
116103
# Seems to cause scroll bars to be added somehow if done to a keyboard at the bottom of the screen...
117104
original_y = widget.get_y()
118105
height = widget.get_height()
119-
anim = lv.anim_t()
120-
anim.init()
121-
anim.set_var(widget)
122106
anim.set_values(original_y, original_y + height)
123-
anim.set_duration(duration)
124-
anim.set_delay(delay)
125107
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_y(value)))
126108
anim.set_path_cb(lv.anim_t.path_ease_in_out)
127109
# Set HIDDEN flag after animation
128110
anim.set_completed_cb(lambda *args: safe_widget_access(lambda: WidgetAnimator.hide_complete_cb(widget, original_y, hide)))
129-
elif anim_type == "slide_up":
111+
else: # "slide_up":
130112
print("hide with slide_up")
131113
# Create slide-up animation (y from original y to -height)
132114
original_y = widget.get_y()
133115
height = widget.get_height()
134-
anim = lv.anim_t()
135-
anim.init()
136-
anim.set_var(widget)
137116
anim.set_values(original_y, original_y - height)
138-
anim.set_duration(duration)
139-
anim.set_delay(delay)
140117
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_y(value)))
141118
anim.set_path_cb(lv.anim_t.path_ease_in_out)
142119
# Set HIDDEN flag after animation
143120
anim.set_completed_cb(lambda *args: safe_widget_access(lambda: WidgetAnimator.hide_complete_cb(widget, original_y, hide)))
144121

145-
# Store and start animation
146-
#self.animations[widget] = anim
147122
anim.start()
148123
return anim
149124

@@ -156,8 +131,8 @@ def hide_complete_cb(widget, original_y=None, hide=True):
156131
widget.set_y(original_y) # in case it shifted slightly due to rounding etc
157132

158133

159-
def smooth_show(widget):
160-
return WidgetAnimator.show_widget(widget, anim_type="fade", duration=500, delay=0)
134+
def smooth_show(widget, duration=500, delay=0):
135+
return WidgetAnimator.show_widget(widget, anim_type="fade", duration=duration, delay=delay)
161136

162-
def smooth_hide(widget, hide=True):
163-
return WidgetAnimator.hide_widget(widget, anim_type="fade", duration=500, delay=0, hide=hide)
137+
def smooth_hide(widget, hide=True, duration=500, delay=0):
138+
return WidgetAnimator.hide_widget(widget, anim_type="fade", duration=duration, delay=delay, hide=hide)

0 commit comments

Comments
 (0)