[themes] Add "cycle" theme capability

It is now possible to add a list of theme configurations in the
"default" section called "cycle". These configuration items will be
cycled through module by module. to create "alternate style" effects.
This is *only* possible in the "default" configuration part, but any
module-specific configurations still take precedence.

Also, removed the capability of per-widget themes. That simply
complicates things and probably doesn't really bring any benefits.
This commit is contained in:
Tobias Witek 2016-10-31 10:45:15 +01:00
parent 656c499c95
commit 2a35905b89
8 changed files with 57 additions and 19 deletions

View file

@ -1,10 +1,7 @@
class Module(object): class Module(object):
def __init__(self, theme, args): def __init__(self, args):
self._theme = theme pass
def theme(self):
return self._theme
def data(self): def data(self):
pass pass

View file

@ -2,8 +2,8 @@ import datetime
import bumblebee.module import bumblebee.module
class Module(bumblebee.module.Module): class Module(bumblebee.module.Module):
def __init__(self, theme, args): def __init__(self, args):
super(Module, self).__init__(theme, args) super(Module, self).__init__(args)
self._battery = "BAT0" if not args else args[0] self._battery = "BAT0" if not args else args[0]
self._capacity = 0 self._capacity = 0
self._status = "Unknown" self._status = "Unknown"

View file

@ -2,8 +2,8 @@ import datetime
import bumblebee.module import bumblebee.module
class Module(bumblebee.module.Module): class Module(bumblebee.module.Module):
def __init__(self, theme, args): def __init__(self, args):
super(Module, self).__init__(theme, args) super(Module, self).__init__(args)
def data(self): def data(self):
return datetime.datetime.now().strftime("%x %X") return datetime.datetime.now().strftime("%x %X")

View file

@ -1,5 +1,11 @@
class Output(object): class Output(object):
def __init__(self, theme):
self._theme = theme
def theme(self):
return self._theme
def start(self): def start(self):
pass pass

View file

@ -4,15 +4,16 @@ import json
import bumblebee.output import bumblebee.output
class i3bar(bumblebee.output.Output): class i3bar(bumblebee.output.Output):
def __init__(self): def __init__(self, theme):
super(i3bar, self).__init__(theme)
self._data = [] self._data = []
self._previous_background = None
def start(self): def start(self):
return json.dumps({ "version": 1 }) + "[" return json.dumps({ "version": 1 }) + "["
def add(self, obj): def add(self, obj):
theme = obj.theme() theme = self.theme()
data = { data = {
u"full_text": "{}{}{}".format(theme.prefix(obj), obj.data(), theme.suffix(obj)), u"full_text": "{}{}{}".format(theme.prefix(obj), obj.data(), theme.suffix(obj)),
@ -26,13 +27,12 @@ class i3bar(bumblebee.output.Output):
self._data.append({ self._data.append({
u"full_text": theme.separator(obj), u"full_text": theme.separator(obj),
"color": theme.background(obj), "color": theme.background(obj),
"background": self._previous_background, "background": theme.previous_background(),
"separator": False, "separator": False,
"separator_block_width": 0, "separator_block_width": 0,
}) })
self._data.append(data) self._data.append(data)
self._previous_background = theme.background(obj)
def get(self): def get(self):
data = json.dumps(self._data) data = json.dumps(self._data)

View file

@ -1,13 +1,20 @@
import os import os
import json import json
class Theme: class Theme:
_cycle_index = 0
_cycle = None
def __init__(self, name="default"): def __init__(self, name="default"):
self._data = None self._data = None
path = os.path.dirname(os.path.realpath(__file__)) path = os.path.dirname(os.path.realpath(__file__))
with open("{}/themes/{}.json".format(path, name)) as f: with open("{}/themes/{}.json".format(path, name)) as f:
self._data = json.load(f) self._data = json.load(f)
self._defaults = self._data.get("defaults", {}) self._defaults = self._data.get("defaults", {})
self._cycle = self._defaults.get("cycle", [])
self.reset()
def _gettheme(self, obj, key): def _gettheme(self, obj, key):
module = obj.__module__.split(".")[-1] module = obj.__module__.split(".")[-1]
@ -17,6 +24,9 @@ class Theme:
value = self._defaults.get(key, value) value = self._defaults.get(key, value)
value = module_theme.get(key, value) value = module_theme.get(key, value)
if len(self._cycle) > 0:
value = self._defaults["cycle"][self._cycle_index].get(key, value)
if hasattr(obj, "state"): if hasattr(obj, "state"):
state = getattr(obj, "state")() state = getattr(obj, "state")()
state_theme = module_theme.get("states", {}).get(state, {}) state_theme = module_theme.get("states", {}).get(state, {})
@ -25,11 +35,26 @@ class Theme:
return value return value
def reset(self):
self._cycle_index = 0
self._previous_background = None
self._background = None
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): def color(self, obj):
return self._gettheme(obj, "fg") return self._gettheme(obj, "fg")
def background(self, obj): def background(self, obj):
return self._gettheme(obj, "bg") self._background = self._gettheme(obj, "bg")
return self._background
def previous_background(self):
return self._previous_background
def separator(self, obj): def separator(self, obj):
return self._gettheme(obj, "separator") return self._gettheme(obj, "separator")

View file

@ -1,7 +1,15 @@
{ {
"defaults": { "defaults": {
"prefix": " ", "prefix": " ",
"suffix" : " " "suffix" : " ",
"cycle": [
{
"fg": "red"
},
{
"fg": "lime"
}
]
}, },
"battery": { "battery": {
"prefix": "bat ", "prefix": "bat ",

View file

@ -24,23 +24,25 @@ def main():
sys.exit(0) sys.exit(0)
modules = [] modules = []
theme = bumblebee.theme.Theme(args.theme) if args.theme else bumblebee.theme.Theme()
for m in args.modules: for m in args.modules:
# TODO: how to cleanly handle errors here? # TODO: how to cleanly handle errors here?
# (useful error messages) # (useful error messages)
module_name = m if not ":" in m else m.split(":")[0] module_name = m if not ":" in m else m.split(":")[0]
module_args = None if not ":" in m else m.split(":")[1:] module_args = None if not ":" in m else m.split(":")[1:]
module = importlib.import_module("bumblebee.modules.{}".format(module_name)) module = importlib.import_module("bumblebee.modules.{}".format(module_name))
modules.append(getattr(module, "Module")(theme, module_args)) modules.append(getattr(module, "Module")(module_args))
output = bumblebee.outputs.i3.i3bar() theme = bumblebee.theme.Theme(args.theme) if args.theme else bumblebee.theme.Theme()
output = bumblebee.outputs.i3.i3bar(theme)
print output.start() print output.start()
sys.stdout.flush() sys.stdout.flush()
while True: while True:
theme.reset()
for m in modules: for m in modules:
output.add(m) output.add(m)
theme.next()
print output.get() print output.get()
sys.stdout.flush() sys.stdout.flush()
time.sleep(1) time.sleep(1)