new: implemented text auto wrapping. (closes #46)

This commit is contained in:
Simone Margaritelli
2019-10-03 11:09:25 +02:00
parent d69e938676
commit 9205ca1e59
3 changed files with 59 additions and 42 deletions

View File

@ -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):

View File

@ -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)

View File

@ -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 != '<hidden>' 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)