290f95d6b4
When pressing the middle mouse button (and it's not assigned to any other functionality), the module (i.e. all widgets of that module) will disappear and be replaced with the module's icon (or prefix, as fallback) and an ellipsis. fixes #264
147 lines
4.6 KiB
Python
147 lines
4.6 KiB
Python
# pylint: disable=R0201
|
|
|
|
"""Output classes"""
|
|
|
|
import sys
|
|
import json
|
|
import uuid
|
|
|
|
import bumblebee.store
|
|
|
|
def scrollable(func):
|
|
def wrapper(module, widget):
|
|
text = func(module, widget)
|
|
if not text: return text
|
|
width = widget.get("theme.width", module.parameter("width", 30))
|
|
widget.set("theme.minwidth", "A"*width)
|
|
if len(text) <= width:
|
|
return text
|
|
# we need to shorten
|
|
start = widget.get("scrolling.start", -1)
|
|
direction = widget.get("scrolling.direction", "right")
|
|
start += 1 if direction == "right" else -1
|
|
widget.set("scrolling.start", start)
|
|
if width + start >= len(text):
|
|
widget.set("scrolling.direction", "left")
|
|
if start <= 0:
|
|
widget.set("scrolling.direction", "right")
|
|
text = text[start:width+start]
|
|
|
|
return text
|
|
return wrapper
|
|
|
|
class Widget(bumblebee.store.Store):
|
|
"""Represents a single visible block in the status bar"""
|
|
def __init__(self, full_text="", name=""):
|
|
super(Widget, self).__init__()
|
|
self._full_text = full_text
|
|
self.module = None
|
|
self._module = None
|
|
self.name = name
|
|
self.id = str(uuid.uuid4())
|
|
|
|
def get_module(self):
|
|
return self._module
|
|
|
|
def link_module(self, module):
|
|
"""Set the module that spawned this widget
|
|
|
|
This is done outside the constructor to avoid having to
|
|
pass in the module name in every concrete module implementation"""
|
|
self.module = module.name
|
|
self._module = module
|
|
|
|
def cls(self):
|
|
if not self._module:
|
|
return None
|
|
return self._module.__module__.replace("bumblebee.modules.", "")
|
|
|
|
def state(self):
|
|
"""Return the widget's state"""
|
|
if self._module and hasattr(self._module, "state"):
|
|
states = self._module.state(self)
|
|
if not isinstance(states, list):
|
|
return [states]
|
|
return states
|
|
return []
|
|
|
|
def full_text(self, value=None):
|
|
"""Set or retrieve the full text to display in the widget"""
|
|
if value:
|
|
self._full_text = value
|
|
else:
|
|
if callable(self._full_text):
|
|
return self._full_text(self)
|
|
else:
|
|
return self._full_text
|
|
|
|
class I3BarOutput(object):
|
|
"""Manage output according to the i3bar protocol"""
|
|
def __init__(self, theme):
|
|
self._theme = theme
|
|
self._widgets = []
|
|
self._started = False
|
|
|
|
def started(self):
|
|
return self._started
|
|
|
|
def start(self):
|
|
"""Print start preamble for i3bar protocol"""
|
|
self._started = True
|
|
sys.stdout.write(json.dumps({"version": 1, "click_events": True}) + "\n[\n")
|
|
|
|
def stop(self):
|
|
"""Finish i3bar protocol"""
|
|
sys.stdout.write("]\n")
|
|
|
|
def draw(self, widget, module=None, engine=None):
|
|
"""Draw a single widget"""
|
|
full_text = widget.full_text()
|
|
if widget.get_module() and widget.get_module().hidden():
|
|
return
|
|
padding = self._theme.padding(widget)
|
|
prefix = self._theme.prefix(widget, padding)
|
|
suffix = self._theme.suffix(widget, padding)
|
|
|
|
if prefix:
|
|
full_text = u"{}{}".format(prefix, full_text)
|
|
if suffix:
|
|
full_text = u"{}{}".format(full_text, suffix)
|
|
|
|
separator = self._theme.separator(widget)
|
|
if separator:
|
|
self._widgets.append({
|
|
u"full_text": separator,
|
|
"separator": False,
|
|
"color": self._theme.separator_fg(widget),
|
|
"background": self._theme.separator_bg(widget),
|
|
"separator_block_width": self._theme.separator_block_width(widget),
|
|
})
|
|
width = self._theme.minwidth(widget)
|
|
self._widgets.append({
|
|
u"full_text": full_text,
|
|
"color": self._theme.fg(widget),
|
|
"background": self._theme.bg(widget),
|
|
"separator_block_width": self._theme.separator_block_width(widget),
|
|
"separator": True if separator is None else False,
|
|
"min_width": width + "A"*(len(prefix) + len(suffix)) if width else None,
|
|
"align": self._theme.align(widget),
|
|
"instance": widget.id,
|
|
"name": module.id,
|
|
})
|
|
|
|
def begin(self):
|
|
"""Start one output iteration"""
|
|
self._widgets = []
|
|
self._theme.reset()
|
|
|
|
def flush(self):
|
|
"""Flushes output"""
|
|
sys.stdout.write(json.dumps(self._widgets))
|
|
|
|
def end(self):
|
|
"""Finalizes output"""
|
|
sys.stdout.write(",\n")
|
|
sys.stdout.flush()
|
|
|
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|