263 lines
6.5 KiB
Python
263 lines
6.5 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
import enum
|
||
|
import logging
|
||
|
import threading
|
||
|
import time
|
||
|
|
||
|
# TODO Update strategies (periodic, inotify file)
|
||
|
# TODO Section order (priority system maybe ?)
|
||
|
# TODO Allow deletion of Bar, BarGroup and Section for screen changes
|
||
|
# TODO Optimize to use write() calls instead of string concatenation (writing
|
||
|
# BarGroup strings should be a good compromise)
|
||
|
|
||
|
|
||
|
class BarGroupType(enum.Enum):
|
||
|
LEFT = 0
|
||
|
RIGHT = 1
|
||
|
# MID_LEFT = 2
|
||
|
# MID_RIGHT = 3
|
||
|
|
||
|
|
||
|
class Bar:
|
||
|
"""
|
||
|
One bar for each screen
|
||
|
"""
|
||
|
|
||
|
everyone = set()
|
||
|
string = ""
|
||
|
|
||
|
@staticmethod
|
||
|
def init():
|
||
|
Section.init()
|
||
|
|
||
|
# Debug
|
||
|
Bar()
|
||
|
|
||
|
def __init__(self):
|
||
|
self.screen = 0 # TODO
|
||
|
self.groups = dict()
|
||
|
|
||
|
for groupType in BarGroupType:
|
||
|
group = BarGroup(groupType, self)
|
||
|
self.groups[groupType] = group
|
||
|
|
||
|
self.childsChanged = False
|
||
|
|
||
|
self.everyone.add(self)
|
||
|
|
||
|
@staticmethod
|
||
|
def addSectionAll(section, group, screens=None):
|
||
|
"""
|
||
|
.. note::
|
||
|
Add the section before updating it for the first time.
|
||
|
"""
|
||
|
assert isinstance(section, Section)
|
||
|
assert isinstance(group, BarGroupType)
|
||
|
# TODO screens selection
|
||
|
for bar in Bar.everyone:
|
||
|
bar.addSection(section, group=group)
|
||
|
|
||
|
def addSection(self, section, group):
|
||
|
assert isinstance(section, Section)
|
||
|
assert isinstance(group, BarGroupType)
|
||
|
self.groups[group].addSection(section)
|
||
|
|
||
|
def update(self):
|
||
|
if self.childsChanged:
|
||
|
self.string = ""
|
||
|
|
||
|
self.childsChanged = False
|
||
|
|
||
|
@staticmethod
|
||
|
def updateAll():
|
||
|
|
||
|
for bar in Bar.everyone:
|
||
|
bar.update()
|
||
|
|
||
|
Bar.string = ""
|
||
|
|
||
|
|
||
|
class BarGroup:
|
||
|
"""
|
||
|
One for each group of each bar
|
||
|
"""
|
||
|
|
||
|
everyone = set()
|
||
|
|
||
|
def __init__(self, groupType, parent):
|
||
|
assert isinstance(groupType, BarGroupType)
|
||
|
assert isinstance(parent, Bar)
|
||
|
|
||
|
self.groupType = groupType
|
||
|
self.parent = parent
|
||
|
|
||
|
self.sections = list()
|
||
|
self.string = ''
|
||
|
self.form = ''
|
||
|
|
||
|
#: One of the sections that had their theme or visibility changed
|
||
|
self.childsThemeChanged = False
|
||
|
|
||
|
#: One of the sections that had their text (maybe their size) changed
|
||
|
self.childsTextChanged = False
|
||
|
|
||
|
BarGroup.everyone.add(self)
|
||
|
|
||
|
def addSection(self, section):
|
||
|
self.sections.append(section)
|
||
|
section.parents.add(self)
|
||
|
|
||
|
def update(self):
|
||
|
if self.childsThemeChanged:
|
||
|
# TODO
|
||
|
self.form = ">".join([sec.curText for sec in self.sections
|
||
|
if sec.visible])
|
||
|
|
||
|
if self.childsTextChanged or self.childsThemeChanged:
|
||
|
print("118")
|
||
|
self.string = ">".join([sec.curText for sec in self.sections
|
||
|
if sec.visible])
|
||
|
print("|{0}|".format(self.string))
|
||
|
|
||
|
self.parent.childsChanged = True
|
||
|
|
||
|
self.childsThemeChanged = False
|
||
|
self.childsTextChanged = False
|
||
|
|
||
|
@staticmethod
|
||
|
def updateAll():
|
||
|
|
||
|
print("130")
|
||
|
|
||
|
for group in BarGroup.everyone:
|
||
|
group.update()
|
||
|
|
||
|
Bar.updateAll()
|
||
|
|
||
|
|
||
|
class SectionThread(threading.Thread):
|
||
|
def run(self):
|
||
|
while Section.somethingChanged.wait():
|
||
|
Section.updateAll()
|
||
|
while len(Section.sizeChanging) > 0:
|
||
|
time.sleep(0.1)
|
||
|
Section.updateAll()
|
||
|
|
||
|
|
||
|
class Section:
|
||
|
|
||
|
#: Sections that do not have their destination size
|
||
|
sizeChanging = set()
|
||
|
somethingChanged = threading.Event()
|
||
|
updateThread = None
|
||
|
|
||
|
@staticmethod
|
||
|
def init():
|
||
|
Section.updateThread = SectionThread(daemon=True)
|
||
|
Section.updateThread.start()
|
||
|
|
||
|
def __init__(self):
|
||
|
#: Displayed section
|
||
|
#: Note: A section can be empty and displayed!
|
||
|
self.visible = False
|
||
|
|
||
|
#: Displayed text
|
||
|
self.curText = ''
|
||
|
#: Displayed text size
|
||
|
self.curSize = 0
|
||
|
|
||
|
#: Destination text
|
||
|
self.dstText = ''
|
||
|
#: Destination size
|
||
|
self.dstSize = 0
|
||
|
|
||
|
#: Groups that have this section
|
||
|
self.parents = set()
|
||
|
|
||
|
def informParentsThemeChanged(self):
|
||
|
for parent in self.parents:
|
||
|
parent.childsThemeChanged = True
|
||
|
|
||
|
def informParentsTextChanged(self):
|
||
|
for parent in self.parents:
|
||
|
parent.childsTextChanged = True
|
||
|
|
||
|
def updateText(self, text):
|
||
|
if len(text):
|
||
|
self.dstText = ' {} '.format(text)
|
||
|
self.dstSize = len(self.dstText)
|
||
|
else:
|
||
|
self.dstSize = 0
|
||
|
|
||
|
if self.curSize == self.dstSize:
|
||
|
self.curText = self.dstText
|
||
|
self.informParentsTextChanged()
|
||
|
else:
|
||
|
Section.sizeChanging.add(self)
|
||
|
Section.somethingChanged.set()
|
||
|
|
||
|
def updateVisibility(self, visibility):
|
||
|
assert isinstance(visibility, bool)
|
||
|
|
||
|
self.visible = visibility
|
||
|
self.informParentsThemeChanged()
|
||
|
Section.somethingChanged.set()
|
||
|
|
||
|
@staticmethod
|
||
|
def fit(text, size):
|
||
|
t = len(text)
|
||
|
return text[:size] if t >= size else text + " " * (size - t)
|
||
|
|
||
|
def update(self):
|
||
|
# TODO Might profit of a better logic
|
||
|
if not self.visible:
|
||
|
self.updateVisibility(True)
|
||
|
return
|
||
|
|
||
|
if self.dstSize > self.curSize:
|
||
|
self.curSize += 1
|
||
|
elif self.dstSize < self.curSize:
|
||
|
self.curSize -= 1
|
||
|
else:
|
||
|
# Visibility toggling must be done one step after curSize = 0
|
||
|
if self.dstSize == 0:
|
||
|
self.updateVisibility(False)
|
||
|
Section.sizeChanging.remove(self)
|
||
|
return
|
||
|
|
||
|
self.curText = Section.fit(self.dstText, self.curSize)
|
||
|
self.informParentsTextChanged()
|
||
|
|
||
|
@staticmethod
|
||
|
def updateAll():
|
||
|
"""
|
||
|
Process all sections for text size changes
|
||
|
"""
|
||
|
|
||
|
for sizeChanging in Section.sizeChanging.copy():
|
||
|
sizeChanging.update()
|
||
|
# print("{1:3d} |{0}|".format(sizeChanging.curText, sizeChanging.curSize))
|
||
|
|
||
|
BarGroup.updateAll()
|
||
|
|
||
|
Section.somethingChanged.clear()
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
Bar.init()
|
||
|
sec = Section()
|
||
|
sec1 = Section()
|
||
|
Bar.addSectionAll(sec, BarGroupType.LEFT)
|
||
|
Bar.addSectionAll(sec1, BarGroupType.LEFT)
|
||
|
|
||
|
sec.updateText("Hello")
|
||
|
# sec1.updateText("world!")
|
||
|
time.sleep(2)
|
||
|
sec.updateText("Salut")
|
||
|
# sec1.updateText("le monde !")
|
||
|
time.sleep(2)
|
||
|
sec.updateText("")
|
||
|
# sec1.updateText("")
|
||
|
time.sleep(2)
|