Add sync_update attribute and draw property with refresh logic

Introduce the `sync_update` attribute to the Screen class to control synchronous screen updates. Changed `draw` into a  property to ensure the refresh state is managed correctly when the draw value changes. Included timing measurements for refresh operations and conditional refresh triggering.
pull/50/head
troyhy 2024-09-17 09:17:01 +03:00
rodzic 2f9c0ee474
commit 4aab4c1dd1
1 zmienionych plików z 24 dodań i 1 usunięć

Wyświetl plik

@ -303,6 +303,7 @@ class Display(DisplayIP):
class Screen: class Screen:
do_gc = True # Allow user to take control of GC do_gc = True # Allow user to take control of GC
sync_update = False # This will set screen updates synchronous
current_screen = None current_screen = None
is_shutdown = asyncio.Event() is_shutdown = asyncio.Event()
# These events enable user code to synchronise display refresh # These events enable user code to synchronise display refresh
@ -352,6 +353,7 @@ class Screen:
if obj.visible: # In a buttonlist only show visible button if obj.visible: # In a buttonlist only show visible button
if force or obj.draw: if force or obj.draw:
obj.show() obj.show()
force or print('r:'+str(obj)) # print object that caused update TODO: remove this
@classmethod @classmethod
def change(cls, cls_new_screen, mode=1, *, args=[], kwargs={}): def change(cls, cls_new_screen, mode=1, *, args=[], kwargs={}):
@ -416,6 +418,8 @@ class Screen:
# no factor, do_refresh confers no benefit, so use synchronous code. # no factor, do_refresh confers no benefit, so use synchronous code.
@classmethod @classmethod
async def auto_refresh(cls): async def auto_refresh(cls):
import time
arfsh = hasattr(ssd, "do_refresh") # Refresh can be asynchronous. arfsh = hasattr(ssd, "do_refresh") # Refresh can be asynchronous.
# By default rfsh_start is permanently set. User code can clear this. # By default rfsh_start is permanently set. User code can clear this.
cls.rfsh_start.set() cls.rfsh_start.set()
@ -428,10 +432,17 @@ class Screen:
await cls.rfsh_start.wait() await cls.rfsh_start.wait()
Screen.show(False) # Update stale controls. No physical refresh. Screen.show(False) # Update stale controls. No physical refresh.
# Now perform physical refresh. # Now perform physical refresh.
s = time.ticks_us()
if arfsh: if arfsh:
await ssd.do_refresh(split) await ssd.do_refresh(split)
else: else:
ssd.show() # Synchronous (blocking) refresh. ssd.show() # Synchronous (blocking) refresh.
e = time.ticks_diff(time.ticks_us(), s)
if cls.current_screen.sync_update:
print(f'ref: {e} us')
cls.rfsh_start.clear()
# Flag user code. # Flag user code.
cls.rfsh_done.set() cls.rfsh_done.set()
await asyncio.sleep_ms(0) # Let user code respond to event await asyncio.sleep_ms(0) # Let user code respond to event
@ -564,6 +575,7 @@ class Screen:
return return
def after_open(self): def after_open(self):
self.rfsh_start.set()
return return
def on_hide(self): def on_hide(self):
@ -689,7 +701,7 @@ class Widget:
self.mrow = row + height + 2 # in subclass. Allow for border. self.mrow = row + height + 2 # in subclass. Allow for border.
self.mcol = col + width + 2 self.mcol = col + width + 2
self.visible = True # Used by ButtonList class for invisible buttons self.visible = True # Used by ButtonList class for invisible buttons
self.draw = True # Signals that obect must be redrawn self._draw = True # Signals that object must be redrawn
self._value = value self._value = value
# Set colors. Writer colors cannot be None: # Set colors. Writer colors cannot be None:
@ -713,6 +725,16 @@ class Widget:
self.callback = lambda *_: None # Value change callback self.callback = lambda *_: None # Value change callback
self.args = [] self.args = []
@property
def draw(self):
return self._draw
@draw.setter
def draw(self, value):
self._draw = bool(value)
if Screen.current_screen.sync_update:
Screen.rfsh_start.set()
def warning(self): def warning(self):
print( print(
"Warning: attempt to create {} outside screen dimensions.".format( "Warning: attempt to create {} outside screen dimensions.".format(
@ -753,6 +775,7 @@ class Widget:
x = self.col x = self.col
y = self.row y = self.row
dev.fill_rect(x, y, self.width, self.height, color_map[BG] if black else self.bgcolor) dev.fill_rect(x, y, self.width, self.height, color_map[BG] if black else self.bgcolor)
Screen.rfsh_start.set() # tell driver that we need a refresh TODO: This might not be needed
return True return True
# Called by Screen.show(). Draw background and bounding box if required. # Called by Screen.show(). Draw background and bounding box if required.