[core/themes] Add module-specific themes
Allow module-specific theme information to overload "default" configuration. I.e. it is now possible to have specific prefix or postfix configurations for different modules. The module name is derived for each widget from the module (__module__) from which it was instantiated. see #23
This commit is contained in:
parent
562fd85ca2
commit
2fa8d7b778
6 changed files with 56 additions and 20 deletions
|
@ -13,6 +13,7 @@ class Module(object):
|
||||||
this base class.
|
this base class.
|
||||||
"""
|
"""
|
||||||
def __init__(self, engine, widgets):
|
def __init__(self, engine, widgets):
|
||||||
|
self.name = self.__module__.split(".")[-1]
|
||||||
self._widgets = []
|
self._widgets = []
|
||||||
if widgets:
|
if widgets:
|
||||||
self._widgets = widgets if isinstance(widgets, list) else [widgets]
|
self._widgets = widgets if isinstance(widgets, list) else [widgets]
|
||||||
|
@ -59,10 +60,14 @@ class Engine(object):
|
||||||
"""Start the event loop"""
|
"""Start the event loop"""
|
||||||
self._output.start()
|
self._output.start()
|
||||||
while self.running():
|
while self.running():
|
||||||
|
self._output.begin()
|
||||||
for module in self._modules:
|
for module in self._modules:
|
||||||
module.update(module.widgets())
|
module.update(module.widgets())
|
||||||
self._output.draw(widgets=module.widgets(), engine=self)
|
for widget in module.widgets():
|
||||||
|
widget.set_module(module)
|
||||||
|
self._output.draw(widget=widget, engine=self)
|
||||||
self._output.flush()
|
self._output.flush()
|
||||||
|
self._output.end()
|
||||||
if self.running():
|
if self.running():
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,13 @@ class Widget(object):
|
||||||
"""Represents a single visible block in the status bar"""
|
"""Represents a single visible block in the status bar"""
|
||||||
def __init__(self, full_text):
|
def __init__(self, full_text):
|
||||||
self._full_text = full_text
|
self._full_text = full_text
|
||||||
|
self._module = None
|
||||||
|
|
||||||
|
def set_module(self, module):
|
||||||
|
self._module = module.name
|
||||||
|
|
||||||
|
def module(self):
|
||||||
|
return self._module
|
||||||
|
|
||||||
def full_text(self):
|
def full_text(self):
|
||||||
"""Retrieve the full text to display in the widget"""
|
"""Retrieve the full text to display in the widget"""
|
||||||
|
@ -21,6 +28,7 @@ class I3BarOutput(object):
|
||||||
"""Manage output according to the i3bar protocol"""
|
"""Manage output according to the i3bar protocol"""
|
||||||
def __init__(self, theme):
|
def __init__(self, theme):
|
||||||
self._theme = theme
|
self._theme = theme
|
||||||
|
self._widgets = []
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Print start preamble for i3bar protocol"""
|
"""Print start preamble for i3bar protocol"""
|
||||||
|
@ -30,30 +38,29 @@ class I3BarOutput(object):
|
||||||
"""Finish i3bar protocol"""
|
"""Finish i3bar protocol"""
|
||||||
sys.stdout.write("]\n")
|
sys.stdout.write("]\n")
|
||||||
|
|
||||||
def draw_widget(self, result, widget):
|
def draw(self, widget, engine=None):
|
||||||
"""Draw a single widget"""
|
"""Draw a single widget"""
|
||||||
full_text = widget.full_text()
|
full_text = widget.full_text()
|
||||||
prefix = self._theme.prefix(widget)
|
prefix = self._theme.prefix(widget)
|
||||||
suffix = self._theme.suffix(widget)
|
suffix = self._theme.suffix(widget)
|
||||||
if prefix:
|
if prefix:
|
||||||
full_text = "{}{}".format(prefix, full_text)
|
full_text = u"{}{}".format(prefix, full_text)
|
||||||
if suffix:
|
if suffix:
|
||||||
full_text = "{}{}".format(full_text, suffix)
|
full_text = u"{}{}".format(full_text, suffix)
|
||||||
result.append({
|
self._widgets.append({
|
||||||
u"full_text": "{}".format(full_text)
|
u"full_text": u"{}".format(full_text)
|
||||||
})
|
})
|
||||||
|
|
||||||
def draw(self, widgets, engine=None):
|
def begin(self):
|
||||||
"""Draw a number of widgets"""
|
"""Start one output iteration"""
|
||||||
if not isinstance(widgets, list):
|
self._widgets = []
|
||||||
widgets = [widgets]
|
|
||||||
result = []
|
|
||||||
for widget in widgets:
|
|
||||||
self.draw_widget(result, widget)
|
|
||||||
sys.stdout.write(json.dumps(result))
|
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
"""Flushes output"""
|
"""Flushes output"""
|
||||||
|
sys.stdout.write(json.dumps(self._widgets))
|
||||||
|
|
||||||
|
def end(self):
|
||||||
|
"""Finalizes output"""
|
||||||
sys.stdout.write(",\n")
|
sys.stdout.write(",\n")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,16 @@ class Theme(object):
|
||||||
|
|
||||||
module_theme = self._theme.get(widget.module(), {})
|
module_theme = self._theme.get(widget.module(), {})
|
||||||
|
|
||||||
|
padding = None
|
||||||
|
if name != "padding":
|
||||||
|
padding = self._get(widget, "padding")
|
||||||
|
|
||||||
value = self._defaults.get(name, default)
|
value = self._defaults.get(name, default)
|
||||||
value = module_theme.get(name, value)
|
value = module_theme.get(name, value)
|
||||||
|
|
||||||
|
if value and padding:
|
||||||
|
value = u"{}{}{}".format(padding, value, padding)
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
# algorithm copied from
|
# algorithm copied from
|
||||||
|
|
|
@ -33,25 +33,34 @@ class TestI3BarOutput(unittest.TestCase):
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
@mock.patch("sys.stdout", new_callable=StringIO)
|
||||||
def test_draw_single_widget(self, stdout):
|
def test_draw_single_widget(self, stdout):
|
||||||
self.output.draw(self.someWidget)
|
self.output.draw(self.someWidget)
|
||||||
|
self.output.flush()
|
||||||
result = json.loads(stdout.getvalue())[0]
|
result = json.loads(stdout.getvalue())[0]
|
||||||
self.assertEquals(result["full_text"], self.someWidget.full_text())
|
self.assertEquals(result["full_text"], self.someWidget.full_text())
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
@mock.patch("sys.stdout", new_callable=StringIO)
|
||||||
def test_draw_multiple_widgets(self, stdout):
|
def test_draw_multiple_widgets(self, stdout):
|
||||||
self.output.draw([self.someWidget, self.someWidget])
|
for widget in [self.someWidget, self.someWidget]:
|
||||||
|
self.output.draw(widget)
|
||||||
|
self.output.flush()
|
||||||
result = json.loads(stdout.getvalue())
|
result = json.loads(stdout.getvalue())
|
||||||
for res in result:
|
for res in result:
|
||||||
self.assertEquals(res["full_text"], self.someWidget.full_text())
|
self.assertEquals(res["full_text"], widget.full_text())
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
@mock.patch("sys.stdout", new_callable=StringIO)
|
||||||
def test_flush(self, stdout):
|
def test_begin(self, stdout):
|
||||||
self.output.flush()
|
self.output.begin()
|
||||||
|
self.assertEquals("", stdout.getvalue())
|
||||||
|
|
||||||
|
@mock.patch("sys.stdout", new_callable=StringIO)
|
||||||
|
def test_end(self, stdout):
|
||||||
|
self.output.end()
|
||||||
self.assertEquals(",\n", stdout.getvalue())
|
self.assertEquals(",\n", stdout.getvalue())
|
||||||
|
|
||||||
@mock.patch("sys.stdout", new_callable=StringIO)
|
@mock.patch("sys.stdout", new_callable=StringIO)
|
||||||
def test_prefix(self, stdout):
|
def test_prefix(self, stdout):
|
||||||
self.theme.set_prefix(" - ")
|
self.theme.set_prefix(" - ")
|
||||||
self.output.draw(self.someWidget)
|
self.output.draw(self.someWidget)
|
||||||
|
self.output.flush()
|
||||||
result = json.loads(stdout.getvalue())[0]
|
result = json.loads(stdout.getvalue())[0]
|
||||||
self.assertEquals(result["full_text"], "{}{}".format(
|
self.assertEquals(result["full_text"], "{}{}".format(
|
||||||
self.theme.prefix(self.someWidget), self.someWidget.full_text())
|
self.theme.prefix(self.someWidget), self.someWidget.full_text())
|
||||||
|
@ -61,6 +70,7 @@ class TestI3BarOutput(unittest.TestCase):
|
||||||
def test_suffix(self, stdout):
|
def test_suffix(self, stdout):
|
||||||
self.theme.set_suffix(" - ")
|
self.theme.set_suffix(" - ")
|
||||||
self.output.draw(self.someWidget)
|
self.output.draw(self.someWidget)
|
||||||
|
self.output.flush()
|
||||||
result = json.loads(stdout.getvalue())[0]
|
result = json.loads(stdout.getvalue())[0]
|
||||||
self.assertEquals(result["full_text"], "{}{}".format(
|
self.assertEquals(result["full_text"], "{}{}".format(
|
||||||
self.someWidget.full_text(), self.theme.suffix(self.someWidget))
|
self.someWidget.full_text(), self.theme.suffix(self.someWidget))
|
||||||
|
@ -71,6 +81,7 @@ class TestI3BarOutput(unittest.TestCase):
|
||||||
self.theme.set_suffix(" - ")
|
self.theme.set_suffix(" - ")
|
||||||
self.theme.set_prefix(" * ")
|
self.theme.set_prefix(" * ")
|
||||||
self.output.draw(self.someWidget)
|
self.output.draw(self.someWidget)
|
||||||
|
self.output.flush()
|
||||||
result = json.loads(stdout.getvalue())[0]
|
result = json.loads(stdout.getvalue())[0]
|
||||||
self.assertEquals(result["full_text"], "{}{}{}".format(
|
self.assertEquals(result["full_text"], "{}{}{}".format(
|
||||||
self.theme.prefix(self.someWidget), self.someWidget.full_text(), self.theme.suffix(self.someWidget))
|
self.theme.prefix(self.someWidget), self.someWidget.full_text(), self.theme.suffix(self.someWidget))
|
||||||
|
|
|
@ -13,12 +13,18 @@ class MockOutput(object):
|
||||||
def stop(self):
|
def stop(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def draw(self, widgets, engine):
|
def draw(self, widget, engine):
|
||||||
engine.stop()
|
engine.stop()
|
||||||
|
|
||||||
|
def begin(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def end(self):
|
||||||
|
pass
|
||||||
|
|
||||||
class MockWidget(object):
|
class MockWidget(object):
|
||||||
def __init__(self, text):
|
def __init__(self, text):
|
||||||
self._text = text
|
self._text = text
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"defaults": { "separator": "" },
|
"defaults": { "separator": "", "padding": " " },
|
||||||
"date": { "prefix": "" },
|
"date": { "prefix": "" },
|
||||||
"time": { "prefix": "" },
|
"time": { "prefix": "" },
|
||||||
"memory": { "prefix": "" },
|
"memory": { "prefix": "" },
|
||||||
|
|
Loading…
Reference in a new issue