Last active
October 19, 2021 00:14
-
-
Save jdtsmith/76f7e7dd7adea768a284140fe2c81e59 to your computer and use it in GitHub Desktop.
LVGL MicroPython custom set_attribute
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import lvgl as lv | |
import display | |
fontBase = 'font_montserrat' | |
# Colors (+ BLACK and WHITE, NONE = black) | |
# AMBER BLUE BLUE_GREY BROWN | |
# CYAN DEEP_ORANGE DEEP_PURPLE GREEN | |
# GREY INDIGO LIGHT_BLUE LIGHT_GREEN | |
# LIME NONE ORANGE PINK | |
# PURPLE RED TEAL YELLOW | |
def color(col): | |
shift = 0 | |
if isinstance(col, (list, tuple)): | |
col, shift = col | |
col = col.upper() | |
if col in ("BLACK","WHITE"): | |
col = getattr(lv,"color_"+col.lower())() | |
else: | |
col = getattr(lv.PALETTE,col) | |
if shift>0: | |
col=lv.palette_lighten(col,shift) | |
elif shift<0: | |
col=lv.palette_darken(col,-shift) | |
else: | |
col=lv.palette_main(col) | |
return col | |
def opa(opa): | |
return max(0,min(255,round(opa*255))) | |
def size(value): | |
if value == "full": # String full/content/percentage width/heigth | |
value = lv.pct(100) | |
elif value == "content": | |
value = lv.SIZE.CONTENT | |
elif value.endswith("%"): | |
value = lv.pct(int(value[:-1])) | |
return value | |
class LVGLObj: | |
attr_priority = dict(x=1, y=1, | |
text_align=2, scroll=2, | |
size=3, width=3, height=3) | |
def __init__(self, lvo, **kwds): | |
self._lvo = lvo | |
#print(f"GOT LVO: {self._lvo}") | |
self.set(**kwds) | |
def __del__(self, extra = None): | |
objs=[self] | |
if extra is not None: | |
if isinstance(extra, (tuple, list)): | |
objs.extend(extra) | |
else: | |
objs.append(extra) | |
for obj in objs: | |
if not obj: continue | |
try: | |
obj.delete() | |
except lv.LvReferenceError: | |
pass # perhaps was already deleted! | |
def set(self, **kwds): | |
didPause = display.pause() | |
for k,v in sorted(kwds.items(), | |
key=lambda x: self.attr_priority.get(x[0]) or 0): | |
setattr(self, k, v) | |
if didPause: display.resume() | |
# fontSize's: 8, 14, 16, 20, 24, 28, 32, 36, 40, "large" | |
@property | |
def fontSize(self): | |
return self._fontSize | |
@fontSize.setter | |
def fontSize(self, fs): | |
"""Set font to a given size in points, or the special value "large".""" | |
self._fontSize = fs | |
if fs == "large": | |
font = display.largeFont | |
elif fs==8: | |
font=lv.font_unscii_8 | |
else: | |
font = getattr(lv,f'{fontBase}_{fs}') | |
self.text_font = font | |
def __getattr__(self, attr, lvobj = None): | |
"""Generic getter for get{_style}_{attr} and obj.FLAG/lv.STATE values.""" | |
# runs *after* actual object attributes are looked up, so | |
# avoid name collisions and use _attribute | |
if attr == "lvo": return self._lvo | |
lvobj = lvobj or self._lvo | |
if hasattr(lvobj, attr): # priority 1: likely a method to call | |
return getattr(lvobj, attr) | |
elif hasattr(lvobj, f'get_{attr}'): # get_x() | |
return getattr(lvobj, f'get_{attr}')() | |
elif hasattr(lvobj, f'get_style_{attr}'): # get_style_x() | |
return getattr(lvobj, f'get_style_{attr}')(lv.PART.MAIN) | |
elif lvobj and hasattr(lv.obj.FLAG, attr): # o.FLAG.x | |
return getattr(lvobj.FLAG, attr) | |
elif lvobj and hasattr(lv.STATE, attr): # o.STATE | |
return lvobj.state & getattr(lv.STATE, attr) | |
else: | |
raise AttributeError(f"No such attribute: {attr}") | |
def __setattr__(self, attr, value, lvobj = None): | |
"""Generic setter for set{_style}_{attr}, and obj.FLAG values. | |
Handles tuples/lists, and pre-processes, color (string color | |
or (string color, integer shift) tuple), opacity (float 0-1), | |
alignment (string from lv.ALIGN or lv.TEXT_ALIGN), and | |
width/height/size ("content", "full", or "xxx%", tuple | |
permitted for size). All internal variables starting with "_" | |
are assigned as attributes on the object itself. | |
""" | |
if attr.startswith("_"): # Special case: internal variables | |
object.__setattr__(self, attr, value) | |
return | |
lvobj = lvobj or self._lvo | |
#print(f"Setting {self}.{attr} to {value}") | |
if attr.endswith("_color"): | |
value = color(value) # String or tuple for color | |
elif attr.endswith("opa"): | |
value = opa(value) # Percentage opacity | |
elif attr in ("width","height","x","y") and isinstance(value, str): | |
value = size(value) | |
elif attr == "align": | |
value = getattr(lv.ALIGN, value) # String alignment | |
elif attr == "text_align": | |
value = getattr(lv.TEXT_ALIGN, value) # String text alignment | |
elif attr == "size": | |
if isinstance(value, str): | |
value = (size(value),) *2 | |
elif isinstance(value, (tuple, list)): | |
value = tuple(size(x) if isinstance(x, str) else x for x in value) | |
# On textareas, set_align sets text alignment and is deprecated. Use | |
# set_style_align there instead. | |
if (hasattr(lvobj, f'set_{attr}') and # set_x | |
not (attr == "align" and isinstance(lvobj, lv.textarea))): | |
if isinstance(value, (tuple, list)): | |
getattr(lvobj, f'set_{attr}')(*value) | |
else: | |
getattr(lvobj, f'set_{attr}')(value) | |
elif hasattr(lvobj,f'set_style_{attr}'): # set_style_x | |
getattr(lvobj,f'set_style_{attr}')(value, 0) | |
elif lvobj and hasattr(lv.obj.FLAG, attr): # add|clear_flag(x) | |
flag = getattr(lv.obj.FLAG, attr) | |
if value: | |
lvobj.add_flag(flag) | |
else: | |
lvobj.clear_flag(flag) | |
elif lvobj and hasattr(lv.STATE, attr): # add|clear_state(x) | |
flag = getattr(lv.STATE, attr) | |
if value: | |
lvobj.add_state(flag) | |
else: | |
lvobj.clear_state(flag) | |
else: # Just assign a regular object attribute | |
object.__setattr__(self, attr, value) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment