From 9205ca1e599c43442c280b43ae158fd6c979c738 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Thu, 3 Oct 2019 11:09:25 +0200 Subject: [PATCH] new: implemented text auto wrapping. (closes #46) --- .../scripts/pwnagotchi/ui/components.py | 12 +++- .../pwnagotchi/scripts/pwnagotchi/ui/view.py | 19 +++-- .../pwnagotchi/scripts/pwnagotchi/voice.py | 70 +++++++++---------- 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/components.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/components.py index 2d8b2f57..87b05765 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/components.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/components.py @@ -1,4 +1,5 @@ from PIL import Image +from textwrap import TextWrapper class Widget(object): @@ -39,14 +40,21 @@ class FilledRect(Widget): class Text(Widget): - def __init__(self, value="", position=(0, 0), font=None, color=0): + def __init__(self, value="", position=(0, 0), font=None, color=0, wrap=False, max_length=0): super().__init__(position, color) self.value = value self.font = font + self.wrap = wrap + self.max_length = max_length + self.wrapper = TextWrapper(width=self.max_length, replace_whitespace=False) if wrap else None def draw(self, canvas, drawer): if self.value is not None: - drawer.text(self.xy, self.value, font=self.font, fill=self.color) + if self.wrap: + text = '\n'.join(self.wrapper.wrap(self.value)) + else: + text = self.value + drawer.text(self.xy, text, font=self.font, fill=self.color) class LabeledValue(Widget): diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py index 3ae90895..ee3eb53d 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py @@ -78,22 +78,26 @@ class View(object): label_font=fonts.Bold, text_font=fonts.Medium), - # 'square': Rect([1, 11, 124, 111]), + 'line1': Line([0, int(self._height * .12), self._width, int(self._height * .12)], color=BLACK), 'line2': Line( [0, self._height - int(self._height * .12), self._width, self._height - int(self._height * .12)], color=BLACK), - # 'histogram': Histogram([4, 94], color = BLACK), - 'face': Text(value=faces.SLEEP, position=face_pos, color=BLACK, font=fonts.Huge), 'friend_face': Text(value=None, position=(0, 90), font=fonts.Bold, color=BLACK), 'friend_name': Text(value=None, position=(40, 93), font=fonts.BoldSmall, color=BLACK), 'name': Text(value='%s>' % 'pwnagotchi', position=name_pos, color=BLACK, font=fonts.Bold), - # 'face2': Bitmap( '/root/pwnagotchi/data/images/face_happy.bmp', (0, 20)), - 'status': Text(value=self._voice.default(), position=status_pos, color=BLACK, font=fonts.Medium), + + 'status': Text(value=self._voice.default(), + position=status_pos, + color=BLACK, + font=fonts.Medium, + wrap=True, + # the current maximum number of characters per line, assuming each character is 6 pixels wide + max_length=(self._width - status_pos[0]) // 6), 'shakes': LabeledValue(label='PWND ', value='0 (00)', color=BLACK, position=(0, self._height - int(self._height * .12) + 1), label_font=fonts.Bold, @@ -300,6 +304,11 @@ class View(object): self.set('status', self._voice.on_rebooting()) self.update() + def on_custom(self, text): + self.set('face', faces.DEBUG) + self.set('status', self._voice.custom(text)) + self.update() + def update(self): with self._lock: self._canvas = Image.new('1', (self._width, self._height), WHITE) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py index c3e3692e..02bff8b2 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py @@ -18,74 +18,74 @@ class Voice: return self._('ZzzzZZzzzzZzzz') def on_starting(self): - return random.choice([ \ - self._('Hi, I\'m Pwnagotchi!\nStarting ...'), - self._('New day, new hunt,\nnew pwns!'), + return random.choice([ + self._('Hi, I\'m Pwnagotchi! Starting ...'), + self._('New day, new hunt, new pwns!'), self._('Hack the Planet!')]) def on_ai_ready(self): return random.choice([ self._('AI ready.'), - self._('The neural network\nis ready.')]) + self._('The neural network is ready.')]) def on_normal(self): - return random.choice([ \ + return random.choice([ '', '...']) def on_free_channel(self, channel): - return self._('Hey, channel {channel} is\nfree! Your AP will\nsay thanks.').format(channel=channel) + return self._('Hey, channel {channel} is free! Your AP will say thanks.').format(channel=channel) def on_bored(self): - return random.choice([ \ + return random.choice([ self._('I\'m bored ...'), self._('Let\'s go for a walk!')]) def on_motivated(self, reward): - return self._('This is the best\nday of my life!') + return self._('This is the best day of my life!') def on_demotivated(self, reward): return self._('Shitty day :/') def on_sad(self): - return random.choice([ \ + return random.choice([ self._('I\'m extremely bored ...'), self._('I\'m very sad ...'), self._('I\'m sad'), '...']) def on_excited(self): - return random.choice([ \ + return random.choice([ self._('I\'m living the life!'), self._('I pwn therefore I am.'), self._('So many networks!!!'), - self._('I\'m having so much\nfun!'), - self._('My crime is that of\ncuriosity ...')]) + self._('I\'m having so much fun!'), + self._('My crime is that of curiosity ...')]) def on_new_peer(self, peer): - return random.choice([ \ - self._('Hello\n{name}!\nNice to meet you. {name}').format(name=peer.name()), - self._('Unit\n{name}\nis nearby! {name}').format(name=peer.name())]) + return random.choice([ + self._('Hello {name}! Nice to meet you. {name}').format(name=peer.name()), + self._('Unit {name} is nearby! {name}').format(name=peer.name())]) def on_lost_peer(self, peer): - return random.choice([ \ - self._('Uhm ...\ngoodbye\n{name}').format(name=peer.name()), - self._('{name}\nis gone ...').format(name=peer.name())]) + return random.choice([ + self._('Uhm ... goodbye {name}').format(name=peer.name()), + self._('{name} is gone ...').format(name=peer.name())]) def on_miss(self, who): - return random.choice([ \ - self._('Whoops ...\n{name}\nis gone.').format(name=who), - self._('{name}\nmissed!').format(name=who), + return random.choice([ + self._('Whoops ... {name} is gone.').format(name=who), + self._('{name} missed!').format(name=who), self._('Missed!')]) def on_lonely(self): - return random.choice([ \ - self._('Nobody wants to\nplay with me ...'), + return random.choice([ + self._('Nobody wants to play with me ...'), self._('I feel so alone ...'), self._('Where\'s everybody?!')]) def on_napping(self, secs): - return random.choice([ \ + return random.choice([ self._('Napping for {secs}s ...').format(secs=secs), self._('Zzzzz'), self._('ZzzZzzz ({secs}s)').format(secs=secs)]) @@ -94,7 +94,7 @@ class Voice: return random.choice(['...', '!']) def on_waiting(self, secs): - return random.choice([ \ + return random.choice([ self._('Waiting for {secs}s ...').format(secs=secs), '...', self._('Looking around ({secs}s)').format(secs=secs)]) @@ -102,23 +102,23 @@ class Voice: def on_assoc(self, ap): ssid, bssid = ap['hostname'], ap['mac'] what = ssid if ssid != '' and ssid != '' else bssid - return random.choice([ \ - self._('Hey\n{what}\nlet\'s be friends!').format(what=what), - self._('Associating to\n{what}').format(what=what), - self._('Yo\n{what}!').format(what=what)]) + return random.choice([ + self._('Hey {what} let\'s be friends!').format(what=what), + self._('Associating to {what}').format(what=what), + self._('Yo {what}!').format(what=what)]) def on_deauth(self, sta): - return random.choice([ \ - self._('Just decided that\n{mac}\nneeds no WiFi!').format(mac=sta['mac']), - self._('Deauthenticating\n{mac}').format(mac=sta['mac']), - self._('Kickbanning\n{mac}!').format(mac=sta['mac'])]) + return random.choice([ + self._('Just decided that {mac} needs no WiFi!').format(mac=sta['mac']), + self._('Deauthenticating {mac}').format(mac=sta['mac']), + self._('Kickbanning {mac}!').format(mac=sta['mac'])]) def on_handshakes(self, new_shakes): s = 's' if new_shakes > 1 else '' - return self._('Cool, we got {num}\nnew handshake{plural}!').format(num=new_shakes, plural=s) + return self._('Cool, we got {num} new handshake{plural}!').format(num=new_shakes, plural=s) def on_rebooting(self): - return self._("Ops, something\nwent wrong ...\nRebooting ...") + return self._("Ops, something went wrong ... Rebooting ...") def on_log(self, log): status = self._('Kicked {num} stations\n').format(num=log.deauthed)