From bab78216079bffc3444cf24b96a9a04b301b4d39 Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Sat, 5 Nov 2016 08:59:43 +0100 Subject: [PATCH] [all] Refactor module <-> output communication Modules now return "bumblebee.output.Widget" objects, so that they can actually define a list of items to be drawn in the bar. --- bumblebee/engine.py | 15 +-- bumblebee/modules/time.py | 8 +- bumblebee/output.py | 38 +++++- bumblebee/outputs/i3.py | 70 +++++------ bumblebee/theme.py | 220 ++++++++++++++++++++++------------ bumblebee/themes/default.json | 3 +- 6 files changed, 223 insertions(+), 131 deletions(-) diff --git a/bumblebee/engine.py b/bumblebee/engine.py index 8834877..d8c2e22 100644 --- a/bumblebee/engine.py +++ b/bumblebee/engine.py @@ -43,18 +43,15 @@ class Engine: self.register_event(e) def run(self): - print self._output.start() + self._output.start() while True: - # improve this - self._theme.reset() + self._theme.begin() for m in self._modules: - self._output.add(m, self._theme) - self._theme.next() - print self._output.get() - sys.stdout.flush() - self._output.wait(self._args.interval) + self._output.draw(m.widgets(), self._theme) + self._output.flush() + self._output.wait() - print self._output.stop() + self._output.stop() # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/time.py b/bumblebee/modules/time.py index 9a69d71..60f2272 100644 --- a/bumblebee/modules/time.py +++ b/bumblebee/modules/time.py @@ -31,7 +31,11 @@ class Module(bumblebee.module.Module): param_name = "{}.format".format(module) self._fmt = config.parameter(param_name, default) - def data(self): - return datetime.datetime.now().strftime(self._fmt) + def widgets(self): + return [ + bumblebee.output.Widget( + datetime.datetime.now().strftime(self._fmt) + ) + ] # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/output.py b/bumblebee/output.py index 2e75a99..4d8df8f 100644 --- a/bumblebee/output.py +++ b/bumblebee/output.py @@ -1,11 +1,39 @@ +import inspect import threading def output(args): import bumblebee.outputs.i3 return bumblebee.outputs.i3.Output(args) +class Widget(object): + def __init__(self, text, warning=False, critical=False, state=None): + self._name = inspect.getmodule(inspect.stack()[1][0]).__name__ + self._text = text + self._warning = warning + self._critical = critical + self._state = state + + def state(self): + return self._state + + def warning(self): + return self._warning + + def critical(self): + return self._critical + + def module(self): + return self._name.split(".")[-1] + + def name(self): + return self._name + + def text(self): + return self._text + class Output(object): - def __init__(self, args): + def __init__(self, config): + self._config = config self._callbacks = {} self._wait = threading.Condition() self._wait.acquire() @@ -35,16 +63,16 @@ class Output(object): ), None) return cb - def wait(self, interval): - self._wait.wait(interval) + def wait(self): + self._wait.wait(self._config.parameter("interval", 1)) def start(self): pass - def add(self, obj, theme): + def draw(self, widgets, theme): pass - def get(self): + def flush(self): pass def stop(self): diff --git a/bumblebee/outputs/i3.py b/bumblebee/outputs/i3.py index ef4a0d9..452fd78 100644 --- a/bumblebee/outputs/i3.py +++ b/bumblebee/outputs/i3.py @@ -32,51 +32,47 @@ class Output(bumblebee.output.Output): super(Output, self).__init__(args) self._data = [] - self.add_callback("i3-msg workspace prev_on_output", 4) - self.add_callback("i3-msg workspace next_on_output", 5) +# TODO +# self.add_callback("i3-msg workspace prev_on_output", 4) +# self.add_callback("i3-msg workspace next_on_output", 5) - self._thread = threading.Thread(target=read_input, args=(self,)) - self._thread.start() +# self._thread = threading.Thread(target=read_input, args=(self,)) +# self._thread.start() def start(self): - return json.dumps({ "version": 1, "click_events": True }) + "[" + print json.dumps({ "version": 1, "click_events": True }) + "[" - def add(self, obj, theme): + def draw(self, widgets, theme): + for widget in widgets: + if theme.separator(widget): + self._data.append({ + u"full_text": theme.separator(obj), + "color": theme.separator_color(obj), + "background": theme.separator_background(), + "separator": False, + "separator_block_width": 0, + }) - while True: - d = obj.data() - data = { - u"full_text": "{}{}{}".format(theme.prefix(obj), d, theme.suffix(obj)), - "color": theme.color(obj), - "background": theme.background(obj), - "name": obj.__module__.replace("bumblebee.modules.",""), - "instance": obj.instance() if hasattr(obj, "instance") else None, - } + self._data.append({ + u"full_text": "{}{}{}".format( + theme.prefix(widget), + widget.text(), + theme.suffix(widget) + ), + "color": theme.color(widget), + "background": theme.background(widget), + "name": widget.name(), + "instance": getattr(widget, "instance", None), + "separator": theme.default_separators(widget), + "separator_block_width": theme.separator_block_width(widget), + }) + theme.next_widget() - if theme.urgent(obj) and obj.critical(): - data["urgent"] = True - - if theme.default_separators(obj) == False: - data["separator"] = False - data["separator_block_width"] = 0 - if theme.separator(obj): - self._data.append({ - u"full_text": theme.separator(obj), - "color": theme.background(obj), - "background": theme.previous_background(), - "separator": False, - "separator_block_width": 0, - }) - - self._data.append(data) - if obj.next() == False: - break - theme.next() - - def get(self): + def flush(self): data = json.dumps(self._data) self._data = [] - return data + "," + print(data + ",") + sys.stdout.flush() def stop(self): return "]" diff --git a/bumblebee/theme.py b/bumblebee/theme.py index a0e4697..8c492ed 100644 --- a/bumblebee/theme.py +++ b/bumblebee/theme.py @@ -10,96 +10,162 @@ def themes(): return [ os.path.basename(f).replace(".json", "") for f in glob.iglob("{}/*.json".format(d)) ] class Theme: - _cycle_index = 0 - _cycle = None + # TODO: cycle handling def __init__(self, config): - self._data = None - path = os.path.dirname(os.path.realpath(__file__)) with open("{}/{}.json".format(getpath(), config.theme())) as f: self._data = json.load(f) self._defaults = self._data.get("defaults", {}) - self._cycle = self._defaults.get("cycle", []) - self._modules = {} + self._cycle = {} - self.reset() + def begin(self): + pass - def _gettheme(self, obj, key): - module = obj.__module__.split(".")[-1] + def next_widget(self): + pass + + def prefix(self, widget): + pass + + def suffix(self, widget): + pass + + def color(self, widget): + result = self._get(widget, "fg") + if widget.warning(): + result = self._get(widget, "fg-warning") + if widget.critical(): + result = self._get(widget, "fg-critical") + return result + + def background(self, widget): + pass + + def separator(self, widget): + pass + + def separator_color(self, widget): + pass + + def separator_background(self, widget): + pass + + def default_separators(self, widget): + pass + + def separator_block_width(self, widget): + pass + + def _get(self, widget, name): + module = widget.module() + state = widget.state() module_theme = self._data.get(module, {}) + state_theme = module_theme.get("states", {}).get(state, {}) - value = getattr(obj, key)() if hasattr(obj, key) else None - value = self._defaults.get(key, value) - if len(self._cycle) > 0: - value = self._defaults["cycle"][self._cycle_index].get(key, value) - value = module_theme.get(key, value) - - if hasattr(obj, "state"): - state = getattr(obj, "state")() - state_theme = module_theme.get("states", {}).get(state, {}) - - value = state_theme.get(key, value) + value = None + value = self._defaults.get(name, value) + value = self._cycle.get(name, value) + value = module_theme.get(name, value) + value = state_theme.get(name, value) if type(value) is list: - # cycle through the values - if not obj in self._modules: - self._modules[obj] = { "idx": 0 } - else: - self._modules[obj]["idx"] += 1 - if self._modules[obj]["idx"] >= len(value): - self._modules[obj]["idx"] = 0 - value = value[self._modules[obj]["idx"]] + # if the value is a list, cycle through it + # TODO + pass return value - def reset(self): - self._cycle_index = 0 - self._previous_background = None - self._background = None - def urgent(self, obj): - self._gettheme(obj, "urgent") - - def next(self): - self._cycle_index += 1 - self._previous_background = self._background - if self._cycle_index >= len(self._cycle): - self._cycle_index = 0 - - def color(self, obj): - fg = None - if obj.warning(): - fg = self._gettheme(obj, "fg-warning") - if obj.critical(): - fg = self._gettheme(obj, "fg-critical") - if fg == None: - fg = self._gettheme(obj, "fg") - return fg - - def background(self, obj): - self._background = None - if obj.warning(): - self._background = self._gettheme(obj, "bg-warning") - if obj.critical(): - self._background = self._gettheme(obj, "bg-critical") - - if self._background == None: - self._background = self._gettheme(obj, "bg") - - return self._background - - def previous_background(self): - return self._previous_background - - def separator(self, obj): - return self._gettheme(obj, "separator") - - def default_separators(self, obj): - return self._gettheme(obj, "default_separators") - - def prefix(self, obj): - return self._gettheme(obj, "prefix") - - def suffix(self, obj): - return self._gettheme(obj, "suffix") +#class Theme: +# _cycle_index = 0 +# _cycle = None +# def __init__(self, config): +# self._data = None +# path = os.path.dirname(os.path.realpath(__file__)) +# with open("{}/{}.json".format(getpath(), config.theme())) as f: +# self._data = json.load(f) +# self._defaults = self._data.get("defaults", {}) +# self._cycle = self._defaults.get("cycle", []) +# self._modules = {} +# +# self.reset() +# +# def _gettheme(self, obj, key): +# module = obj.__module__.split(".")[-1] +# module_theme = self._data.get(module, {}) +# +# value = getattr(obj, key)() if hasattr(obj, key) else None +# value = self._defaults.get(key, value) +# if len(self._cycle) > 0: +# value = self._defaults["cycle"][self._cycle_index].get(key, value) +# value = module_theme.get(key, value) +# +# if hasattr(obj, "state"): +# state = getattr(obj, "state")() +# state_theme = module_theme.get("states", {}).get(state, {}) +# +# value = state_theme.get(key, value) +# +# if type(value) is list: +# # cycle through the values +# if not obj in self._modules: +# self._modules[obj] = { "idx": 0 } +# else: +# self._modules[obj]["idx"] += 1 +# if self._modules[obj]["idx"] >= len(value): +# self._modules[obj]["idx"] = 0 +# value = value[self._modules[obj]["idx"]] +# +# return value +# +# def reset(self): +# self._cycle_index = 0 +# self._previous_background = None +# self._background = None +# +# def urgent(self, obj): +# self._gettheme(obj, "urgent") +# +# def next(self): +# self._cycle_index += 1 +# self._previous_background = self._background +# if self._cycle_index >= len(self._cycle): +# self._cycle_index = 0 +# +# def color(self, obj): +# fg = None +# if obj.warning(): +# fg = self._gettheme(obj, "fg-warning") +# if obj.critical(): +# fg = self._gettheme(obj, "fg-critical") +# if fg == None: +# fg = self._gettheme(obj, "fg") +# return fg +# +# def background(self, obj): +# self._background = None +# if obj.warning(): +# self._background = self._gettheme(obj, "bg-warning") +# if obj.critical(): +# self._background = self._gettheme(obj, "bg-critical") +# +# if self._background == None: +# self._background = self._gettheme(obj, "bg") +# +# return self._background +# +# def previous_background(self): +# return self._previous_background +# +# def separator(self, obj): +# return self._gettheme(obj, "separator") +# +# def default_separators(self, obj): +# return self._gettheme(obj, "default_separators") +# +# def prefix(self, obj): +# return self._gettheme(obj, "prefix") +# +# def suffix(self, obj): +# return self._gettheme(obj, "suffix") # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/themes/default.json b/bumblebee/themes/default.json index 2b607da..5520c02 100644 --- a/bumblebee/themes/default.json +++ b/bumblebee/themes/default.json @@ -2,7 +2,8 @@ "defaults": { "prefix": " ", "suffix" : " ", - "urgent": true + "urgent": true, + "fg": "#aabbcc" }, "date": { "prefix": " "