From 8ed80eeebab06dba5839a7f08703494a9917348a Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Mon, 6 Apr 2020 22:03:05 +0100 Subject: [PATCH] wasp: launcher: Experimental launcher implementation It is not really the launcher itself that is immature. Rather that the framework and UI concepts to move between applications isn't complete yet. --- res/app_icon.png | Bin 0 -> 7124 bytes res/clock_icon.png | Bin 0 -> 965 bytes res/down_arrow.png | Bin 0 -> 599 bytes res/settings_icon.png | Bin 0 -> 1082 bytes res/torch_icon.png | Bin 0 -> 820 bytes res/up_arrow.png | Bin 0 -> 593 bytes wasp/apps/clock.py | 3 ++ wasp/apps/flashlight.py | 4 ++ wasp/apps/launcher.py | 80 +++++++++++++++++++++++++++++++ wasp/apps/testapp.py | 4 ++ wasp/boards/pinetime/manifest.py | 3 +- wasp/icons.py | 9 ++++ wasp/wasp.py | 34 ++++++++++--- 13 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 res/app_icon.png create mode 100644 res/clock_icon.png create mode 100644 res/down_arrow.png create mode 100644 res/settings_icon.png create mode 100644 res/torch_icon.png create mode 100644 res/up_arrow.png create mode 100644 wasp/apps/launcher.py diff --git a/res/app_icon.png b/res/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..574f75fe221e251189f06146a45601aa10da4f12 GIT binary patch literal 7124 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 Bic0_h literal 0 HcmV?d00001 diff --git a/res/clock_icon.png b/res/clock_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..165bf5166a0616fe2ba319a058a8f3b3e58c9eae GIT binary patch literal 965 zcmeAS@N?(olHy`uVBq!ia0vp^2|(L7=A<$( zXiTh~Xzg*>LFU+gyCtq#d~X#VO;~6Z`JvS!OSCIM@e0>ks~IuBn$&nbySf)Yh${H7 zF`~4f@Y>abp#m)O3VwZlU3x)}{!eo1mUwUR?s)nC_mAJzH|&p0T_q{Q9CFskXyuX# zr`K~W3}?w~6Fj=(h)=Db$mI_*@!vmu{Hu3x^PboLWNN(*rZo5~%uC&sD3~wcpC4uQ zy!MfVwl~*D%a1D@#Z~H_?0WM_`uU{8b@L>RH_fbkB(X8zRnpGx$eRJ3%R3%-tqR;{ z|9sP-%I?ikYd3$h{mHG&nwvWF^_I2?hm@u%I5qTGX{|Wq)Ku0hA}nd;U-g4scE5+- z%otIFBAo?nqLUu8|8Ks(*R*@Ga9)rK=a)S0f*+6{@(utlL?eJ^%3+ z#uGv7FPR@WsAv$h=uK&VdHe3)-|~HT*V|h!ESh+f`LH!GTG*1j-Cck*5d3uBT@R!< z3p^r=85s1GL71^(seKtxkiEpy*OmPV3k!#oI2+#^cA$`CiEBiObAE1aYF-J0b5Uwy zNotBhd1gt5g1e`0KzJjcI54{Bdb&7tf##1rFD%KmPAOv(GFxdZW^%mpf0| z_%=Nd6v_3|^mMu%GJ^?dC?f*{2Qb9|SwNlu149Fl#lpa_VC$;#`mQbVr;E-VW{$kI zDeUxi!Tsx!F5ft{@}r7na>12regabW-~G9CtSo)?8@>;j266i$f2k_{e-o-}%IzMd z{U9UUW!uyxk9UY^M{{qCY^riInOq_lGW(PqgUP<$ANIy+ALC*#nmt;*ac%9cP2%q) ztajzg)N5z|T4np{a;-zlnI(e1oz(Am$G=z3SaK<9&!yj|8Z{={Z|aYjw=1h9bV6~R z$ez&NxSQQy9z{hpDc$+}=1XMp@sPbtv-WN9UJFYh!zBDW#=)7Ip5-_9--?EdBI(xMjlSEch>$9G_;;R;Fx cnAHB2_Hzm!W#^vxITNJZ)78&qol`;+0I+_a<^TWy literal 0 HcmV?d00001 diff --git a/res/down_arrow.png b/res/down_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..ef94eb3c0b4737ba4ddfc443f14515720edd8d50 GIT binary patch literal 599 zcmV-d0;v6oP)EX>4Tx04R}tkv&MmKp2MKrj?3B9qb_DkfAzR5EXIMDionYs1;guFuC*(nlvOW zE{=k0!NH%!s)LKOt`4q(Aov5~C`-Ngjgzcu-d__Xz9dL#8FK*C|}5U zta0Arte0!7bx;06F=wnSbDh>O5?I6%WJpj^LkVS65u@E8#YT$G<39c&*DsSxC07ZI z91EyGhvNFd|KN9T?fm3~mn6o4t{2Do7y-h&K(p>R-^Y&AJOP5wz?ISVR~o>~C+YRJ z7Ci#`w}Ff6wx;d@mpj1Vlc`vWD+Or@`8@D`M&FbL25y0#HLq{2bDTZ^Y3fz-1~@nb zMhld^?(^>M&c6Ly)9T+3-3oGRsRnkS00009a7bBm000XU000XU0RWnu7ytkO2XskI zMF->r1Pm29T1i#g0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbN zK}keGR2b8hjzJ0lFbKn%{r}J1L69MHxSmuJ72EpB(r1t~KLQZd#0i+}-%hUPoOVvq lRk%7QeG!UN=r*>y_cmQS8v%C!aSZ?f002ovPDHLkV1iRk0qg(( literal 0 HcmV?d00001 diff --git a/res/settings_icon.png b/res/settings_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d1141b03052397335cfa703f4dbf7826c2dbc88b GIT binary patch literal 1082 zcmV-A1jYM_P)EX>4Tx04R}tkv&MmKp2MKrj?3B9qb_DkfAzR5EXIMDionYs1;guFuC*(nlvOW zE{=k0!NH%!s)LKOt`4q(Aov5~C`-Ngjgzcu-d__Xz9dL#8FK*C|}5U zta0Arte0!7bx;06F=wnSbDh>O5?I6%WJpj^LkVS65u@E8#YT$G<39c&*DsSxC07ZI z91EyGhvNFd|KN9T?fm3~mn6o4t{2Do7y-h&K(p>R-^Y&AJOP5wz?ISVR~o>~C+YRJ z7Ci#`w}Ff6wx;d@mpj1Vlc`vWD+Or@`8@D`M&FbL25y0#HLq{2bDTZ^Y3fz-1~@nb zMhld^?(^>M&c6Ly)9T+3-3oGRsRnkS00009a7bBm000XU000XU0RWnu7ytkO2XskI zMF->r1q&__?!9CA0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbP zBuPX;RCwC$T*0oxAPgg@|NqOp!&4=MN*fp@PU@UCjk4i@9aC0GDV1aprI>teH$=qb zdvju#1{3hb1fbE6vHDmqXBUdici^&5(UuK2s2)g$~~x4-L` z378aC?F{xH*clCc5xE7p_nGFpo^DVBF2FrskBVyD_Uc*@AqCAQW#_e@Ou&wriDuRg zgc&{q%8JqwVTC|wK%Im;&ev8on(I;M39byC0bkp;6=+h>V!El@dD)W4I{?!-))ibo zTIY{CY!?a845&Borx~l6(KCHmCL&wY$r}~REcI94A_dD%U;zJb_L9qlB0gWy3&HCAj>4o^zn2vC!_|PgC0%R$ZbYV-`3j|F7|?2 zEzqn4FGo`{3cyd`u5iML+tCm!Knu)WqO|)&Xa~3sB=C1vEC@+}GGaTxK+^_zC;W?P z@^D%j?ri84&yR>_3;OxKK4-)P{7_=Hfc|R0NI@x09YwV4H>3viHsfX-Yu)~?UsBK} zV31w0tAEI}M#}RRgqt!ndbmq~2Vo6ML7sso1u+2(GYX3I=o&XGAQDf%IhO48her|o zZBI?)L;H*qzyR_AsH-8&!7Pv3z=wCU3}slvAM_nbypjZu>i_@%07*qoM6N<$f?@IL AssI20 literal 0 HcmV?d00001 diff --git a/res/torch_icon.png b/res/torch_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bbd4db3bb8ecc7e891ef7187deeb57f27239a10f GIT binary patch literal 820 zcmV-41Izr0P)EX>4Tx04R}tkv&MmKp2MKrj?3B9qb_DkfAzR5EXIMDionYs1;guFuC*(nlvOW zE{=k0!NH%!s)LKOt`4q(Aov5~C`-Ngjgzcu-d__Xz9dL#8FK*C|}5U zta0Arte0!7bx;06F=wnSbDh>O5?I6%WJpj^LkVS65u@E8#YT$G<39c&*DsSxC07ZI z91EyGhvNFd|KN9T?fm3~mn6o4t{2Do7y-h&K(p>R-^Y&AJOP5wz?ISVR~o>~C+YRJ z7Ci#`w}Ff6wx;d@mpj1Vlc`vWD+Or@`8@D`M&FbL25y0#HLq{2bDTZ^Y3fz-1~@nb zMhld^?(^>M&c6Ly)9T+3-3oGRsRnkS00009a7bBm000XU000XU0RWnu7ytkO2XskI zMF->r1qcTUBG`+k0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbO z9!W$&RCwC$nMn@BAPfW{%KyL297c*p44VLhajFivWHU`;vp5F;00000000000F&_N zh8{wQ8{<6!C3F$h=sr}Me<8}k*>}*>{-j5~cO{0{G3rze(&C_&@8}w0QMla}C^x(8 zKD|RM*{WP}skSYI(EaXA2MOiE!S6?JjaX*LLDK4s6z`;i_LTX>#iB9$3jO^uvLF!a zvujol&%J8PjQ#Tw33YNAcZ)_nNqT(_YN_$Rfh}IIRc4~nLu{{uj0~}kHN>_x(XOeZ zP+&&Nyj-{4s-hX02Wi<4(z)8mRk2s>5H%*g>Fz1jv{-~Rs?cw yryA2W;#|y}Kn11Vd+Y-M0000000000I`{ymQ-~0^R{FL80000EX>4Tx04R}tkv&MmKp2MKrj?3B9qb_DkfAzR5EXIMDionYs1;guFuC*(nlvOW zE{=k0!NH%!s)LKOt`4q(Aov5~C`-Ngjgzcu-d__Xz9dL#8FK*C|}5U zta0Arte0!7bx;06F=wnSbDh>O5?I6%WJpj^LkVS65u@E8#YT$G<39c&*DsSxC07ZI z91EyGhvNFd|KN9T?fm3~mn6o4t{2Do7y-h&K(p>R-^Y&AJOP5wz?ISVR~o>~C+YRJ z7Ci#`w}Ff6wx;d@mpj1Vlc`vWD+Or@`8@D`M&FbL25y0#HLq{2bDTZ^Y3fz-1~@nb zMhld^?(^>M&c6Ly)9T+3-3oGRsRnkS00009a7bBm001r{001r{0eGc9b^rhX2XskI zMF->r1Pm1mlAZ)x0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbN zJ4r-AR2b8hj6n_nAPB>#|Nrwmn5Y3F*z4MvWk`~gPNepkp$Ou!Yk1qSp|o8?$G#hy f_HO9gi(#Kk@~ImE3U6Cw00000NkvXXu0mjf^Z^4O literal 0 HcmV?d00001 diff --git a/wasp/apps/clock.py b/wasp/apps/clock.py index 4feba63..4236d9a 100644 --- a/wasp/apps/clock.py +++ b/wasp/apps/clock.py @@ -3,6 +3,7 @@ import wasp +import icons import fonts.clock as digits DIGITS = ( @@ -25,6 +26,8 @@ class ClockApp(): Shows a time (as HH:MM) together with a battery meter and the date. """ + NAME = 'Clock' + ICON = icons.clock def __init__(self): self.meter = wasp.widgets.BatteryMeter() diff --git a/wasp/apps/flashlight.py b/wasp/apps/flashlight.py index 13e3443..c4702a0 100644 --- a/wasp/apps/flashlight.py +++ b/wasp/apps/flashlight.py @@ -3,11 +3,15 @@ import wasp +import icons + class FlashlightApp(object): """Trivial flashlight application. Shows a pure white screen with the backlight set to maximum. """ + NAME = 'Torch' + ICON = icons.torch def foreground(self): """Activate the application.""" diff --git a/wasp/apps/launcher.py b/wasp/apps/launcher.py new file mode 100644 index 0000000..274ea9c --- /dev/null +++ b/wasp/apps/launcher.py @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: LGPL-3.0-or-later +# Copyright (C) 2020 Daniel Thompson + +import wasp +import icons + +class LauncherApp(): + """An application launcher application. + """ + NAME = 'Launcher' + ICON = icons.app + + def foreground(self): + """Activate the application.""" + self._page = 0 + self._draw() + wasp.system.request_event(wasp.EventMask.TOUCH | + wasp.EventMask.SWIPE_UPDOWN) + + def swipe(self, event): + i = self._page + n = self._num_pages + if event[0] == wasp.EventType.UP: + i += 1 + if i >= n: + i -= 1 + wasp.watch.vibrator.pulse() + return + else: + i -= 1 + if i < 0: + wasp.system.switch(wasp.system.applications[0]) + return + + self._page = i + wasp.watch.display.mute(True) + self._draw() + wasp.watch.display.mute(False) + + def touch(self, event): + page = self._get_page(self._page) + x = event[1] + y = event[2] + app = page[2 * (y // 120) + (x // 120)] + if app: + wasp.system.switch(app) + else: + wasp.watch.vibrator.pulse() + + @property + def _num_pages(self): + """Work out what the highest possible pages it.""" + num_apps = len(wasp.system.applications) + return (num_apps + 3) // 4 + + def _get_page(self, i): + apps = wasp.system.applications + page = apps[4*i: 4*(i+1)] + while len(page) < 4: + page.append(None) + return page + + def _draw(self): + """Redraw the display from scratch.""" + def draw_app(app, x, y): + if not app: + return + draw.set_color(0xffff) + draw.rleblit(app.ICON, (x+13, y+12)) + draw.set_color(0xbdb6) + draw.string(app.NAME, x, y+120-30, 120) + + draw = wasp.watch.drawable + page = self._get_page(self._page) + + draw.fill() + draw_app(page[0], 0, 0) + draw_app(page[1], 120, 0) + draw_app(page[2], 0, 120) + draw_app(page[3], 120, 120) diff --git a/wasp/apps/testapp.py b/wasp/apps/testapp.py index 8c15848..478249f 100644 --- a/wasp/apps/testapp.py +++ b/wasp/apps/testapp.py @@ -3,10 +3,13 @@ import machine import wasp +import icons class TestApp(): """Simple test application. """ + NAME = 'Self Test' + ICON = icons.app def __init__(self): self.tests = ('Touch', 'String', 'Button', 'Crash') @@ -57,6 +60,7 @@ class TestApp(): def benchmark_string(self): draw = wasp.watch.drawable draw.fill(0, 0, 30, 240, 240-30) + self.scroll.draw() t = machine.Timer(id=1, period=8000000) t.start() draw.string("The quick brown", 12, 24+24) diff --git a/wasp/boards/pinetime/manifest.py b/wasp/boards/pinetime/manifest.py index 191ee3d..30d54e2 100644 --- a/wasp/boards/pinetime/manifest.py +++ b/wasp/boards/pinetime/manifest.py @@ -5,8 +5,9 @@ freeze('.', 'watch.py', opt=3) freeze('../..', ( 'apps/clock.py', - 'apps/testapp.py', 'apps/flashlight.py', + 'apps/launcher.py', + 'apps/testapp.py', 'boot.py', 'demo.py', 'draw565.py', diff --git a/wasp/icons.py b/wasp/icons.py index c3089c4..76b5ee7 100644 --- a/wasp/icons.py +++ b/wasp/icons.py @@ -4,6 +4,15 @@ # 1-bit RLE, generated from res/battery.png, 189 bytes battery = (36, 48, b'\x97\x0e\x14\x12\x11\x14\x10\x14\x0c\x08\x0c\x08\x08\x08\x0c\x08\x08\x08\x0c\x08\x08\x08\x0c\x08\x08\x04\x14\x04\x08\x04\x14\x04\x08\x04\x0c\x04\x04\x04\x08\x04\x0b\x05\x04\x04\x08\x04\n\x06\x04\x04\x08\x04\t\x07\x04\x04\x08\x04\x08\x07\x05\x04\x08\x04\x07\x07\x06\x04\x08\x04\x06\x07\x07\x04\x08\x04\x05\x07\x08\x04\x08\x04\x04\x0e\x02\x04\x08\x04\x03\x0f\x02\x04\x08\x04\x02\x10\x02\x04\x08\x04\x02\x10\x02\x04\x08\x04\x02\x0f\x03\x04\x08\x04\x02\x0e\x04\x04\x08\x04\x08\x07\x05\x04\x08\x04\x07\x07\x06\x04\x08\x04\x06\x07\x07\x04\x08\x04\x05\x07\x08\x04\x08\x04\x04\x07\t\x04\x08\x04\x04\x06\n\x04\x08\x04\x04\x05\x0b\x04\x08\x04\x04\x04\x0c\x04\x08\x04\x14\x04\x08\x04\x14\x04\x08\x04\x14\x04\x08\x04\x14\x04\x08\x1c\x08\x1c\x08\x1c\x08\x1c\x98') +# 1-bit RLE, generated from res/app_icon.png, 441 bytes +app = (96, 64, b'\x1e$<$<$;&\x97,20/2-4,\x03.\x03,\x03.\x03,\x03.\x03,\x03.\x03,\x03.\x03,\x03\x0c\x03\x10\x03\x0c\x03,\x03\n\x07\x0c\x07\n\x03,\x03\t\x03\x02\x04\n\x04\x02\x03\t\x03,\x03\x08\x02\x07\x02\x08\x02\x07\x02\x08\x03,\x03\x07\x02\t\x02\x06\x02\t\x02\x07\x03,\x03\x06\x02\x0b\x02\x04\x02\x0b\x02\x06\x03,\x03\x06\x02\x0b\x02\x04\x02\x0b\x02\x06\x03,\x03\x05\x02\x0c\x02\x04\x02\x0c\x02\x05\x03,\x03\x05\x02\x0c\x02\x04\x02\x0c\x02\x05\x03,\x03\x05\x03\x0b\x02\x04\x02\x0b\x03\x05\x03,\x03\x06\x02\x0b\x02\x04\x02\x0b\x02\x06\x03,\x03\x06\x02\x0b\x02\x04\x02\x0b\x01\x07\x03,\x03\x07\x02\n\x02\x04\x02\n\x02\x07\x03+\x04\x08\x02\t\x02\x04\x02\t\x02\x08\x03*\x05\t\x0c\x04\x0c\t\x03*\x05\n\x0b\x04\x0b\n\x03*\x05.\x03*\x05.\x03*\x05.\x03*\x05.\x03*\x05\n\x0b\x04\x0b\n\x03+\x04\t\x0c\x04\x0c\t\x03,\x03\x08\x02\t\x02\x04\x02\t\x02\x08\x03,\x03\x07\x02\n\x02\x04\x02\n\x02\x07\x03,\x03\x06\x02\x0b\x02\x04\x02\x0b\x01\x07\x03,\x03\x06\x02\x0b\x02\x04\x02\x0b\x02\x06\x03,\x03\x05\x03\x0b\x02\x04\x02\x0b\x03\x05\x03,\x03\x05\x02\x0c\x02\x04\x02\x0c\x02\x05\x03,\x03\x05\x02\x0c\x02\x04\x02\x0c\x02\x05\x03,\x03\x06\x02\x0b\x02\x04\x02\x0b\x02\x06\x03,\x03\x06\x02\x0b\x02\x04\x02\x0b\x02\x06\x03,\x03\x07\x02\t\x02\x06\x02\t\x02\x07\x03,\x03\x08\x02\x07\x02\x08\x02\x07\x02\x08\x03,\x03\t\x03\x02\x04\n\x04\x02\x03\t\x03,\x03\n\x06\x0e\x06\n\x03,\x03\x0c\x03\x10\x03\x0c\x03,\x03.\x03,\x03.\x03,\x03.\x03,\x03.\x03,\x03.\x03,4-2/02,\x97&;$<$<$\x1e') + +# 1-bit RLE, generated from res/clock_icon.png, 301 bytes +clock = (96, 64, b'\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xcd\x06\r\x06!\x05\x0b\x08\x0c\x08\x0b\n\x1d\t\x07\x0c\n\x08\n\x0c\x1b\x0b\x06\x0e\x08\x03\x02\x03\n\x04\x05\x04\x1a\x04\x03\x04\x06\x02\x08\x04\r\x03\t\x04\x07\x03\x19\x04\x05\x04\x10\x04\x0c\x03\t\x03\t\x02\x19\x03\x07\x03\x11\x03\x0c\x03\t\x03\t\x03\n\x04\t\x04\x07\x04\x10\x03\x0c\x03\t\x03\t\x03\n\x04\t\x03\t\x03\x10\x03\x0c\x03\t\x03\t\x03\n\x04\t\x03\t\x03\x10\x03\x0c\x03\t\x04\x07\x04\n\x04\t\x03\t\x03\x0f\x04\x0c\x03\n\x04\x05\x05\n\x04\t\x03\x03\x02\x04\x03\x0e\x04\r\x03\n\n\x01\x03\x17\x03\x02\x04\x03\x03\r\x05\r\x03\x0b\t\x01\x03\x17\x03\x02\x03\x04\x03\x0c\x05\x0e\x03\r\x05\x03\x03\x17\x03\t\x03\x0b\x05\x0f\x03\x15\x03\x17\x03\t\x03\n\x05\x10\x03\x14\x04\x17\x03\t\x03\t\x05\x11\x03\x14\x03\x18\x04\x07\x04\x08\x04\x13\x03\x14\x03\x19\x03\x07\x03\x08\x04\x14\x03\x13\x04\x0b\x04\n\x03\x06\x04\x07\x04\x15\x03\x0b\x01\x05\x05\x0c\x04\x0b\x04\x03\x04\x07\x03\x12\r\x06\n\r\x04\x0b\x0b\x06\x0f\x07\r\x06\t\x0e\x04\x0c\t\x07\x0f\x07\r\x07\x06\x10\x04\x0e\x05\t\x0f\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xaa') + +# 1-bit RLE, generated from res/torch_icon.png, 283 bytes +torch = (96, 64, b'\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00e\x06W\nT\x04\x06\x02S\x03\x07\x02S\x02\n\x01\x0b\x029\x05\x08\x02\t\x02\x08\x03:\x07\x06\x02\x0b\x01\x06\x02$(\n\x02\x03\x03%(\x0c\x01+\x02%\x01\x0b\x02+\x02%\x01\x0c\x01+\x02\x05\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x05\x01\x0b\x02+\x02\x04\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x04\x01\x0c\x01+\x02%\x01\x0b\x02\x03\n\x1e\x02\x05\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x05\x01\x0c\x01+\x02\x04\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x04\x01\x0b\x02+\x02%\x01\x0c\x01+\x02%\x01\x0b\x02+(\x0c\x01,(\n\x02\x03\x03L\x02\x0b\x01\x06\x02K\x02\t\x02\x08\x03H\x02\n\x01\x0b\x02G\x03\x07\x02U\x04\x06\x02V\nY\x06\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xe2') + # 1-bit RLE, generated from res/up_arrow.png, 16 bytes up_arrow = (16, 9, b'\x07\x02\r\x04\x0b\x06\t\x08\x07\n\x05\x0c\x03\x0e\x01 ') diff --git a/wasp/wasp.py b/wasp/wasp.py index a18c466..6016bd5 100644 --- a/wasp/wasp.py +++ b/wasp/wasp.py @@ -15,6 +15,7 @@ import widgets from apps.clock import ClockApp from apps.flashlight import FlashlightApp +from apps.launcher import LauncherApp from apps.testapp import TestApp class EventType(): @@ -86,6 +87,8 @@ class Manager(): self.applications = [] self.blank_after = 15 self.charging = True + self.launcher = LauncherApp() + self._brightness = 2 self._button = PinHandler(watch.button) @@ -142,23 +145,40 @@ class Manager(): quick application ring. Applications on the ring are not permitted to subscribe to :py:data`EventMask.SWIPE_LEFTRIGHT` events. + Swipe up is used to bring up the launcher. Clock applications are not + permitted to subscribe to :py:data`EventMask.SWIPE_UPDOWN` events since + they should expect to be the default application (and is important that + we can trigger the launcher from the default application). + :param int direction: The direction of the navigation """ app_list = self.applications if direction == EventType.LEFT: - i = app_list.index(self.app) + 1 - if i >= len(app_list): + if self.app in app_list: + i = app_list.index(self.app) + 1 + if i >= len(app_list): + i = 0 + else: i = 0 self.switch(app_list[i]) elif direction == EventType.RIGHT: - i = app_list.index(self.app) - 1 - if i < 0: - i = len(app_list)-1 + if self.app in app_list: + i = app_list.index(self.app) - 1 + if i < 0: + i = len(app_list)-1 + else: + i = 0 self.switch(app_list[i]) + elif direction == EventType.UP: + self.switch(self.launcher) + elif direction == EventType.DOWN: + if self.app != app_list[0]: + self.switch(app_list[0]) + else: + watch.vibrator.pulse() elif direction == EventType.HOME: - i = app_list.index(self.app) - if i != 0: + if self.app != app_list[0]: self.switch(app_list[0]) else: self.sleep()