self.curses_shutdown()
class Menu:
+ status_extra_text = None
+
def __init__(self, cc):
self.cc = cc
+ self.items = []
+ self.normalised = False
+
+ def normalise(self):
+ if self.normalised:
+ return
+
+ maxw = 0
+ for _ in range(2):
+ for item in self.items:
+ if isinstance(item, text.MenuKeypressLine):
+ maxw = item.expand_key_width(maxw)
+
+ self.normalised = True
def render(self):
+ self.normalise()
y = 0
header = text.FileHeader(self.title)
self.cc.print_at(y, 0, line)
y += 1
- sl = text.FileStatusLine()
+ # FIXME: handle menus too large for the screen, so that you
+ # have to add > and < keypresses to scroll them
+ y += 1
+ for item in self.items:
+ for line in item.render(self.cc.scr_w):
+ self.cc.print_at(y, 0, line)
+ y += 1
+
+ sl = text.FileStatusLine(self.status_extra_text)
self.add_keys(sl)
sl_rendered = util.exactly_one(sl.render(self.cc.scr_w))
self.cc.print_at(self.cc.scr_h - 1, 0, sl_rendered)
return 'quit'
class MainMenu(Menu):
+ status_extra_text = text.ColouredString("Select an option")
+
def __init__(self, cc):
super().__init__(cc)
self.title = text.ColouredString(
"Mastodonochrome Main Menu", 'H')
+ self.items.append(text.MenuKeypressLine(
+ 'H', text.ColouredString("Home timeline",
+ "K ")))
+ self.items.append(text.BlankLine())
+ self.items.append(text.MenuKeypressLine(
+ 'ESC', text.ColouredString("Utilities and Exit")))
def add_keys(self, sl):
# intentionally don't call the base class, because [Q] doesn't
# do anything on this menu
- sl.keys.append(('ESC', 'Utilities'))
+ pass
def handle_key(self, ch):
if ch in {ord('h'), ord('H')}:
self.title = text.ColouredString(
"Utilities [ESC]",
"HHHHHHHHHHHKKKH")
+ self.items.append(text.MenuKeypressLine(
+ 'L', text.ColouredString("Logs menu",
+ "K ")))
+ self.items.append(text.BlankLine())
+ self.items.append(text.MenuKeypressLine(
+ 'X', text.ColouredString("EXit Mastodonochrome",
+ " K ")))
def handle_key(self, ch):
if ch in {ord('r'), ord('R')}:
self.title = text.ColouredString(
"Client Logs [ESC][L]",
"HHHHHHHHHHHHHKKKHHKH")
+ self.items.append(text.MenuKeypressLine(
+ 'L', text.ColouredString("Server Logs",
+ " K ")))
def handle_key(self, ch):
if ch in {ord('l'), ord('L')}:
self.title = text.ColouredString(
"Server Logs [ESC][L][L]",
"HHHHHHHHHHHHHKKKHHKHHKH")
+ self.items.append(text.MenuKeypressLine(
+ 'E', text.ColouredString("Ego Log (Boosts, Follows and Faves)",
+ "K ")))
def handle_key(self, ch):
if ch in {ord('e'), ord('E')}:
self.title = text.ColouredString(
"Exit Mastodonochrome [ESC][X]",
"HHHHHHHHHHHHHHHHHHHHHHKKKHHKH")
+ self.items.append(text.MenuKeypressLine(
+ 'X', text.ColouredString("Confirm eXit",
+ " K ")))
def handle_key(self, ch):
if ch in {ord('x'), ord('X')}:
yield ColouredString("")
class FileStatusLine:
- def __init__(self):
+ def __init__(self, text=None):
self.keys = []
self.proportion = None
+ self.text = text
def render(self, width):
message = ColouredString('')
sep = ColouredString('')
sep2 = ColouredString(' ')
+ if self.text is not None:
+ message += sep + self.text
+ sep = sep2
for key, action in self.keys:
message += (
sep + ColouredString('[') + ColouredString(key, 'k') +
yield (ColouredString(" " * lspace) + message)
+class MenuKeypressLine:
+ def __init__(self, key, description):
+ self.key = ColouredString(key)
+ self.description = ColouredString(description)
+ self.max_key_width = self.key.width
+
+ def expand_key_width(self, new_max):
+ self.max_key_width = max(self.max_key_width, new_max)
+ return self.max_key_width
+
+ def render(self, width):
+ equalpos = (width - 1) // 2 - 1
+ lspace = equalpos - self.max_key_width - 3
+ kspace = self.max_key_width - self.key.width
+ klspace = kspace // 2
+ krspace = kspace - klspace
+ yield (ColouredString(" " * lspace) +
+ ColouredString(" " * klspace) +
+ ColouredString("[") +
+ ColouredString(self.key, 'k') +
+ ColouredString("]") +
+ ColouredString(" " * krspace) +
+ ColouredString(" = ") +
+ self.description)
+
class Paragraph:
def __init__(self):
self.words = []