Skip to content
This repository was archived by the owner on Oct 28, 2023. It is now read-only.

Commit 3610bd3

Browse files
authored
Merge pull request SHA2017-badge#68 from SHA2017-badge/asyncTextPrompt
Dialogs: async API for text prompt
2 parents 0faba7f + 568a644 commit 3610bd3

File tree

2 files changed

+96
-60
lines changed

2 files changed

+96
-60
lines changed

esp32/modules/dialogs.py

Lines changed: 80 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ def notice(text, title="SHA2017", close_text="Close", width = 296, height = 128,
1515
"""
1616
prompt_boolean(text, title = title, true_text = close_text, false_text = None, width = width, height = height, font=font)
1717

18-
def prompt_boolean(text, title="SHA2017", true_text="Yes", false_text="No", width = 296, height = 128, font="Roboto_Regular12"):
18+
def prompt_boolean(text, title="SHA2017", true_text="Yes", false_text="No", width = 296, height = 128, font="Roboto_Regular12", cb=None):
1919
"""A simple one and two-options dialog
2020
2121
if 'false_text' is set to None only one button is displayed.
2222
If both 'false_text' and 'true_text' are given a boolean is returned, press B for false, A for true.
2323
24+
Pass along a 'cb' callback to make the dialog async, which is needed to make input work when used from a callback
25+
2426
The caller is responsible for flushing the display after processing the response.
2527
"""
2628
global wait_for_interrupt, button_pushed
@@ -35,6 +37,32 @@ def prompt_boolean(text, title="SHA2017", true_text="Yes", false_text="No", widt
3537
false_text = "B: " + false_text
3638
true_text = "A: " + true_text
3739

40+
def done(result):
41+
window.destroy()
42+
if cb:
43+
cb(result)
44+
return result
45+
46+
def syncSuccess(evt):
47+
if evt:
48+
# We'd like promises here, but for now this should do
49+
global wait_for_interrupt, button_pushed
50+
button_pushed = "A"
51+
wait_for_interrupt = False
52+
def syncCancel(evt):
53+
if evt:
54+
# We'd like promises here, but for now this should do
55+
global wait_for_interrupt, button_pushed
56+
button_pushed = "B"
57+
wait_for_interrupt = False
58+
59+
def asyncSuccess(evt):
60+
if evt:
61+
done(True)
62+
def asyncCancel(evt):
63+
if evt:
64+
done(False)
65+
3866
label = ugfx.Label(5, 30, width - 10, height - 80, text = text, parent=window)
3967
button_no = ugfx.Button(5, height - 40, width // 2 - 15, 30, false_text, parent=window) if false_text else None
4068
button_yes = ugfx.Button(width // 2 + 5 if true_text else 5, height - 40, width // 2 - 15 if false_text else width - 10, 30, true_text, parent=window)
@@ -46,28 +74,24 @@ def prompt_boolean(text, title="SHA2017", true_text="Yes", false_text="No", widt
4674
ugfx.set_lut(ugfx.LUT_NORMAL)
4775
ugfx.flush()
4876

49-
def done(value):
50-
window.hide()
51-
window.destroy()
52-
button_yes.destroy()
53-
if button_no: button_no.destroy()
54-
label.destroy()
55-
return value
77+
if button_no: ugfx.input_attach(ugfx.BTN_B, asyncCancel if cb else syncCancel)
78+
ugfx.input_attach(ugfx.BTN_A, asyncSuccess if cb else syncSuccess)
5679

57-
if button_no: ugfx.input_attach(ugfx.BTN_B, pressed_b)
58-
ugfx.input_attach(ugfx.BTN_A, pressed_a)
59-
60-
wait_for_interrupt = True
61-
while wait_for_interrupt:
62-
time.sleep(0.2)
80+
if cb:
81+
return
82+
else:
83+
wait_for_interrupt = True
84+
while wait_for_interrupt:
85+
time.sleep(0.2)
6386

64-
if button_pushed == "B": return done(False)
65-
if button_pushed == "A": return done(True)
87+
if button_pushed == "B": return done(False)
88+
return done(True)
6689

67-
def prompt_text(description, init_text = "", true_text="OK", false_text="Back", width = 300, height = 200, font="Roboto_BlackItalic24"):
90+
def prompt_text(description, init_text = "", true_text="OK", false_text="Back", width = 300, height = 200, font="Roboto_BlackItalic24", cb=None):
6891
"""Shows a dialog and keyboard that allows the user to input/change a string
6992
70-
Returns None if user aborts with button B
93+
Calls the 'cb' callback or return None if user aborts with button B. Using a callback is highly recommended as it's not
94+
possible to process events inside an event callback.
7195
7296
The caller is responsible for flushing the display after processing the response.
7397
"""
@@ -86,13 +110,33 @@ def prompt_text(description, init_text = "", true_text="OK", false_text="Back",
86110
ugfx.set_default_font("Roboto_Regular12")
87111
button_height = 25
88112

89-
def okay(evt):
90-
# We'd like promises here, but for now this should do
91-
global wait_for_interrupt
92-
button_pushed = "A"
93-
wait_for_interrupt = False
94-
95-
button_yes = ugfx.Button(int(width*4/5), height-kb_height-button_height, int(width*1/5)-3, button_height, true_text, parent=window, cb=okay)
113+
def done(result):
114+
window.destroy()
115+
if cb:
116+
cb(result)
117+
return result
118+
119+
def syncSuccess(evt):
120+
if evt:
121+
# We'd like promises here, but for now this should do
122+
global wait_for_interrupt, button_pushed
123+
button_pushed = "A"
124+
wait_for_interrupt = False
125+
def syncCancel(evt):
126+
if evt:
127+
# We'd like promises here, but for now this should do
128+
global wait_for_interrupt, button_pushed
129+
button_pushed = "B"
130+
wait_for_interrupt = False
131+
132+
def asyncSuccess(evt):
133+
if evt:
134+
done(edit.text())
135+
def asyncCancel(evt):
136+
if evt:
137+
done(None)
138+
139+
button_yes = ugfx.Button(int(width*4/5), height-kb_height-button_height, int(width*1/5)-3, button_height, true_text, parent=window, cb=asyncSuccess if cb else syncSuccess)
96140
button_no = ugfx.Button(int(width*4/5), height-kb_height-button_height-button_height, int(width/5)-3, button_height, false_text, parent=window) if false_text else None
97141
ugfx.set_default_font(font)
98142
label = ugfx.Label(5, 1, int(width*4/5), height-kb_height-5-edit_height-5, description, parent=window)
@@ -114,14 +158,14 @@ def toggle_focus(pressed):
114158
elif focus == 1 or not button_no:
115159
button_yes.set_focus()
116160
kb.enabled(0)
117-
ugfx.input_attach(ugfx.BTN_A, pressed_a)
118-
ugfx.input_attach(ugfx.BTN_B, pressed_b)
161+
ugfx.input_attach(ugfx.BTN_A, asyncSuccess if cb else syncSuccess)
162+
ugfx.input_attach(ugfx.BTN_B, asyncCancel if cb else syncCancel)
119163
focus = (2 if button_no else 0)
120164
else:
121165
button_no.set_focus()
122166
kb.enabled(0)
123-
ugfx.input_attach(ugfx.BTN_A, pressed_a)
124-
ugfx.input_attach(ugfx.BTN_B, pressed_b)
167+
ugfx.input_attach(ugfx.BTN_A, asyncCancel if cb else syncCancel)
168+
ugfx.input_attach(ugfx.BTN_B, asyncCancel if cb else syncCancel)
125169
focus = 0
126170
ugfx.flush()
127171

@@ -138,21 +182,14 @@ def toggle_focus(pressed):
138182
ugfx.flush()
139183

140184
wait_for_interrupt = True
141-
while wait_for_interrupt:
142-
time.sleep(0.2)
185+
if cb:
186+
return
187+
else:
188+
while wait_for_interrupt:
189+
time.sleep(0.2)
143190

144-
def done(value):
145-
window.hide()
146-
window.destroy()
147-
button_yes.destroy()
148-
if button_no: button_no.destroy()
149-
label.destroy()
150-
kb.destroy()
151-
edit.destroy()
152-
return value
153-
154-
if (focus == 0 and no_button) or button_pushed == "B": return done(False)
155-
return done(edit.text())
191+
if (focus == 0 and no_button) or button_pushed == "B": return done(False)
192+
return done(edit.text())
156193

157194
def prompt_option(options, index=0, text = "Please select one of the following:", title=None, select_text="OK", none_text=None):
158195
"""Shows a dialog prompting for one of multiple options

esp32/modules/launcher.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ def get_install_path():
7373
install_path = expandhome(install_path)
7474
return install_path
7575

76-
7776
def uninstall_it(pushed):
7877
if (pushed):
7978
selected = options.selected_text()
@@ -82,23 +81,23 @@ def uninstall_it(pushed):
8281
if selected == 'ota_update':
8382
return
8483
options.destroy()
85-
import dialogs
86-
print(selected)
87-
uninstall = dialogs.prompt_boolean('Are you sure you want to remove %s?' % selected)
88-
print(uninstall)
89-
if uninstall:
90-
ugfx.clear(ugfx.BLACK)
91-
ugfx.string_box(0, 25, 296, 25,"Uninstalling:","Roboto_BlackItalic24",ugfx.WHITE, ugfx.justifyCenter)
92-
ugfx.string_box(0, 51, 296, 23, selected, "PermanentMarker22", ugfx.WHITE, ugfx.justifyCenter)
93-
ugfx.flush()
94-
install_path = get_install_path()
95-
for rm_file in os.listdir("%s/%s" % (install_path, selected)):
96-
os.remove("%s/%s/%s" % (install_path, selected, rm_file))
97-
os.rmdir("%s/%s" % (install_path, selected))
98-
badge.eink_busy_wait()
99-
esp.rtcmem_write_string('launcher')
100-
esp.start_sleeping(1)
10184

85+
def perform_uninstall(ok):
86+
if ok:
87+
ugfx.clear(ugfx.BLACK)
88+
ugfx.string_box(0, 25, 296, 25,"Uninstalling:","Roboto_BlackItalic24",ugfx.WHITE, ugfx.justifyCenter)
89+
ugfx.string_box(0, 51, 296, 23, selected, "PermanentMarker22", ugfx.WHITE, ugfx.justifyCenter)
90+
ugfx.flush()
91+
install_path = get_install_path()
92+
for rm_file in os.listdir("%s/%s" % (install_path, selected)):
93+
os.remove("%s/%s/%s" % (install_path, selected, rm_file))
94+
os.rmdir("%s/%s" % (install_path, selected))
95+
badge.eink_busy_wait()
96+
esp.rtcmem_write_string('launcher')
97+
esp.start_sleeping(1)
98+
99+
import dialogs
100+
uninstall = dialogs.prompt_boolean('Are you sure you want to remove %s?' % selected, cb=perform_uninstall)
102101

103102
populate_it()
104103

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy