diff --git a/i3pystatus/core/modules.py b/i3pystatus/core/modules.py index 0f5bb93..ab898f9 100644 --- a/i3pystatus/core/modules.py +++ b/i3pystatus/core/modules.py @@ -21,7 +21,6 @@ def is_method_of(method, object): class Module(SettingsBase): - output = None position = 0 settings = ( @@ -38,6 +37,7 @@ class Module(SettingsBase): ('on_doubledownscroll', "Callback called on double scroll down (see :ref:`callbacks`)"), ('on_otherclick', "Callback called on other click (see :ref:`callbacks`)"), ('on_doubleotherclick', "Callback called on double other click (see :ref:`callbacks`)"), + ('on_change', "Callback called when output is changed (see :ref:`callbacks`)"), ('multi_click_timeout', "Time (in seconds) before a single click is executed."), ('hints', "Additional output blocks for module output (see :ref:`hints`)"), ) @@ -54,6 +54,7 @@ class Module(SettingsBase): on_doubledownscroll = None on_otherclick = None + on_change = None on_doubleotherclick = None multi_click_timeout = 0.25 @@ -62,9 +63,20 @@ class Module(SettingsBase): def __init__(self, *args, **kwargs): super(Module, self).__init__(*args, **kwargs) + self._output = None self.__multi_click = MultiClickHandler(self.__button_callback_handler, self.multi_click_timeout) + @property + def output(self): + return self._output + + @output.setter + def output(self, value): + self._output = value + if self.on_change: + self.on_change() + def registered(self, status_handler): """Called when this module is registered with a status handler""" self.__status_handler = status_handler diff --git a/i3pystatus/group.py b/i3pystatus/group.py new file mode 100644 index 0000000..f8cfa51 --- /dev/null +++ b/i3pystatus/group.py @@ -0,0 +1,73 @@ +from i3pystatus import IntervalModule, Status, Module +from i3pystatus.core import util +from i3pystatus.core.imputil import ClassFinder + + +class Group(Module, Status): + """ + Module for grouping modules together + Cycles trough groups by means of scrolling + + .. code-block:: python + + group = Group() + group.register("network", + interface="eth0", + divisor=1024, + start_color='white', + format_up="{bytes_recv}K / {bytes_sent}K" + ) + group.register("network", + interface="eth0", + color_up='#FFFFFF', + format_up="{v4}" + ) + status.register(group) + + """ + on_upscroll = ['cycle_module', 1] + on_downscroll = ['cycle_module', -1] + + def __init__(self, *args, **kwargs): + Module.__init__(self, *args, **kwargs) + self.modules = util.ModuleList(self, ClassFinder(Module)) + self.active = 0 + self.__name__ = 'Group' + + def get_active_module(self): + if self.active > len(self.modules): + return + return self.modules[self.active] + + def run(self): + activemodule = self.get_active_module() + if not activemodule: + return + self.output = activemodule.output + + def register(self, *args, **kwargs): + module = Status.register(self, *args, **kwargs) + if module: + module.on_change = self.run + return module + + def cycle_module(self, increment=1): + active = self.active + increment + if active >= len(self.modules): + active = 0 + elif active < 0: + active = len(self.modules) - 1 + self.active = active + + def on_click(self, button, **kwargs): + """ + Capture scrollup and scorlldown to move in groups + Pass everthing else to the module itself + """ + if button in (4, 5): + return super().on_click(button, **kwargs) + else: + activemodule = self.get_active_module() + if not activemodule: + return + return activemodule.on_click(button, **kwargs)