diff --git a/footer.py b/footer.py index 3d58a74..2e4da48 100644 --- a/footer.py +++ b/footer.py @@ -14,13 +14,8 @@ class FooterView(object): self._mode = None self._dt = None - self._callbacks = set() - self._window_size = MIN_WINDOW_SIZE - def add_callback(self, callback): - self._callbacks.add(callback) - def draw(self): # TODO: figure out window width etc. if self._pad is None: @@ -56,21 +51,13 @@ class FooterView(object): self._pad.refresh(0, 0, maxy-2, 0, maxy, min(maxx-1, 100)) - async def on_mode_change(self, newmode, seek=None): - if seek is not None: - assert newmode is None - if self._mode is None: - return - idx = MODES.index(self._mode) - idx = (idx + seek) % len(MODES) - newmode = MODES[idx] + async def on_mode_change(self, newmode): + if self._mode == newmode: + return self._mode = newmode self.draw() - for callback in self._callbacks: - await callback(newmode) - async def on_tick(self, dt): self._dt = dt self.draw() diff --git a/main.py b/main.py index d4c2bc9..6d549de 100644 --- a/main.py +++ b/main.py @@ -9,39 +9,27 @@ import datetime import rpc import interface +import modes import header import footer import monitor import peers import block -from macros import MODES, DEFAULT_MODE +from macros import DEFAULT_MODE -async def handle_hotkeys(window, callback, resize_callback): - - async def handle_key(key): +async def keypress_loop(window, callback, resize_callback): + async def handle_keypress(key): if key == "KEY_RESIZE": y, x = window.getmaxyx() await resize_callback(y, x) return - if key == "KEY_LEFT": - await callback(None, seek=-1) - return - - if key == "KEY_RIGHT": - await callback(None, seek=1) - return - - if len(key) > 1: - return - - lower = key.lower() - - for mode in MODES: - if mode[0] == lower: - await callback(mode) + key = await callback(key) + if key is not None: + # hand off key to somewhere else. + raise Exception first = True while True: @@ -52,13 +40,13 @@ async def handle_hotkeys(window, callback, resize_callback): except Exception: # This is bonkers and I don't understand it. if first: - await callback(DEFAULT_MODE) + await callback(DEFAULT_MODE[0]) # hackery! first = False await asyncio.sleep(0.05) continue - await handle_key(key) + await handle_keypress(key) async def poll_client(client, method, callback, sleeptime, params=None): @@ -116,15 +104,17 @@ def create_tasks(client, window): headerview = header.HeaderView() footerview = footer.FooterView() + modehandler = modes.ModeHandler(footerview.on_mode_change) + monitorview = monitor.MonitorView(client) peerview = peers.PeersView() blockstore = block.BlockStore(client) blockview = block.BlockView(blockstore) - footerview.add_callback(monitorview.on_mode_change) - footerview.add_callback(peerview.on_mode_change) - footerview.add_callback(blockview.on_mode_change) + modehandler.add_callback("monitor", monitorview.on_mode_change) + modehandler.add_callback("peers", peerview.on_mode_change) + modehandler.add_callback("block", blockview.on_mode_change) async def on_bestblockhash(key, obj): await monitorview.on_bestblockhash(key, obj) @@ -176,7 +166,7 @@ def create_tasks(client, window): poll_client(client, "uptime", monitorview.on_uptime, 5.0, params=[10]), tick(on_tick, 1.0), - handle_hotkeys(window, footerview.on_mode_change, on_window_resize) + keypress_loop(window, modehandler.handle_keypress, on_window_resize) ] if not check_disablewallet(client): diff --git a/modes.py b/modes.py new file mode 100644 index 0000000..51fcbd1 --- /dev/null +++ b/modes.py @@ -0,0 +1,90 @@ +# Copyright (c) 2014-2017 esotericnonsense (Daniel Edgecumbe) +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/licenses/mit-license.php + +from macros import MODES + + +class ModeHandler(object): + def __init__(self, base_callback): + self._mode = None + + self._callbacks = {} # mode -> callback, one per mode. + self._base_callback = base_callback + + self._keypress_handlers = {} # mode -> keypress handler. + + def add_callback(self, key, callback): + self._callbacks[key] = callback + + def add_keypress_handler(self, key, handler): + self._keypress_handlers[key] = handler + + async def _call_callbacks(self, oldmode, newmode): + # Tell the old mode that it's no longer active + try: + cb1 = self._callbacks[oldmode] + except KeyError: + cb1 = None + + if cb1 is not None: + await cb1(newmode) + + # Tell the new mode that it's now active + try: + cb2 = self._callbacks[newmode] + except KeyError: + cb2 = None + + if cb2 is not None: + await cb2(newmode) + + # Base callback (generally FooterView) + await self._base_callback(newmode) + + async def set_mode(self, newmode): + if self._mode == newmode: + return + + await self._call_callbacks(self._mode, newmode) + self._mode = newmode + + async def _seek_mode(self, seek): + if self._mode is None: + # Can't seek if no mode + return + + idx = MODES.index(self._mode) + idx = (idx + seek) % len(MODES) + newmode = MODES[idx] + + await self.set_mode(newmode) + + async def handle_keypress(self, key): + # See if it's related to switching modes. + if key == "KEY_LEFT": + await self._seek_mode(-1) + return None + + if key == "KEY_RIGHT": + await self._seek_mode(1) + return None + + if len(key) == 1: + for mode in MODES: + if mode[0] == key.lower(): + await self.set_mode(mode) + return None + + # See if the current mode can handle it. + if self._mode is None: + return key + + try: + handler = self._keypress_handlers[self._mode] + except KeyError: + return key + + key = await handler(key) + + return key # Either none by this point, or still there.