f5052473fb
The idea is to simplify the way the output module currently works by: - introducing an abstraction that represents blocks; these abstractions contain all data - uninterpreted - required to draw a block - separately from that, whenever the block is serialized into JSON, do the interpretation (pango vs. non-pango, etc.) This - theoretically - should simplify code by creating two separate concerns: collecting the data and actually interpreting it.
135 lines
4.4 KiB
Python
135 lines
4.4 KiB
Python
import sys
|
|
import json
|
|
import time
|
|
|
|
import core.theme
|
|
import core.event
|
|
|
|
def dump_json(obj):
|
|
return obj.__dict__
|
|
|
|
class block(object):
|
|
__COMMON_THEME_FIELDS = [
|
|
'separator', 'separator_block_width',
|
|
'border_top', 'border_left', 'border_right', 'border_bottom',
|
|
'pango', 'fg', 'bg'
|
|
]
|
|
def __init__(self, theme, module, widget):
|
|
self.__attributes = {}
|
|
for key in self.__COMMON_THEME_FIELDS:
|
|
tmp = theme.get(key, widget)
|
|
if tmp:
|
|
self.__attributes[key] = tmp
|
|
|
|
self.__attributes['name'] = module.id
|
|
self.__attributes['instance'] = widget.id
|
|
|
|
def set(self, key, value):
|
|
self.__attributes[key] = value
|
|
|
|
def __dict__(self):
|
|
return {}
|
|
|
|
class i3(object):
|
|
def __init__(self, theme=core.theme.Theme(), config=core.config.Config([])):
|
|
self.__modules = []
|
|
self.__content = {}
|
|
self.__theme = theme
|
|
self.__config = config
|
|
core.event.register('start', self.draw, 'start')
|
|
core.event.register('update', self.draw, 'statusline')
|
|
core.event.register('stop', self.draw, 'stop')
|
|
|
|
def theme(self, new_theme=None):
|
|
if new_theme:
|
|
self.__theme = new_theme
|
|
return self.__theme
|
|
|
|
def modules(self, modules=None):
|
|
if not modules:
|
|
return self.__modules
|
|
self.__modules = modules if isinstance(modules, list) else [ modules ]
|
|
|
|
def draw(self, what, args=None):
|
|
cb = getattr(self, what)
|
|
data = cb(args) if args else cb()
|
|
if 'blocks' in data:
|
|
sys.stdout.write(json.dumps(data['blocks'], default=dump_json))
|
|
if 'suffix' in data:
|
|
sys.stdout.write(data['suffix'])
|
|
sys.stdout.write('\n')
|
|
sys.stdout.flush()
|
|
|
|
def start(self):
|
|
return {
|
|
'blocks': { 'version': 1, 'click_events': True },
|
|
'suffix': '\n[',
|
|
}
|
|
|
|
def stop(self):
|
|
return { 'suffix': '\n]' }
|
|
|
|
def __pad(self, module, widget, full_text):
|
|
padding = self.__theme.padding()
|
|
if not full_text: return padding
|
|
return '{}{}{}'.format(padding, full_text, padding)
|
|
|
|
def __decorate(self, module, widget, full_text):
|
|
if full_text is None: return None
|
|
return '{}{}{}'.format(
|
|
self.__pad(module, widget, self.__theme.prefix(widget)),
|
|
full_text,
|
|
self.__pad(module, widget, self.__theme.suffix(widget))
|
|
)
|
|
|
|
def __separator_block(self, module, widget):
|
|
blk = block(self.__theme, module, widget)
|
|
blk.set('_decorator', True)
|
|
return blk
|
|
|
|
def __content_block(self, module, widget):
|
|
text = self.__content[widget]
|
|
blk = block(self.__theme, module, widget)
|
|
blk.set('min_width', self.__decorate(module, widget, widget.get('theme.minwidth')))
|
|
blk.set('full_text', self.__decorate(module, widget, text))
|
|
if self.__config.debug():
|
|
blk.set('__state', ', '.join(module.state(widget)))
|
|
return blk
|
|
|
|
def blocks(self, module):
|
|
blocks = []
|
|
for widget in module.widgets():
|
|
if widget.module() and self.__config.autohide(widget.module().name()):
|
|
if not any(state in widget.state() for state in [ 'warning', 'critical']):
|
|
continue
|
|
blocks.append(self.__separator_block(module, widget))
|
|
blocks.append(self.__content_block(module, widget))
|
|
core.event.trigger('next-widget')
|
|
return blocks
|
|
|
|
def update(self, affected_modules=None):
|
|
now = time.time()
|
|
for module in self.__modules:
|
|
if affected_modules and not module.id in affected_modules:
|
|
continue
|
|
if not affected_modules and module.next_update:
|
|
if now < module.next_update:
|
|
continue
|
|
module.update_wrapper()
|
|
module.next_update = now + float(module.parameter('interval', self.__config.interval()))
|
|
for widget in module.widgets():
|
|
self.__content[widget] = widget.full_text()
|
|
|
|
def statusline(self):
|
|
blocks = []
|
|
for module in self.__modules:
|
|
blocks.extend(self.blocks(module))
|
|
return {
|
|
'blocks': blocks,
|
|
'suffix': ','
|
|
}
|
|
|
|
def wait(self, interval):
|
|
time.sleep(interval)
|
|
|
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|