From e09b951017761236f75137498cc3495a12a91f49 Mon Sep 17 00:00:00 2001 From: Adam Blair Date: Wed, 23 Jun 2021 15:31:42 -0600 Subject: [PATCH] Advanced alarm app Features: * Multiple alarms (up to 4) * Day of the week support * One time alarms * Snooze Changes to wasp-os for app support: * Added + and - to the 28pt and 36pt fonts * Checkboxes now require a click on the body of the checkbox if there is no label * Added a Toggle Button class that extends Button and stores a state like checkbox Signed-off-by: Adam Blair --- res/AlarmApp.png | Bin 6006 -> 5845 bytes wasp/apps/alarm.py | 339 ++++++++++++++++++++++++++++++++++++------- wasp/fonts/sans28.py | 130 +++++++++-------- wasp/fonts/sans36.py | 223 +++++++++++++++------------- wasp/widgets.py | 37 ++++- 5 files changed, 513 insertions(+), 216 deletions(-) diff --git a/res/AlarmApp.png b/res/AlarmApp.png index 183c3d6f0d9606178ba87f887c8a1be6d3d3cf56..7d8a7259edd5896da4fc0e1577f81dfc269ae4d9 100644 GIT binary patch literal 5845 zcmcJTXH*m0-o`@}NdyHU0v^C1pwc5qFG`U^Z-SIiBqBu-=@1drLjVCW0&-A##288t z5b2;I5Rf9hL`tX%gb+$7fpEvO*8An&_uhA{_pF<>CLi|f*)#Ls&+PsDo&+n4tH-#7 zxj`V%vEPjiY(O9uFW`8=#R{~18E(1`0tsgQZgANyJc}}cxP5Zyu$`7ULD5Om;V$Lk zi17CNooVn;gr7#f@-flv!SjH}2})Amz#L}rM#jo*U!n`xC0UMMzMTf<()nX9njC9n zR->2D=Wf>UQRlLg-Z>Uhe?`>j1XH2yv^0ql+EjTfG|X$NEL=%b6V;PXyHD@RyjZ!= z)s;k!E^B7)LEY|KFWG~FB5AEq-qUJUOZMK!FNCmxc8+3L^kRr0aXlpHxHufdbzBI< z9uEPr8gPPGU~Dm<|JLb;#(loRA|mynl=0Eg(Y3XA^v`8(&4flXJ?!#GS*~W71*-hm zv12MKDspmi!2dY7w<9YvlSbHFU0uD~d_ezR8`ONrWPJP>6DFXdtZe7tfO62W%A?U} z7|e+jZdLQ3-SzntZTjdN^H({j)!LzA2b3L#Y>hNCH_z4xDJm{ro@q@4hCMHwjBX*% z406;wGbwz7!zJ2|v?YsZYHGTLlVgjDE*up0dZ(KdT4bq}-`@>9IL0Af9ys5bDsA~@ zz^5_FW%1l>iY{}sHfXU|_fU%=H=wMaZ*}e@9OC)u5l5Xb`-Sg2J2f7sGR>q?JLXot zim3YUZw^>$YG?!xy_JL4)zyVkC$-hpeWrxCW0#heUcP!&Wyd1koS&bM!C*=(vW?F^ z71L$*n=1I=ujnI@@JwwK{j_FiSJTCl+*Kbw2wsPS!XiKh)J{sw6bL;Fq=zNWql6t^&Oec6ixdWWn zRqER4gpjYjzq_8VANM_d)+H{v~VAD3S=uLMNImvB7{Yn;fz+EEvTjEsz=Bi?12y{WG!wWh}z zpS^+577`WJLD5&fDm2UP)zkz%*qzVtb&kANg~Lh9D8Mj8HeM}vZSk{$iLosn>#SBK z=aa&$xtiaX1+mAQF$wr1FyH*Z!nGvu5X?hjQt8M|J)7P7sH=;Lohy8VR8 zyI2Js@98zESpTft4RpLNYvc-&PfAX1y-{wMC^$w{5;=X^4l21&s6pM_e7~uFy@I$y zYZn{(u(7O7Z+Kf&B4??#KIE zBW?wCNKC$zY_=Auor#i^A1-7KSp9TF%#LL7;DT|8$IokAmyz)~MFfARix4b<;2#`p zHz*5&ZLdyLy2&&K&YLi2uOYAVo({D*E>s{nxwLS9V3R(Q4!UkOV0U?XpM;29MoXK@ zQE)a}TU)MnEbf;W$0T|(eB#6Tgy;juy|f<|;ERiGNumc<<zOETJt?WHbGp-un)t$TfbkIHQLoj3=t(e+ z3Atvy3O^+jt2N6T<3~@=8wZbw3Hb_eVp!7tSc-I&O;``uOI`G1ktF+!Y`pvNIoeY= z2AmVB&B^+A7WV`?&Yae|k*{Wyz3(M|XP z)=5k%QO8!((eI#XRC0oYH-dn-ZG;?z3 z$HdfSY;7ddW$`!qEQRzy%km7|MD`Xh&3aeZuWRE|@d)9Cv#*^jjID6-?9CESuBXo> z;GMBc5aD)?rc*b%n8x<Gwr$h77G$9 z?K@GNX);phB;~MtC;72S?iJBwMq%5&nC$rV-z8M?)@IW&wThiw;%;Uh>^W1GdJCV= zNf5tBkx7i^_kYYld^@B0l;1{p09{0NbDp!C*}Jm;Ecqf1XGPmSe+~|HJ!N2IC2$CC zUK8HHr6^SRgt`XrTVBNr&z@L-KWa(Aoqf>21J4-SfF7=l?e%_jPg0AAAZ5sD20hov zO~f=%ZIgPwF-q23oofXs%*`Yo;I-PyUFgldnFFiausG?&e^ij8g2&O)f6M(TP zLQ*tCpV?q%EX)GsMMJ8!%sj1I%gT3>w=ulR2Qy2|gUHVFG6Kq-e;S*2RgG%(I=e!z z?F%PPg-7?LLn9L}h^6xhSwuc+@l+OFct&Vjmg7#x!z|1y_Vk9=NX%6O-z&;$y|!uc z!Xng(DVB7sjge62O3rk{-8pJt<+iuwvn#?>gtZl&%Db>1i&&FrnY_EWBtSplVbrD; zaO28pq6fd_y?w_O>dUSRkAV@NB!F?%YQ zQCLOXdZLds7r$*#WEB&NRR3wwqbbdr*S`+P;PpC=Gvds=KZ|Lmta|as2E_|V1lpBm z>~e6ZF>+WlXE=S$3s5y$(;gP^%BZzy6p$4Jy3U(0RKMYMglxks@g_cbY|;aMTnoXE zf%Pbd^Xe6RNOPsGCeb-04{TA%f*{|GO0w%IbQH*ea$?RrSEQ;fC2YVc}uE*VF zIxg1Ijpton8veRZ&}KB$K-z701GZ=-UrdNdx#u4$_ze1DS3)ASbCA!DT7@0I#u_n$HRF;BX|o&;+nc;@$V&vuCvt-zI0CAY=c4TXKUOKf2| zt%<3rMxK!EUkQFY*Ps|^)J7py=RVl`*{j2l&9;CxU*>`o^J;cvYc0FHR*5_jL{ECV z_E$gV0V8^M9=g@9+zr^hg@uI|FJ8bdm6WI-77&z!LYNVj+UvNsl}t?Sib-hOm|F7`4>0aR z&L;OxgXd=VFWgA;=nG-s4_4|v7Q9aP#bZbTivmOf!IZ-gT}X6eM(VoiB=hE!9wwl+ zzv3_N(Y8(0l~@+$t=oBQTu%w8b%NHpu5Z&>vHwaR)6Ftc^8qsKdDga`w)j`#)6GQp zV|nHu+)bwtTAN{GoQmyUWeeVh8{^ z(zQE~>vReUaJ8+z0x|G(2{?djzldw1KI|&CZ$_0%PyMU*fly+r4s&O=si{eIGJKXC zCng{G3Y1oQ-@(ku$%#i)D|~Bd$TUO#H?;uw<>Au5h7!0J_^l4u8A_d1Ra68LTO0h3 z#{{<3{p+;<^Gy7`V*J;yzWfU`g|K|FSEyO>60e1i>i1vOt z;*?OPSzG;QmM+5(?E&Q~C_xu)Cu56GqXSJ}2M9P__?7(V&a?2C=KyyOqnDC|flJUH zgCiq;3SxSqAt52YBryzt&L&meY@Z&&D#J8Tw+35Di6sC|<-Fh(PaMhaNhMmf3r!o}eoiHN`}^CIuvjc$ zv&8|ztqG&%927#UxM2FqJ@}%cic8noxKFkN48G)F#MWaP$%LtC@Ff^vt>cc6aK6-u zdIwuu312}Fh65~^l#)`MvEeFXO@>ikRm4~qY6@v8D=WXH0IR6AAt=lAEFWFoiy9eZ zjR*(m{uf5jzUlKiidd|Q`2f%1nG>wht#xi11AHgWAstrdkhx}AiBFOwO<%+>JvTH0 zIPAyH@UVTAwu(xj{2}Pu&A`CG$jI^WOXdTUKeL{N`Z^+mgM;IrszR`hjfgvz78U@t zwY3@foB?_H0Z=2AO22!<=TH^m+5J+bVD=`a{NAilRn&Z^KwPfVhufLs7KJvCA3yHF zS+mU90U$>iS7CJL(#sb2SF%SY@!8J|+xRWDPVmH)-dR*FlHxnc(Dm~2TIk8vGsXd z&F)vK)Tw4Mo;XUeA#hs<2PjV*&=9>mEXRO;@OfF#pm;kwY-6E&XlSUQ*T~?i2)aCq zK?eZ*)A%Zt>Q?2OzR~-ks%mR{n{-(9GdMCleAH=PIKcphiN6Y-Wy$SC!tp?;U^3FnHux%a7${TN0`IZpMf9G#){tt5-7=+;rgZ8;xmguL`THGuroAV!2|k^e0NZ zSY7q^^CW+c1y-_tYxIsxBY{Auth8->Fa08@w6qk64KVTHNo?YL3Gb_`>%W3gaT8U3 z8OjO}C>GM9=>NS2cvFHsu1>^z6j2)}nc9Jb3;7$fcwICH5}4R4`JcryvFK9(=mFt^ zxw&~i-}n2y3XT=Xsir7u!^YFC3LLJzb;w;)A?G)CaZ^jnl<@})N;P6Gmh7MAaSCu4 zF4g`MxzS9YMo3&su|rv?HBZdUJ4zqq3gDZ@f_B!(tkEIm--wD3Pe4P!+aBQ+eNPQ;>|xg4TPWE6Q7sgKXU)Lp$!{#I-0o=1Bgyc_kqh|KTfC= zp4o-B#c{igapVQ~4VUZ!S=MIgT4ttDHWnh8ZW48{HG)7O7JG9QdMLO0yzR7!Z0Gdx zb|%{Xy|(#QKgMq5P5>tF!yQt?kCQnDXtEU1Q3jphQ^ZN@ULVH2r0)CIf8-A z=qoUt@1Y{eMt**Nz^F_6)la$Y8c4m^z8_BnWV9~a?<+7AO^0~*4GzBdXhGXlUttq{ h$noEcWSc^I#3=L(CDCw-7WREDV`F(yXFE5{P*1kXI zmLE=e)G$q*ImrZWtBE)}b*+wO5t&3#fxucc6PR_n;X_m`0Z#g6{Rl%bIkRwa1naGSsjM%1@&7k=9gQs95=Y#B+H zW#|+VGKY1nwEp1vd!IC-b{1x2lyp)#G9#5TAaEmzDF!!$gwf3MKtkhu*uztM?lj8cHU-8eH*hwi&ZReDGWZ z!um2h`)HcO1D#0d!)z`z`}z8gAELxK9=W(!)Yv_hL4!=@Mn^~c`*jhfrT5B;bTGKX zZ|Fwpu9*J*72nnX66I?YTcWYHNHX`e`{pwckXuM-s9$sLcGhBRV8;PIw7mTOjBjyr z@~{&SS-`iR_y}wB$*HL+b1C?8Hq~1bV`I$wPGD$%Iab)Uk3qV^Uvm0db({SVT32iw zkH3omAx80dPv*Ek@!{KByA-b_B+@Xj0;^ycaS{D-hL1|c@nZt_`fW5=j|wVRLvtQ|mY=WyuX0 z+0l)N=-8LzPf}L?%B&tup-^gP-zhH6&K?bdJH%4-m`D~2*JnE-I`VkS%U|(E_Q@b| zHfpxME1%M$7}%`b`t-qsxdt~Z7EAQE3Y{4nd+0ISQt_bLscyE-PXpwitSiQ!Bx~DJ z-xbi(+S(A`($bQbmlw^%n=sweb#Lj(fvqYyQRn^};K9H+aFmvo4luobZXRsivkpC+Zs@b z!y(84KElgn;zS6-V%`2C=I@JTpT&ejd5~+b};p4^AQy2L{m=()*n>Y%Vt#^~5;FTvFRW z{&QCnQ4mWca%paEZebz!KovXe6dDo&^WYzxviK}95Ma20Z@(3B8s?F&0iWF84@mJc zES-poit2U#wtWbs-5x6wDCNhG9~%qJ@=&N_*q_~7)v^6aGvMax3fz0Gr6}XqwUghQ z9n+XQnM>CO2ASaSwUPXMU9o+lXX*{t2i8NS2`(2SvWuS6u}CvF-Fj4ag$;*FKbKMiPdZP+%2~1$kR~cvRlD-EWJh+t-PCe+#vGEC;&8 z2k!T_U+Ve0|Lu372#~b=3)+TupWmXI!qIn7Ab3GW9;arZfXeZ}Nke40cRg9ay=7-9 zliu!WQL&B==-+Aj`HOBC>vYke<2`G&+vr4pWmQGR`-frE_^Kyoi)*J8P)k+2tvCWp z+I@7a2SaYnzR-(DXcN!mI+bigTR(*#4-FBRfE&l3Z6m3JEMJRgUV(m99@CKpRp1;d9_agrDZ`ID)$0FE?A@^0@AAgI_weHkNxU?q%QI^I= zBPsmZZPlY~I~SX7n^0~kdYy7qrg?l4o6op8uX6XDiuA4{%B4WgTHx>+)ae?C6zsNC z5$(~~(5OV=wq52hC{;(8Aq-gLh2;n;_|3EQ)eb>U2Z13)4DvJ!=nG;Q5bIL z&^tIj?^E2%T_h?qo(3t9TJ@%y)f{~$qWM<_KdzsNR?m0l7ZP*`fuzowi9Qd0=pe!W7(9a>IoAsI+-Cbu5BnH${uq`BFgs3i_Bz|5S#b6J0Bc-fqA1?_voXOu-0B! za|bLa7HnLbe)p-#3f))8*&ak+6#OiKMpcNtzJD}Y3Ow}dugoPK$x!hMl7TduQxCs9 zD40^Kk;bcK9S}@wE^Z(ldf<&Y04twOl)aNzJ%|vn;S8jegM=mXYNb^saXf|xMHw%~`C%;rv4GvsZJBa>Hkm^C9^hl#V3li_D&C^Su1te)ti&=PjEQ&{&nFwl(? zc-hCp-0|Cb#rJ>?v)_2m-1Nzlc9IA19tu6!cr+m>D5$kY{P}axscx?R=z__!KxvxD zqW@3L^{)#$^>@Dnnr$}5iw%~-c83A+V`Fgzgt#vS0bZJ{LMlP4Ls|15yjmMIKyB}W zP;VxP*js_&I|El|-KSQ#slPgEi4dwgPD56+oWm)^s|VBc!8nyrq-m4OzW0>t@Yw2a7S#52G|>P@ffi zxDdQ`IlyqiuEgrC34wd}ZVf&~x8B|2MOUC}W$A(%l0( zM%Ik?4jc-I^{V++gL^ZKe5P73`qNlm4xI-fV(6o%bv5j_ByejD)i%@g_AlAtcTlwY zlNJ3d$F*)>rH4czU*pPSc?C33hdHG&~mc91T zAkMrx#Zmq0dJ#{Uvzp(DQOwAkIGWt%YvDj>g1cFqY9rffN-7(YB9w284SMS>rA{E^iQH6C7e7x;wiYvriT)E>^`?SP?T_h8z0;a!dGRO%=obw$ph zPM!lf4y0~jVKK*7%Ac~aO76F4@-9&HIXis%Ic+@CINgx|>-8H^ zEj7lxc)`lT;t0t?L1q^getk<=UaCE(_h-5%<^3jAf%xDxK!crav~H4}$BF*R*Z`l( zEldsfpGhzYWJq>SPRGgqJW$rX1fPQkjFB1KYR6f+V)%%&6C4gVjf^+}d_+Jn78G>9 zOkM&gUBD?^ym+w*=#Qr-zi)WVeV?+T+LAQOD6T}bhwS~BG&3`chjkJEbce*j|De(Q zKQz6b@^)(PNnoSq@v9}yDUBb_jTC0Ei`@Ml?Kj+&6PH-yU0ZN^ATK za+li4=J0lWw2>O!-Q5&_0|PWC+FK05BW>~ePwgqcX9NY`EBi7t zlet~MX}}JPd7BRuK#`FgJ(qW1PtS9NX9!ig_+kY6kRbZwx9z5ZtfW}izTRHInZYXP z)KQ;vl{h&$Dc!Ye`eg6qsS;^B^3*U{5a1qUVnM-`v1g#n4E^FnaVP2a*>!Oh=g$IT zwW#FnQBAf-oK983mH<+~uMIfW2{6zJ>;RSiQ=BgzmdL>AT%^-msD*|BHb^@(wAJMl zpb6^}Kxh=AFeo4^H#avgZ>j_ihw@%$6vX(?i0Ti+PS>M1iYR8pLx5IDn?}$2Y2OP^+7!0zTJY z`N_eCEy0p;H@M(p!i{8ImHioq!s0=ZqOvmLz}5UOCB-zdK!Axijx+P}a6k<0p$COy zZ++?|BMbTY`3uL^ffJrfIFIA5`*3(FZ$d%P4fh!nYwK$vUWN)E3MH)@-IXFv+Y}d< zmO9*LA-kI%US6ARc?6mtZHgr>Bcd+py_NUx4|26dJKP)8yK&>OwU*cJ8HFXDpd?w4`YG=oF4a=rH#>Q{%m6?^^CGySyYWMUs+|7u}+X}!sdAtLt zoiAl(>9J;3YDLWfq&WcD{9u#MVlJZ!G6Ben52`y^ROf!Bm1A>50{xv|3(dQe50I0> zPLM1-9;47@v-tyM ztdM|!!tFY@=_<`wR`_8BI!!yKP!iyvq5Hp-yuU_n>kSeNLFTev^>50{y>LgX^Ijdc z!Gnshm{kDQ01JNuuWx9|1&3d{bZK~Di$;AVCMHH(TYD#=1&2E&VASxyg3F+5WFTBx z0DxG;J^B5IB;m@Fv`pb?OcqqFE*}`Dv^99J54&SnbTC2U4Hv@n&CksVxP}3Lowb2^#{Ts92w30BeXE&BYdfm{96jEOc;o3< Vz3tI-2jJ--J*~U2Dh<15{{<#&-Ms(+ diff --git a/wasp/apps/alarm.py b/wasp/apps/alarm.py index c3c1847..4d87b0c 100644 --- a/wasp/apps/alarm.py +++ b/wasp/apps/alarm.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: LGPL-3.0-or-later # Copyright (C) 2020 Daniel Thompson # Copyright (C) 2020 Joris Warmbier +# Copyright (C) 2021 Adam Blair """Alarm Application ~~~~~~~~~~~~~~~~~~~~ @@ -12,11 +13,12 @@ An application to set a vibration alarm. All settings can be accessed from the W Screenshot of the Alarm Application """ - import wasp import fonts import time import widgets +import array +from micropython import const # 2-bit RLE, generated from res/alarm_icon.png, 390 bytes icon = ( @@ -49,7 +51,29 @@ icon = ( b'\x11\x83\x17' ) -class AlarmApp(): +# Enabled masks +_MONDAY = const(0x01) +_TUESDAY = const(0x02) +_WEDNESDAY = const(0x04) +_THURSDAY = const(0x08) +_FRIDAY = const(0x10) +_SATURDAY = const(0x20) +_SUNDAY = const(0x40) +_WEEKDAYS = const(0x1F) +_WEEKENDS = const(0x60) +_EVERY_DAY = const(0x7F) +_IS_ACTIVE = const(0x80) + +# Alarm data indices +_HOUR_IDX = const(0) +_MIN_IDX = const(1) +_ENABLED_IDX = const(2) + +# Pages +_HOME_PAGE = const(-1) +_RINGING_PAGE = const(-2) + +class AlarmApp: """Allows the user to set a vibration alarm. """ NAME = 'Alarm' @@ -57,83 +81,296 @@ class AlarmApp(): def __init__(self): """Initialize the application.""" - self.active = widgets.Checkbox(104, 200) - self.hours = widgets.Spinner(50, 60, 0, 23, 2) - self.minutes = widgets.Spinner(130, 60, 0, 59, 2) - self.hours.value = 7 - self.ringing = False + self.page = _HOME_PAGE + self.alarms = (bytearray(3), bytearray(3), bytearray(3), bytearray(3)) + self.pending_alarms = array.array('d', [0.0, 0.0, 0.0, 0.0]) + + # Set a nice default + self.num_alarms = 1 + for alarm in self.alarms: + alarm[_HOUR_IDX] = 8 + alarm[_MIN_IDX] = 0 + alarm[_ENABLED_IDX] = 0 + self.alarms[0][_ENABLED_IDX] = _WEEKDAYS + def foreground(self): """Activate the application.""" + + self.del_alarm_btn = widgets.Button(170, 204, 70, 35, 'DEL') + self.hours_wid = widgets.Spinner(50, 30, 0, 23, 2) + self.min_wid = widgets.Spinner(130, 30, 0, 59, 2) + self.day_btns = (widgets.ToggleButton(10, 145, 40, 35, 'Mo'), + widgets.ToggleButton(55, 145, 40, 35, 'Tu'), + widgets.ToggleButton(100, 145, 40, 35, 'We'), + widgets.ToggleButton(145, 145, 40, 35, 'Th'), + widgets.ToggleButton(190, 145, 40, 35, 'Fr'), + widgets.ToggleButton(10, 185, 40, 35, 'Sa'), + widgets.ToggleButton(55, 185, 40, 35, 'Su')) + self.alarm_checks = (widgets.Checkbox(200, 57), widgets.Checkbox(200, 102), + widgets.Checkbox(200, 147), widgets.Checkbox(200, 192)) + + self._deactivate_pending_alarms() self._draw() - wasp.system.request_event(wasp.EventMask.TOUCH) + + wasp.system.request_event(wasp.EventMask.TOUCH | wasp.EventMask.SWIPE_LEFTRIGHT | wasp.EventMask.BUTTON) wasp.system.request_tick(1000) - if self.active.state: - wasp.system.cancel_alarm(self.current_alarm, self._alert) def background(self): """De-activate the application.""" - if self.active.state: - self._set_current_alarm() - wasp.system.set_alarm(self.current_alarm, self._alert) - if self.ringing: - self.ringing = False + if self.page > _HOME_PAGE: + self._save_alarm() + + self.page = _HOME_PAGE + + del self.del_alarm_btn + del self.hours_wid + del self.min_wid + del self.alarm_checks + del self.day_btns + + self._set_pending_alarms() def tick(self, ticks): """Notify the application that its periodic tick is due.""" - if self.ringing: + if self.page == _RINGING_PAGE: wasp.watch.vibrator.pulse(duty=50, ms=500) wasp.system.keep_awake() else: wasp.system.bar.update() + def press(self, button, state): + """"Notify the application of a button press event.""" + if self.page == _RINGING_PAGE: + self._snooze() + wasp.system.navigate(wasp.EventType.HOME) + + def swipe(self, event): + """"Notify the application of a swipe event.""" + if self.page == _RINGING_PAGE: + self._silence_alarm() + elif self.page > _HOME_PAGE: + self._save_alarm() + self._draw() + else: + wasp.system.navigate(event[0]) + def touch(self, event): """Notify the application of a touchscreen touch event.""" - if self.ringing: - mute = wasp.watch.display.mute - self.ringing = False - mute(True) - self._draw() - mute(False) - elif self.hours.touch(event) or self.minutes.touch(event) or \ - self.active.touch(event): - pass + if self.page == _RINGING_PAGE: + self._silence_alarm() + elif self.page > _HOME_PAGE: + if self.hours_wid.touch(event) or self.min_wid.touch(event): + return + for day_btn in self.day_btns: + if day_btn.touch(event): + return + if self.del_alarm_btn.touch(event): + self._remove_alarm(self.page) + elif self.page == _HOME_PAGE: + for index, checkbox in enumerate(self.alarm_checks): + if checkbox.touch(event): + if checkbox.state: + self.alarms[index][_ENABLED_IDX] |= _IS_ACTIVE + else: + self.alarms[index][_ENABLED_IDX] &= ~_IS_ACTIVE + self._draw(index) + return + for index, alarm in enumerate(self.alarms): + # Open edit page for clicked alarms + if index < self.num_alarms and event[1] < 190 \ + and 60 + (index * 45) < event[2] < 60 + ((index + 1) * 45): + self.page = index + self._draw() + return + # Add new alarm if plus clicked + elif index == self.num_alarms and 60 + (index * 45) < event[2]: + self.num_alarms += 1 + self._draw(index) + return - def _draw(self): - """Draw the display from scratch.""" - draw = wasp.watch.drawable - if not self.ringing: - draw.fill() + def _remove_alarm(self, alarm_index): + # Shift alarm indices + for index in range(alarm_index, 3): + self.alarms[index][_HOUR_IDX] = self.alarms[index + 1][_HOUR_IDX] + self.alarms[index][_MIN_IDX] = self.alarms[index + 1][_MIN_IDX] + self.alarms[index][_ENABLED_IDX] = self.alarms[index + 1][_ENABLED_IDX] + self.pending_alarms[index] = self.pending_alarms[index + 1] - sbar = wasp.system.bar - sbar.clock = True - sbar.draw() + # Set last alarm to default + self.alarms[3][_HOUR_IDX] = 8 + self.alarms[3][_MIN_IDX] = 0 + self.alarms[3][_ENABLED_IDX] = 0 - draw.set_font(fonts.sans28) - draw.string(':', 110, 120-14, width=20) + self.page = _HOME_PAGE + self.num_alarms -= 1 + self._draw() - self.active.draw() - self.hours.draw() - self.minutes.draw() + def _save_alarm(self): + alarm = self.alarms[self.page] + alarm[_HOUR_IDX] = self.hours_wid.value + alarm[_MIN_IDX] = self.min_wid.value + for day_idx, day_btn in enumerate(self.day_btns): + if day_btn.state: + alarm[_ENABLED_IDX] |= 1 << day_idx + else: + alarm[_ENABLED_IDX] &= ~(1 << day_idx) + + self.page = _HOME_PAGE + + def _draw(self, update_alarm_row=-1): + if self.page == _RINGING_PAGE: + self._draw_ringing_page() + elif self.page > _HOME_PAGE: + self._draw_edit_page() else: + self._draw_home_page(update_alarm_row) + + def _draw_ringing_page(self): + draw = wasp.watch.drawable + + draw.set_color(wasp.system.theme('bright')) + draw.fill() + draw.set_font(fonts.sans24) + draw.string("Alarm", 0, 150, width=240) + draw.blit(icon, 73, 50) + draw.line(35, 1, 35, 239) + draw.string('Z', 10, 80) + draw.string('z', 10, 110) + draw.string('z', 10, 140) + + def _draw_edit_page(self): + draw = wasp.watch.drawable + alarm = self.alarms[self.page] + + draw.fill() + self._draw_system_bar() + + self.hours_wid.value = alarm[_HOUR_IDX] + self.min_wid.value = alarm[_MIN_IDX] + draw.set_font(fonts.sans28) + draw.string(':', 110, 90-14, width=20) + + self.del_alarm_btn.draw() + self.hours_wid.draw() + self.min_wid.draw() + for day_idx, day_btn in enumerate(self.day_btns): + day_btn.state = alarm[_ENABLED_IDX] & (1 << day_idx) + day_btn.draw() + + def _draw_home_page(self, update_alarm_row=_HOME_PAGE): + draw = wasp.watch.drawable + if update_alarm_row == _HOME_PAGE: + draw.set_color(wasp.system.theme('bright')) draw.fill() - draw.set_font(fonts.sans24) - draw.string("Alarm", 0, 150, width=240) - draw.blit(icon, 73, 50) + self._draw_system_bar() + draw.line(0, 50, 240, 50, width=1, color=wasp.system.theme('bright')) + + for index in range(len(self.alarms)): + if index < self.num_alarms and (update_alarm_row == _HOME_PAGE or update_alarm_row == index): + self._draw_alarm_row(index) + elif index == self.num_alarms: + # Draw the add button + draw.set_color(wasp.system.theme('bright')) + draw.set_font(fonts.sans28) + draw.string('+', 100, 60 + (index * 45)) + + def _draw_alarm_row(self, index): + draw = wasp.watch.drawable + alarm = self.alarms[index] + + self.alarm_checks[index].state = alarm[_ENABLED_IDX] & _IS_ACTIVE + self.alarm_checks[index].draw() + + if self.alarm_checks[index].state: + draw.set_color(wasp.system.theme('bright')) + else: + draw.set_color(wasp.system.theme('mid')) + + draw.set_font(fonts.sans28) + draw.string("{:02d}:{:02d}".format(alarm[_HOUR_IDX], alarm[_MIN_IDX]), 10, 60 + (index * 45), width=120) + + draw.set_font(fonts.sans18) + draw.string(self._get_repeat_code(alarm[_ENABLED_IDX]), 130, 70 + (index * 45), width=60) + + draw.line(0, 95 + (index * 45), 240, 95 + (index * 45), width=1, color=wasp.system.theme('bright')) + + def _draw_system_bar(self): + sbar = wasp.system.bar + sbar.clock = True + sbar.draw() def _alert(self): - self.ringing = True + self.page = _RINGING_PAGE wasp.system.wake() wasp.system.switch(self) - def _set_current_alarm(self): + def _snooze(self): now = wasp.watch.rtc.get_localtime() - yyyy = now[0] - mm = now[1] - dd = now[2] - HH = self.hours.value - MM = self.minutes.value - if HH < now[3] or (HH == now[3] and MM <= now[4]): - dd += 1 - self.current_alarm = (time.mktime((yyyy, mm, dd, HH, MM, 0, 0, 0, 0))) + alarm = (now[0], now[1], now[2], now[3], now[4] + 10, now[5], 0, 0, 0) + wasp.system.set_alarm(time.mktime(alarm), self._alert) + + def _silence_alarm(self): + mute = wasp.watch.display.mute + mute(True) + self._draw() + mute(False) + wasp.system.navigate(wasp.EventType.HOME) + + def _set_pending_alarms(self): + now = wasp.watch.rtc.get_localtime() + for index, alarm in enumerate(self.alarms): + if index < self.num_alarms and alarm[_ENABLED_IDX] & _IS_ACTIVE: + yyyy = now[0] + mm = now[1] + dd = now[2] + HH = alarm[_HOUR_IDX] + MM = alarm[_MIN_IDX] + + # If next alarm is tomorrow increment the day + if HH < now[3] or (HH == now[3] and MM <= now[4]): + dd += 1 + + pending_time = time.mktime((yyyy, mm, dd, HH, MM, 0, 0, 0, 0)) + + # If this is not a one time alarm find the next day of the week that is enabled + if alarm[_ENABLED_IDX] & ~_IS_ACTIVE != 0: + for _i in range(7): + if (1 << time.localtime(pending_time)[6]) & alarm[_ENABLED_IDX] == 0: + dd += 1 + pending_time = time.mktime((yyyy, mm, dd, HH, MM, 0, 0, 0, 0)) + else: + break + + self.pending_alarms[index] = pending_time + wasp.system.set_alarm(pending_time, self._alert) + else: + self.pending_alarms[index] = 0.0 + + def _deactivate_pending_alarms(self): + now = wasp.watch.rtc.get_localtime() + now = time.mktime((now[0], now[1], now[2], now[3], now[4], now[5], 0, 0, 0)) + for index, alarm in enumerate(self.alarms): + pending_alarm = self.pending_alarms[index] + if not pending_alarm == 0.0: + wasp.system.cancel_alarm(pending_alarm, self._alert) + # If this is a one time alarm and in the past disable it + if alarm[_ENABLED_IDX] & ~_IS_ACTIVE == 0 and pending_alarm <= now: + alarm[_ENABLED_IDX] = 0 + + @staticmethod + def _get_repeat_code(days): + # Ignore the is_active bit + days = days & ~_IS_ACTIVE + + if days == _WEEKDAYS: + return "wkds" + elif days == _WEEKENDS: + return "wkns" + elif days == _EVERY_DAY: + return "evry" + elif days == 0: + return "once" + else: + return "cust" \ No newline at end of file diff --git a/wasp/fonts/sans28.py b/wasp/fonts/sans28.py index 9a123f3..72915b8 100644 --- a/wasp/fonts/sans28.py +++ b/wasp/fonts/sans28.py @@ -1,6 +1,6 @@ # Code generated by font_to_py.py. -# Font: DejaVuSans.ttf -# Cmd: ./tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 28 -e 58 -s 48 -l 58 wasp/fonts/sans28.py +# Font: DejaVuSans.ttf Char set: +-0123456789: +# Cmd: tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 28 -e 58 -c 0123456789:+- wasp/fonts/sans28.py version = '0.33' def height(): @@ -10,7 +10,7 @@ def baseline(): return 27 def max_width(): - return 24 + return 31 def hmap(): return True @@ -22,7 +22,7 @@ def monospaced(): return False def min_ch(): - return 48 + return 43 def max_ch(): return 58 @@ -31,66 +31,78 @@ _font =\ b'\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ b'\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x00\x00\x00\x00'\ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00'\ -b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x18\x00\x00\xfe\x00\x03\xff\x80'\ -b'\x07\xff\xc0\x0f\x83\xe0\x0f\x01\xe0\x1e\x00\xf0\x1e\x00\xf0\x1e'\ -b'\x00\xf0\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00'\ +b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x1f\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x00\x00\x03'\ +b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\ +b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\ +b'\x80\x00\x0f\xff\xff\xe0\x0f\xff\xff\xe0\x0f\xff\xff\xe0\x00\x03'\ +b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\ +b'\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03\x80\x00\x00\x03'\ +b'\x80\x00\x00\x03\x80\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x3f\xf0\x3f\xf0\x3f\xf0\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00'\ +b'\x00\xfe\x00\x03\xff\x80\x07\xff\xc0\x0f\x83\xe0\x0f\x01\xe0\x1e'\ +b'\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x3c\x00\x78\x3c\x00\x78\x3c\x00'\ b'\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78'\ -b'\x3c\x00\x78\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x0f\x01\xe0\x0f'\ -b'\x83\xe0\x07\xff\xc0\x03\xff\x80\x00\xfe\x00\x18\x00\x00\xfe\x00'\ -b'\x07\xfe\x00\x07\xfe\x00\x07\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00'\ +b'\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x1e\x00\xf0\x1e\x00\xf0\x1e'\ +b'\x00\xf0\x0f\x01\xe0\x0f\x83\xe0\x07\xff\xc0\x03\xff\x80\x00\xfe'\ +b'\x00\x18\x00\x00\xfe\x00\x07\xfe\x00\x07\xfe\x00\x07\x1e\x00\x00'\ b'\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e'\ b'\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00'\ b'\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00'\ -b'\x1e\x00\x00\x1e\x00\x07\xff\xf8\x07\xff\xf8\x07\xff\xf8\x18\x00'\ -b'\x01\xfc\x00\x0f\xff\x80\x1f\xff\xc0\x1f\x07\xe0\x18\x01\xe0\x10'\ -b'\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01'\ -b'\xf0\x00\x01\xe0\x00\x03\xe0\x00\x07\xc0\x00\x0f\x80\x00\x1f\x00'\ -b'\x00\x3e\x00\x00\x7e\x00\x00\xfc\x00\x01\xf8\x00\x03\xf0\x00\x07'\ -b'\xe0\x00\x0f\xc0\x00\x1f\x80\x00\x1f\xff\xf0\x1f\xff\xf0\x1f\xff'\ -b'\xf0\x18\x00\x03\xfe\x00\x0f\xff\x80\x0f\xff\xc0\x0c\x03\xe0\x00'\ -b'\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01'\ -b'\xe0\x00\x03\xc0\x00\xff\x80\x00\xfe\x00\x00\xff\xc0\x00\x03\xe0'\ -b'\x00\x00\xf0\x00\x00\xf8\x00\x00\x78\x00\x00\x78\x00\x00\x78\x00'\ -b'\x00\x78\x00\x00\xf8\x00\x01\xf0\x18\x03\xf0\x1f\xff\xe0\x1f\xff'\ -b'\x80\x07\xfe\x00\x18\x00\x00\x07\xc0\x00\x0f\xc0\x00\x0f\xc0\x00'\ -b'\x1f\xc0\x00\x3b\xc0\x00\x3b\xc0\x00\x73\xc0\x00\xf3\xc0\x00\xe3'\ -b'\xc0\x01\xc3\xc0\x03\xc3\xc0\x03\x83\xc0\x07\x03\xc0\x07\x03\xc0'\ -b'\x0e\x03\xc0\x1e\x03\xc0\x1c\x03\xc0\x38\x03\xc0\x3f\xff\xfc\x3f'\ -b'\xff\xfc\x3f\xff\xfc\x00\x03\xc0\x00\x03\xc0\x00\x03\xc0\x00\x03'\ -b'\xc0\x00\x03\xc0\x00\x03\xc0\x18\x00\x0f\xff\xc0\x0f\xff\xc0\x0f'\ -b'\xff\xc0\x0f\x00\x00\x0f\x00\x00\x0f\x00\x00\x0f\x00\x00\x0f\x00'\ -b'\x00\x0f\x00\x00\x0f\xfc\x00\x0f\xff\x00\x0f\xff\xc0\x0c\x0f\xc0'\ -b'\x00\x03\xe0\x00\x01\xe0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00'\ -b'\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01\xe0\x00\x03\xe0\x18\x07'\ -b'\xc0\x1f\xff\xc0\x1f\xff\x00\x07\xfc\x00\x18\x00\x00\x3f\x80\x00'\ -b'\xff\xe0\x03\xff\xe0\x07\xe0\x60\x0f\x80\x00\x0f\x00\x00\x1f\x00'\ -b'\x00\x1e\x00\x00\x1e\x00\x00\x3c\x00\x00\x3c\x7f\x00\x3c\xff\xc0'\ -b'\x3d\xff\xe0\x3f\x83\xf0\x3e\x00\xf0\x3e\x00\xf8\x3c\x00\x78\x3c'\ -b'\x00\x78\x3c\x00\x78\x1c\x00\x78\x1c\x00\x78\x1e\x00\xf8\x0e\x00'\ -b'\xf0\x0f\x83\xf0\x07\xff\xe0\x03\xff\x80\x00\xfe\x00\x18\x00\x1f'\ -b'\xff\xf0\x1f\xff\xf0\x1f\xff\xf0\x00\x01\xe0\x00\x01\xe0\x00\x03'\ -b'\xe0\x00\x03\xc0\x00\x03\xc0\x00\x07\xc0\x00\x07\x80\x00\x07\x80'\ -b'\x00\x0f\x80\x00\x0f\x00\x00\x0f\x00\x00\x1f\x00\x00\x1e\x00\x00'\ -b'\x1e\x00\x00\x3e\x00\x00\x3c\x00\x00\x3c\x00\x00\x78\x00\x00\x78'\ -b'\x00\x00\x78\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01\xe0\x00'\ -b'\x18\x00\x00\xfe\x00\x03\xff\x80\x0f\xff\xe0\x0f\x83\xe0\x1f\x01'\ -b'\xf0\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0\x0f\x01\xe0'\ -b'\x07\x83\xc0\x03\xff\x80\x00\xfe\x00\x07\xff\xc0\x0f\x83\xe0\x1e'\ -b'\x00\xf0\x3e\x00\xf0\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3c\x00'\ -b'\x78\x3e\x00\xf8\x1e\x00\xf0\x1f\x83\xf0\x0f\xff\xe0\x07\xff\xc0'\ -b'\x00\xfe\x00\x18\x00\x00\xfe\x00\x03\xff\x00\x0f\xff\xc0\x1f\x83'\ -b'\xe0\x1e\x00\xe0\x3e\x00\xf0\x3c\x00\x70\x3c\x00\x70\x3c\x00\x78'\ -b'\x3c\x00\x78\x3c\x00\x78\x3e\x00\xf8\x1e\x00\xf8\x1f\x83\xf8\x0f'\ -b'\xff\x78\x07\xfe\x78\x01\xfc\x78\x00\x00\xf8\x00\x00\xf0\x00\x00'\ -b'\xf0\x00\x01\xf0\x00\x01\xe0\x00\x03\xe0\x0c\x0f\xc0\x0f\xff\x80'\ -b'\x0f\xfe\x00\x03\xf8\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ -b'\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00'\ -b'\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ -b'\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00' +b'\x1e\x00\x00\x1e\x00\x00\x1e\x00\x00\x1e\x00\x07\xff\xf8\x07\xff'\ +b'\xf8\x07\xff\xf8\x18\x00\x01\xfc\x00\x0f\xff\x80\x1f\xff\xc0\x1f'\ +b'\x07\xe0\x18\x01\xe0\x10\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00'\ +b'\xf0\x00\x00\xf0\x00\x01\xf0\x00\x01\xe0\x00\x03\xe0\x00\x07\xc0'\ +b'\x00\x0f\x80\x00\x1f\x00\x00\x3e\x00\x00\x7e\x00\x00\xfc\x00\x01'\ +b'\xf8\x00\x03\xf0\x00\x07\xe0\x00\x0f\xc0\x00\x1f\x80\x00\x1f\xff'\ +b'\xf0\x1f\xff\xf0\x1f\xff\xf0\x18\x00\x03\xfe\x00\x0f\xff\x80\x0f'\ +b'\xff\xc0\x0c\x03\xe0\x00\x01\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00'\ +b'\xf0\x00\x00\xf0\x00\x01\xe0\x00\x03\xc0\x00\xff\x80\x00\xfe\x00'\ +b'\x00\xff\xc0\x00\x03\xe0\x00\x00\xf0\x00\x00\xf8\x00\x00\x78\x00'\ +b'\x00\x78\x00\x00\x78\x00\x00\x78\x00\x00\xf8\x00\x01\xf0\x18\x03'\ +b'\xf0\x1f\xff\xe0\x1f\xff\x80\x07\xfe\x00\x18\x00\x00\x07\xc0\x00'\ +b'\x0f\xc0\x00\x0f\xc0\x00\x1f\xc0\x00\x3b\xc0\x00\x3b\xc0\x00\x73'\ +b'\xc0\x00\xf3\xc0\x00\xe3\xc0\x01\xc3\xc0\x03\xc3\xc0\x03\x83\xc0'\ +b'\x07\x03\xc0\x07\x03\xc0\x0e\x03\xc0\x1e\x03\xc0\x1c\x03\xc0\x38'\ +b'\x03\xc0\x3f\xff\xfc\x3f\xff\xfc\x3f\xff\xfc\x00\x03\xc0\x00\x03'\ +b'\xc0\x00\x03\xc0\x00\x03\xc0\x00\x03\xc0\x00\x03\xc0\x18\x00\x0f'\ +b'\xff\xc0\x0f\xff\xc0\x0f\xff\xc0\x0f\x00\x00\x0f\x00\x00\x0f\x00'\ +b'\x00\x0f\x00\x00\x0f\x00\x00\x0f\x00\x00\x0f\xfc\x00\x0f\xff\x00'\ +b'\x0f\xff\xc0\x0c\x0f\xc0\x00\x03\xe0\x00\x01\xe0\x00\x00\xf0\x00'\ +b'\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x00\xf0\x00\x01'\ +b'\xe0\x00\x03\xe0\x18\x07\xc0\x1f\xff\xc0\x1f\xff\x00\x07\xfc\x00'\ +b'\x18\x00\x00\x3f\x80\x00\xff\xe0\x03\xff\xe0\x07\xe0\x60\x0f\x80'\ +b'\x00\x0f\x00\x00\x1f\x00\x00\x1e\x00\x00\x1e\x00\x00\x3c\x00\x00'\ +b'\x3c\x7f\x00\x3c\xff\xc0\x3d\xff\xe0\x3f\x83\xf0\x3e\x00\xf0\x3e'\ +b'\x00\xf8\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x1c\x00\x78\x1c\x00'\ +b'\x78\x1e\x00\xf8\x0e\x00\xf0\x0f\x83\xf0\x07\xff\xe0\x03\xff\x80'\ +b'\x00\xfe\x00\x18\x00\x1f\xff\xf0\x1f\xff\xf0\x1f\xff\xf0\x00\x01'\ +b'\xe0\x00\x01\xe0\x00\x03\xe0\x00\x03\xc0\x00\x03\xc0\x00\x07\xc0'\ +b'\x00\x07\x80\x00\x07\x80\x00\x0f\x80\x00\x0f\x00\x00\x0f\x00\x00'\ +b'\x1f\x00\x00\x1e\x00\x00\x1e\x00\x00\x3e\x00\x00\x3c\x00\x00\x3c'\ +b'\x00\x00\x78\x00\x00\x78\x00\x00\x78\x00\x00\xf0\x00\x00\xf0\x00'\ +b'\x00\xf0\x00\x01\xe0\x00\x18\x00\x00\xfe\x00\x03\xff\x80\x0f\xff'\ +b'\xe0\x0f\x83\xe0\x1f\x01\xf0\x1e\x00\xf0\x1e\x00\xf0\x1e\x00\xf0'\ +b'\x1e\x00\xf0\x0f\x01\xe0\x07\x83\xc0\x03\xff\x80\x00\xfe\x00\x07'\ +b'\xff\xc0\x0f\x83\xe0\x1e\x00\xf0\x3e\x00\xf0\x3c\x00\x78\x3c\x00'\ +b'\x78\x3c\x00\x78\x3c\x00\x78\x3e\x00\xf8\x1e\x00\xf0\x1f\x83\xf0'\ +b'\x0f\xff\xe0\x07\xff\xc0\x00\xfe\x00\x18\x00\x00\xfe\x00\x03\xff'\ +b'\x00\x0f\xff\xc0\x1f\x83\xe0\x1e\x00\xe0\x3e\x00\xf0\x3c\x00\x70'\ +b'\x3c\x00\x70\x3c\x00\x78\x3c\x00\x78\x3c\x00\x78\x3e\x00\xf8\x1e'\ +b'\x00\xf8\x1f\x83\xf8\x0f\xff\x78\x07\xfe\x78\x01\xfc\x78\x00\x00'\ +b'\xf8\x00\x00\xf0\x00\x00\xf0\x00\x01\xf0\x00\x01\xe0\x00\x03\xe0'\ +b'\x0c\x0f\xc0\x0f\xff\x80\x0f\xfe\x00\x03\xf8\x00\x0c\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00'\ +b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00'\ +b'\x0f\x00\x0f\x00' _index =\ -b'\x00\x00\x38\x00\x8b\x00\xde\x00\x31\x01\x84\x01\xd7\x01\x2a\x02'\ -b'\x7d\x02\xd0\x02\x23\x03\x76\x03\xae\x03' +b'\x00\x00\x38\x00\x00\x00\xa6\x00\x00\x00\x00\x00\xde\x00\x31\x01'\ +b'\x84\x01\xd7\x01\x2a\x02\x7d\x02\xd0\x02\x23\x03\x76\x03\xc9\x03'\ +b'\x1c\x04\x54\x04' _mvfont = memoryview(_font) _mvi = memoryview(_index) @@ -98,7 +110,7 @@ ifb = lambda l : l[0] | (l[1] << 8) def get_ch(ch): oc = ord(ch) - ioff = 2 * (oc - 48 + 1) if oc >= 48 and oc <= 58 else 0 + ioff = 2 * (oc - 43 + 1) if oc >= 43 and oc <= 58 else 0 doff = ifb(_mvi[ioff : ]) width = ifb(_mvfont[doff : ]) diff --git a/wasp/fonts/sans36.py b/wasp/fonts/sans36.py index 683dbb5..642fd5d 100644 --- a/wasp/fonts/sans36.py +++ b/wasp/fonts/sans36.py @@ -1,6 +1,6 @@ # Code generated by font_to_py.py. -# Font: DejaVuSans.ttf -# Cmd: tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 36 -e 58 -s 48 -l 58 wasp/fonts/sans36.py +# Font: DejaVuSans.ttf Char set: +-0123456789: +# Cmd: tools/micropython-font-to-py/font_to_py.py /usr/share/fonts/dejavu/DejaVuSans.ttf --xmap 36 -e 58 -c 0123456789:+- wasp/fonts/sans36.py version = '0.33' def height(): @@ -10,7 +10,7 @@ def baseline(): return 35 def max_width(): - return 30 + return 39 def hmap(): return True @@ -22,7 +22,7 @@ def monospaced(): return False def min_ch(): - return 48 + return 43 def max_ch(): return 58 @@ -32,107 +32,126 @@ b'\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ b'\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0\x03\xe0\x03\xe0'\ b'\x03\xe0\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0'\ -b'\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x00\x00\x1e\x00\x00\x0f\xc0\x00'\ -b'\x00\x7f\xf8\x00\x00\xff\xfc\x00\x01\xff\xfe\x00\x03\xf0\x3f\x00'\ -b'\x03\xe0\x1f\x00\x07\xc0\x0f\x80\x07\x80\x07\x80\x0f\x80\x07\xc0'\ -b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x1e\x00\x01\xe0'\ -b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\ -b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\ -b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x0f\x00\x03\xc0'\ -b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x07\xc0\x07\x80\x07\x80'\ -b'\x07\xc0\x0f\x80\x07\xe0\x1f\x00\x03\xf0\x3f\x00\x01\xff\xfe\x00'\ -b'\x00\xff\xfc\x00\x00\x7f\xf8\x00\x00\x1f\xe0\x00\x1e\x00\x00\x00'\ -b'\x00\x00\x00\x1f\x80\x00\x01\xff\x80\x00\x07\xff\x80\x00\x07\xff'\ -b'\x80\x00\x07\xe7\x80\x00\x06\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ -b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ -b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ -b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ -b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ -b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ -b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x07\xff\xff\x80\x07\xff'\ -b'\xff\x80\x07\xff\xff\x80\x07\xff\xff\x80\x00\x00\x00\x00\x1e\x00'\ -b'\x00\x7f\xc0\x00\x03\xff\xf8\x00\x0f\xff\xfc\x00\x0f\xff\xff\x00'\ -b'\x0f\xe0\x3f\x00\x0e\x00\x0f\x80\x08\x00\x07\x80\x00\x00\x07\xc0'\ -b'\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0'\ -b'\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00'\ -b'\x00\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00\x00\x00\xf8\x00'\ -b'\x00\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00\x00\x0f\x80\x00'\ -b'\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00\x00\x00\xf8\x00\x00'\ -b'\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00\x00\x0f\xff\xff\xc0'\ -b'\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x00\x00\x00\x00'\ -b'\x1e\x00\x00\xff\xe0\x00\x07\xff\xf8\x00\x07\xff\xfe\x00\x07\xff'\ -b'\xff\x00\x07\x00\x3f\x80\x00\x00\x0f\x80\x00\x00\x07\xc0\x00\x00'\ -b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\ -b'\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x3f\x00\x00\x3f'\ -b'\xfe\x00\x00\x3f\xf8\x00\x00\x3f\xfc\x00\x00\x3f\xff\x00\x00\x00'\ -b'\x3f\x80\x00\x00\x0f\xc0\x00\x00\x03\xc0\x00\x00\x03\xe0\x00\x00'\ -b'\x01\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00'\ -b'\x01\xe0\x00\x00\x03\xe0\x00\x00\x07\xc0\x08\x00\x0f\xc0\x0f\x00'\ -b'\x3f\x80\x0f\xff\xff\x00\x0f\xff\xfe\x00\x07\xff\xf8\x00\x00\x7f'\ -b'\xc0\x00\x1e\x00\x00\x00\x00\x00\x00\x00\xfc\x00\x00\x01\xfc\x00'\ -b'\x00\x01\xfc\x00\x00\x03\xfc\x00\x00\x07\xbc\x00\x00\x07\x3c\x00'\ -b'\x00\x0f\x3c\x00\x00\x1e\x3c\x00\x00\x1e\x3c\x00\x00\x3c\x3c\x00'\ -b'\x00\x78\x3c\x00\x00\x78\x3c\x00\x00\xf0\x3c\x00\x01\xe0\x3c\x00'\ -b'\x01\xe0\x3c\x00\x03\xc0\x3c\x00\x07\x80\x3c\x00\x07\x80\x3c\x00'\ -b'\x0f\x00\x3c\x00\x1f\x00\x3c\x00\x1e\x00\x3c\x00\x3c\x00\x3c\x00'\ -b'\x3f\xff\xff\xe0\x3f\xff\xff\xe0\x3f\xff\xff\xe0\x3f\xff\xff\xe0'\ -b'\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\ -b'\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\ -b'\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x07\xff\xfe\x00\x07\xff'\ -b'\xfe\x00\x07\xff\xfe\x00\x07\xff\xfe\x00\x07\x80\x00\x00\x07\x80'\ -b'\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80'\ -b'\x00\x00\x07\x80\x00\x00\x07\xbf\x80\x00\x07\xff\xf0\x00\x07\xff'\ -b'\xfc\x00\x07\xff\xfe\x00\x07\x80\xff\x00\x04\x00\x1f\x00\x00\x00'\ -b'\x0f\x80\x00\x00\x07\x80\x00\x00\x07\xc0\x00\x00\x03\xc0\x00\x00'\ -b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\ -b'\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x08\x00'\ -b'\x1f\x00\x0f\x00\x7f\x00\x0f\xff\xfe\x00\x0f\xff\xfc\x00\x0f\xff'\ -b'\xf0\x00\x01\xff\x80\x00\x1e\x00\x00\x03\xfe\x00\x00\x1f\xff\x80'\ -b'\x00\x7f\xff\x80\x00\xff\xff\x80\x01\xfc\x01\x80\x03\xf0\x00\x00'\ -b'\x03\xe0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00\x0f\x00\x00\x00'\ -b'\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x0f\xe0\x00\x1e\x3f\xfc\x00'\ -b'\x1e\x7f\xfe\x00\x1e\xff\xff\x00\x1f\xf8\x3f\x80\x1f\xe0\x0f\x80'\ -b'\x1f\xc0\x07\xc0\x1f\x80\x03\xc0\x1f\x80\x03\xe0\x1f\x00\x01\xe0'\ -b'\x1f\x00\x01\xe0\x1f\x00\x01\xe0\x0f\x00\x01\xe0\x0f\x00\x01\xe0'\ -b'\x0f\x00\x01\xe0\x0f\x80\x03\xe0\x07\x80\x03\xc0\x07\xc0\x07\xc0'\ -b'\x03\xe0\x0f\x80\x03\xf8\x3f\x80\x01\xff\xff\x00\x00\xff\xfe\x00'\ -b'\x00\x7f\xfc\x00\x00\x0f\xe0\x00\x1e\x00\x00\x00\x00\x00\x0f\xff'\ -b'\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\x80\x00\x00'\ -b'\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00\x1f\x00\x00\x00'\ -b'\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\x3c\x00\x00\x00'\ -b'\x3c\x00\x00\x00\x78\x00\x00\x00\x78\x00\x00\x00\xf8\x00\x00\x00'\ -b'\xf0\x00\x00\x00\xf0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00\x03'\ -b'\xe0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x07'\ -b'\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x1e'\ -b'\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\x3c\x00\x00\x00\x3c'\ -b'\x00\x00\x00\x78\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x1f\xe0\x00'\ -b'\x00\xff\xfc\x00\x01\xff\xfe\x00\x03\xff\xff\x00\x07\xf0\x3f\x80'\ -b'\x07\xc0\x0f\x80\x0f\x80\x07\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0'\ -b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x07\x80\x07\x80'\ -b'\x07\xc0\x0f\x80\x03\xf0\x3f\x00\x01\xff\xfe\x00\x00\x7f\xf8\x00'\ -b'\x00\xff\xfc\x00\x03\xff\xff\x00\x07\xe0\x1f\x80\x0f\x80\x07\xc0'\ -b'\x0f\x00\x03\xc0\x1f\x00\x03\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\ -b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1f\x00\x03\xe0'\ -b'\x0f\x00\x03\xc0\x0f\x80\x07\xc0\x0f\xe0\x1f\x80\x07\xff\xff\x80'\ -b'\x03\xff\xff\x00\x00\xff\xfc\x00\x00\x1f\xe0\x00\x1e\x00\x00\x1f'\ -b'\xc0\x00\x00\xff\xf0\x00\x01\xff\xfc\x00\x03\xff\xfe\x00\x07\xf0'\ -b'\x7f\x00\x0f\xc0\x1f\x00\x0f\x80\x0f\x80\x0f\x00\x07\x80\x1f\x00'\ -b'\x07\xc0\x1e\x00\x03\xc0\x1e\x00\x03\xc0\x1e\x00\x03\xc0\x1e\x00'\ -b'\x03\xe0\x1e\x00\x03\xe0\x1e\x00\x03\xe0\x1f\x00\x07\xe0\x0f\x00'\ -b'\x07\xe0\x0f\x80\x0f\xe0\x0f\xc0\x1f\xe0\x07\xf0\x7f\xe0\x03\xff'\ -b'\xfd\xe0\x01\xff\xf9\xe0\x00\xff\xf1\xe0\x00\x1f\xc3\xc0\x00\x00'\ -b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00'\ -b'\x0f\x80\x00\x00\x1f\x00\x00\x00\x3f\x00\x06\x00\xfe\x00\x07\xff'\ -b'\xfc\x00\x07\xff\xf8\x00\x07\xff\xe0\x00\x01\xff\x00\x00\x10\x00'\ +b'\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x00\x00\x27\x00\x00\x00\x00\x00'\ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ -b'\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0'\ -b'\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00'\ +b'\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00'\ +b'\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c'\ +b'\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00'\ +b'\x00\x00\x00\x3c\x00\x00\x07\xff\xff\xff\xe0\x07\xff\xff\xff\xe0'\ +b'\x07\xff\xff\xff\xe0\x07\xff\xff\xff\xe0\x00\x00\x3c\x00\x00\x00'\ +b'\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00'\ +b'\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c'\ +b'\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00'\ +b'\x00\x00\x00\x3c\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00'\ +b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfc'\ +b'\x00\x3f\xfc\x00\x3f\xfc\x00\x3f\xfc\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00'\ +b'\x00\x0f\xc0\x00\x00\x7f\xf8\x00\x00\xff\xfc\x00\x01\xff\xfe\x00'\ +b'\x03\xf0\x3f\x00\x03\xe0\x1f\x00\x07\xc0\x0f\x80\x07\x80\x07\x80'\ +b'\x0f\x80\x07\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x1f\x00\x03\xc0'\ +b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\ +b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\ +b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\ +b'\x1f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x80\x07\xc0'\ +b'\x07\x80\x07\x80\x07\xc0\x0f\x80\x03\xe0\x1f\x00\x03\xf0\x3f\x00'\ +b'\x01\xff\xfe\x00\x00\xff\xfc\x00\x00\x7f\xf8\x00\x00\x1f\xc0\x00'\ +b'\x1e\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x01\xff\x80\x00\x07\xff'\ +b'\x80\x00\x07\xff\x80\x00\x07\xe7\x80\x00\x06\x07\x80\x00\x00\x07'\ +b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ +b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ +b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ +b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ +b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07'\ +b'\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x07\xff'\ +b'\xff\x80\x07\xff\xff\x80\x07\xff\xff\x80\x07\xff\xff\x80\x00\x00'\ +b'\x00\x00\x1e\x00\x00\x7f\xc0\x00\x03\xff\xf8\x00\x0f\xff\xfe\x00'\ +b'\x0f\xff\xff\x00\x0f\xe0\x3f\x00\x0e\x00\x0f\x80\x08\x00\x07\x80'\ +b'\x00\x00\x07\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0'\ +b'\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80'\ +b'\x00\x00\x0f\x00\x00\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00'\ +b'\x00\x00\xf8\x00\x00\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00'\ +b'\x00\x0f\x80\x00\x00\x1f\x00\x00\x00\x3e\x00\x00\x00\x7c\x00\x00'\ +b'\x00\xf8\x00\x00\x01\xf0\x00\x00\x03\xe0\x00\x00\x07\xc0\x00\x00'\ +b'\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0'\ +b'\x00\x00\x00\x00\x1e\x00\x00\xff\xe0\x00\x07\xff\xf8\x00\x07\xff'\ +b'\xfe\x00\x07\xff\xff\x00\x07\x00\x3f\x80\x00\x00\x0f\x80\x00\x00'\ +b'\x07\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\ +b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00'\ +b'\x3f\x00\x00\x3f\xfe\x00\x00\x3f\xf8\x00\x00\x3f\xfc\x00\x00\x3f'\ +b'\xff\x00\x00\x00\x3f\x80\x00\x00\x0f\xc0\x00\x00\x03\xc0\x00\x00'\ +b'\x03\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00\x01\xe0\x00\x00'\ +b'\x01\xe0\x00\x00\x01\xe0\x00\x00\x03\xe0\x00\x00\x07\xc0\x08\x00'\ +b'\x0f\xc0\x0f\x00\x3f\x80\x0f\xff\xff\x00\x0f\xff\xfe\x00\x07\xff'\ +b'\xf8\x00\x00\x7f\xc0\x00\x1e\x00\x00\x00\x00\x00\x00\x00\xfc\x00'\ +b'\x00\x01\xfc\x00\x00\x01\xfc\x00\x00\x03\xfc\x00\x00\x07\xbc\x00'\ +b'\x00\x07\x3c\x00\x00\x0f\x3c\x00\x00\x1e\x3c\x00\x00\x1e\x3c\x00'\ +b'\x00\x3c\x3c\x00\x00\x78\x3c\x00\x00\x78\x3c\x00\x00\xf0\x3c\x00'\ +b'\x01\xe0\x3c\x00\x01\xe0\x3c\x00\x03\xc0\x3c\x00\x07\x80\x3c\x00'\ +b'\x07\x80\x3c\x00\x0f\x00\x3c\x00\x1f\x00\x3c\x00\x1e\x00\x3c\x00'\ +b'\x3c\x00\x3c\x00\x3f\xff\xff\xe0\x3f\xff\xff\xe0\x3f\xff\xff\xe0'\ +b'\x3f\xff\xff\xe0\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\ +b'\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00\x00\x00\x3c\x00'\ +b'\x00\x00\x3c\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x07\xff'\ +b'\xfe\x00\x07\xff\xfe\x00\x07\xff\xfe\x00\x07\xff\xfe\x00\x07\x80'\ +b'\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\x80'\ +b'\x00\x00\x07\x80\x00\x00\x07\x80\x00\x00\x07\xbf\x80\x00\x07\xff'\ +b'\xf0\x00\x07\xff\xfc\x00\x07\xff\xfe\x00\x07\x80\xff\x00\x04\x00'\ +b'\x1f\x00\x00\x00\x0f\x80\x00\x00\x07\x80\x00\x00\x07\xc0\x00\x00'\ +b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00'\ +b'\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00'\ +b'\x0f\x80\x08\x00\x1f\x00\x0f\x00\x7f\x00\x0f\xff\xfe\x00\x0f\xff'\ +b'\xfc\x00\x0f\xff\xf0\x00\x01\xff\x80\x00\x1e\x00\x00\x03\xfe\x00'\ +b'\x00\x1f\xff\x80\x00\x7f\xff\x80\x00\xff\xff\x80\x01\xfc\x01\x80'\ +b'\x03\xf0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x00'\ +b'\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x1f\x0f\xe0\x00'\ +b'\x1e\x3f\xfc\x00\x1e\x7f\xfe\x00\x1e\xff\xff\x00\x1f\xf8\x3f\x80'\ +b'\x1f\xe0\x0f\xc0\x1f\xc0\x07\xc0\x1f\x80\x03\xc0\x1f\x80\x03\xe0'\ +b'\x1f\x00\x01\xe0\x1f\x00\x01\xe0\x1f\x00\x01\xe0\x0f\x00\x01\xe0'\ +b'\x0f\x00\x01\xe0\x0f\x00\x01\xe0\x0f\x80\x03\xe0\x07\x80\x03\xc0'\ +b'\x07\xc0\x07\xc0\x03\xe0\x0f\x80\x03\xf8\x3f\x80\x01\xff\xff\x00'\ +b'\x00\xff\xfe\x00\x00\x7f\xfc\x00\x00\x0f\xe0\x00\x1e\x00\x00\x00'\ +b'\x00\x00\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff\xff\xc0\x0f\xff'\ +b'\xff\x80\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00'\ +b'\x1f\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00'\ +b'\x3c\x00\x00\x00\x3c\x00\x00\x00\x78\x00\x00\x00\x78\x00\x00\x00'\ +b'\xf8\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x01\xe0\x00\x00\x01'\ +b'\xe0\x00\x00\x03\xe0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07'\ +b'\x80\x00\x00\x07\x80\x00\x00\x0f\x80\x00\x00\x0f\x00\x00\x00\x0f'\ +b'\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\x3c'\ +b'\x00\x00\x00\x3c\x00\x00\x00\x78\x00\x00\x00\x00\x00\x00\x1e\x00'\ +b'\x00\x1f\xe0\x00\x00\xff\xfc\x00\x01\xff\xfe\x00\x03\xff\xff\x00'\ +b'\x07\xf0\x3f\x80\x07\xc0\x0f\x80\x0f\x80\x07\xc0\x0f\x00\x03\xc0'\ +b'\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0\x0f\x00\x03\xc0'\ +b'\x07\x80\x07\x80\x07\xc0\x0f\x80\x03\xf0\x3f\x00\x01\xff\xfe\x00'\ +b'\x00\x7f\xf8\x00\x00\xff\xfc\x00\x03\xff\xff\x00\x07\xe0\x1f\x80'\ +b'\x0f\x80\x07\xc0\x0f\x00\x03\xc0\x1f\x00\x03\xe0\x1e\x00\x01\xe0'\ +b'\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0\x1e\x00\x01\xe0'\ +b'\x1f\x00\x03\xe0\x0f\x00\x03\xc0\x0f\x80\x07\xc0\x07\xe0\x1f\x80'\ +b'\x07\xff\xff\x80\x03\xff\xff\x00\x00\xff\xfc\x00\x00\x1f\xe0\x00'\ +b'\x1e\x00\x00\x1f\xc0\x00\x00\xff\xf8\x00\x01\xff\xfc\x00\x03\xff'\ +b'\xfe\x00\x07\xf0\x7f\x00\x0f\xc0\x1f\x00\x0f\x80\x0f\x80\x0f\x00'\ +b'\x07\x80\x1f\x00\x07\xc0\x1e\x00\x03\xc0\x1e\x00\x03\xc0\x1e\x00'\ +b'\x03\xc0\x1e\x00\x03\xe0\x1e\x00\x03\xe0\x1e\x00\x03\xe0\x1f\x00'\ +b'\x07\xe0\x0f\x00\x07\xe0\x0f\x80\x0f\xe0\x0f\xc0\x1f\xe0\x07\xf0'\ +b'\x7f\xe0\x03\xff\xfd\xe0\x01\xff\xf9\xe0\x00\xff\xf1\xe0\x00\x1f'\ +b'\xc3\xc0\x00\x00\x03\xc0\x00\x00\x03\xc0\x00\x00\x07\xc0\x00\x00'\ +b'\x07\x80\x00\x00\x0f\x80\x00\x00\x1f\x00\x00\x00\x3f\x00\x06\x00'\ +b'\xfe\x00\x07\xff\xfc\x00\x07\xff\xf8\x00\x07\xff\xe0\x00\x01\xff'\ +b'\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0\x03\xe0\x03\xe0'\ -b'\x03\xe0\x03\xe0\x03\xe0\x00\x00' +b'\x03\xe0\x03\xe0\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe0'\ +b'\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x00\x00' _index =\ -b'\x00\x00\x4a\x00\xdc\x00\x6e\x01\x00\x02\x92\x02\x24\x03\xb6\x03'\ -b'\x48\x04\xda\x04\x6c\x05\xfe\x05\x48\x06' +b'\x00\x00\x4a\x00\x00\x00\x00\x01\x00\x00\x00\x00\x6e\x01\x00\x02'\ +b'\x92\x02\x24\x03\xb6\x03\x48\x04\xda\x04\x6c\x05\xfe\x05\x90\x06'\ +b'\x22\x07\x6c\x07' _mvfont = memoryview(_font) _mvi = memoryview(_index) @@ -140,7 +159,7 @@ ifb = lambda l : l[0] | (l[1] << 8) def get_ch(ch): oc = ord(ch) - ioff = 2 * (oc - 48 + 1) if oc >= 48 and oc <= 58 else 0 + ioff = 2 * (oc - 43 + 1) if oc >= 43 and oc <= 58 else 0 doff = ifb(_mvi[ioff : ]) width = ifb(_mvfont[doff : ]) diff --git a/wasp/widgets.py b/wasp/widgets.py index 01d20a8..4e63d95 100644 --- a/wasp/widgets.py +++ b/wasp/widgets.py @@ -222,11 +222,14 @@ class Button(): def draw(self): """Draw the button.""" - draw = wasp.watch.drawable - im = self._im - bg = draw.darken(wasp.system.theme('ui')) + bg = wasp.watch.drawable.darken(wasp.system.theme('ui')) frame = wasp.system.theme('mid') txt = wasp.system.theme('bright') + self.update(bg, frame, txt) + + def update(self, bg, frame, txt): + draw = wasp.watch.drawable + im = self._im draw.fill(bg, im[0], im[1], im[2], im[3]) draw.set_color(txt, bg) @@ -255,6 +258,31 @@ class Button(): return False +class ToggleButton(Button): + """A button with a text label that can be toggled on and off.""" + def __init__(self, x, y, w, h, label): + super().__init__(x, y, w, h, label) + self.state = False + + def draw(self): + """Draw the button.""" + draw = wasp.watch.drawable + + if self.state: + bg = draw.darken(wasp.system.theme('ui')) + else: + bg = draw.darken(wasp.system.theme('mid')) + frame = wasp.system.theme('mid') + txt = wasp.system.theme('bright') + + self.update(bg, frame, txt) + + def touch(self, event): + """Handle touch events.""" + if super().touch(event): + self.state = not self.state + self.draw() + class Checkbox(): """A simple (labelled) checkbox.""" def __init__(self, x, y, label=None): @@ -294,9 +322,10 @@ class Checkbox(): def touch(self, event): """Handle touch events.""" + x = event[1] y = event[2] im = self._im - if y >= im[1] and y < im[1]+40: + if (self.label or im[0] <= x < im[0]+40) and im[1] <= y < im[1]+40: self.state = not self.state self.update() return True