Skip to content

Commit

Permalink
Changed that CanvasGroup's loop can be set to None, instead of settin…
Browse files Browse the repository at this point in the history
…g _rc_canvas_group to None
  • Loading branch information
almarklein committed Dec 6, 2024
1 parent 46eee9d commit 664ba5b
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 19 deletions.
12 changes: 6 additions & 6 deletions docs/backendapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ Also see https://github.com/pygfx/rendercanvas/blob/main/rendercanvas/stub.py.
with each version without warning.


.. autoclass:: rendercanvas.stub.StubCanvasGroup
.. autoclass:: rendercanvas.stub.StubLoop
:members:
:private-members:
:member-order: bysource


.. autoclass:: rendercanvas.stub.StubRenderCanvas
.. autoclass:: rendercanvas.stub.StubCanvasGroup
:members:
:private-members:
:member-order: bysource


.. autoclass:: rendercanvas.base.WrapperRenderCanvas


.. autoclass:: rendercanvas.stub.StubLoop
.. autoclass:: rendercanvas.stub.StubRenderCanvas
:members:
:private-members:
:member-order: bysource


.. autoclass:: rendercanvas.base.WrapperRenderCanvas
28 changes: 18 additions & 10 deletions rendercanvas/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,32 @@ class BaseCanvasGroup:

def __init__(self, default_loop):
self._canvases = weakref.WeakSet()
self._loop = default_loop
self._loop = None
self.select_loop(default_loop)

def _register_canvas(self, canvas, task):
"""Used by the canvas to register itself."""
self._canvases.add(canvas)
loop = self.get_loop()
loop._register_canvas_group(self)
loop.add_task(task, name="scheduler-task")
if loop is not None:
loop._register_canvas_group(self)
loop.add_task(task, name="scheduler-task")

def select_loop(self, loop):
"""Select the loop to use for this group of canvases."""
if not isinstance(loop, BaseLoop):
raise TypeError("select_loop() requires a loop instance.")
if not (loop is None or isinstance(loop, BaseLoop)):
raise TypeError("select_loop() requires a loop instance or None.")
elif len(self._canvases):
raise RuntimeError("Cannot select_loop() when live canvases exist.")
elif loop is self._loop:
pass
else:
self._loop._unregister_canvas_group(self)
if self._loop is not None:
self._loop._unregister_canvas_group(self)
self._loop = loop

def get_loop(self):
"""Get the currently associated loop."""
"""Get the currently associated loop (can be None for canvases that don't run a scheduler)."""
return self._loop

def get_canvases(self):
Expand Down Expand Up @@ -88,7 +90,6 @@ class BaseRenderCanvas:
_rc_canvas_group = None
"""Class attribute that refers to the ``CanvasGroup`` instance to use for canvases of this class.
It specifies what loop is used, and enables users to changing the used loop.
Set to None to not use a loop.
"""

@classmethod
Expand Down Expand Up @@ -132,14 +133,19 @@ def __init__(
"fps": "?",
"backend": self.__class__.__name__,
"loop": self._rc_canvas_group.get_loop().__class__.__name__
if self._rc_canvas_group
if (self._rc_canvas_group and self._rc_canvas_group.get_loop())
else "no-loop",
}

# Events and scheduler
self._events = EventEmitter()
self.__scheduler = None
if self._rc_canvas_group is not None:
if self._rc_canvas_group is None:
pass # No scheduling, not even grouping
elif self._rc_canvas_group.get_loop() is None:
# Group, but no loop: no scheduling
self._rc_canvas_group._register_canvas(self, None)
else:
self.__scheduler = Scheduler(
self,
self._events,
Expand Down Expand Up @@ -583,6 +589,8 @@ class WrapperRenderCanvas(BaseRenderCanvas):
wrapped canvas and set it as ``_subwidget``.
"""

_rc_canvas_group = None # No grouping for these wrappers

@classmethod
def select_loop(cls, loop):
m = sys.modules[cls.__module__]
Expand Down
8 changes: 6 additions & 2 deletions rendercanvas/offscreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@

import time

from .base import BaseRenderCanvas, BaseLoop
from .base import BaseCanvasGroup, BaseRenderCanvas, BaseLoop


class OffscreenCanvasGroup(BaseCanvasGroup):
pass


class ManualOffscreenRenderCanvas(BaseRenderCanvas):
Expand All @@ -15,7 +19,7 @@ class ManualOffscreenRenderCanvas(BaseRenderCanvas):
Call the ``.draw()`` method to perform a draw and get the result.
"""

_rc_canvas_group = None # unmanaged, no loop
_rc_canvas_group = OffscreenCanvasGroup(None) # no loop, no scheduling

def __init__(self, *args, pixel_ratio=1.0, **kwargs):
super().__init__(*args, **kwargs)
Expand Down
5 changes: 4 additions & 1 deletion rendercanvas/stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ def _rc_call_later(self, delay, callback):
raise NotImplementedError()


loop = StubLoop()


class StubCanvasGroup(BaseCanvasGroup):
"""
The ``CanvasGroup`` representss a group of canvas objects from the same class, that share a loop.
Expand Down Expand Up @@ -75,7 +78,7 @@ def _draw_frame_and_present(self):

# Must be implemented by subclasses.

_rc_canvas_group = None
_rc_canvas_group = StubCanvasGroup(loop)

def _rc_gui_poll(self):
raise NotImplementedError()
Expand Down

0 comments on commit 664ba5b

Please sign in to comment.