22The base classes.
33"""
44
5- __all__ = [ "BaseLoop" , "BaseRenderCanvas" , "WrapperRenderCanvas" ]
5+ from __future__ import annotations
66
77import sys
88import weakref
99import importlib
10- from typing import Optional , Tuple
10+ from typing import TYPE_CHECKING
1111
1212from ._events import EventEmitter , EventType # noqa: F401
1313from ._loop import BaseLoop
1414from ._scheduler import Scheduler , UpdateMode
1515from ._coreutils import logger , log_exception , BaseEnum
1616
17+ if TYPE_CHECKING :
18+ from typing import Callable , List , Optional , Tuple
19+
20+ EventHandlerFunction = Callable [[dict ], None ]
21+ DrawFunction = Callable [[], None ]
22+
23+
24+ __all__ = ["BaseLoop" , "BaseRenderCanvas" , "WrapperRenderCanvas" ]
25+
1726
1827# Notes on naming and prefixes:
1928#
@@ -61,7 +70,7 @@ def _register_canvas(self, canvas, task):
6170 loop ._register_canvas_group (self )
6271 loop .add_task (task , name = "scheduler-task" )
6372
64- def select_loop (self , loop ) :
73+ def select_loop (self , loop : BaseLoop ) -> None :
6574 """Select the loop to use for this group of canvases."""
6675 if not (loop is None or isinstance (loop , BaseLoop )):
6776 raise TypeError ("select_loop() requires a loop instance or None." )
@@ -74,11 +83,11 @@ def select_loop(self, loop):
7483 self ._loop ._unregister_canvas_group (self )
7584 self ._loop = loop
7685
77- def get_loop (self ):
86+ def get_loop (self ) -> BaseLoop :
7887 """Get the currently associated loop (can be None for canvases that don't run a scheduler)."""
7988 return self ._loop
8089
81- def get_canvases (self ):
90+ def get_canvases (self ) -> List [ BaseRenderCanvas ] :
8291 """Get a list of currently active (not-closed) canvases for this group."""
8392 return [canvas for canvas in self ._canvases if not canvas .get_closed ()]
8493
@@ -112,7 +121,7 @@ class BaseRenderCanvas:
112121 """
113122
114123 @classmethod
115- def select_loop (cls , loop ) :
124+ def select_loop (cls , loop : BaseLoop ) -> None :
116125 """Select the loop to run newly created canvases with.
117126 Can only be called when there are no live canvases of this class.
118127 """
@@ -213,11 +222,11 @@ def __del__(self):
213222
214223 _canvas_context = None # set in get_context()
215224
216- def get_physical_size (self ):
225+ def get_physical_size (self ) -> Tuple [ int ] :
217226 """Get the physical size of the canvas in integer pixels."""
218227 return self ._rc_get_physical_size ()
219228
220- def get_context (self , context_type ) :
229+ def get_context (self , context_type : str ) -> object :
221230 """Get a context object that can be used to render to this canvas.
222231
223232 The context takes care of presenting the rendered result to the canvas.
@@ -292,13 +301,15 @@ def get_context(self, context_type):
292301
293302 # %% Events
294303
295- def add_event_handler (self , * args , ** kwargs ):
296- return self ._events .add_handler (* args , ** kwargs )
304+ def add_event_handler (
305+ self , * args : str | EventHandlerFunction , order : float = 0
306+ ) -> None :
307+ return self ._events .add_handler (* args , order = order )
297308
298- def remove_event_handler (self , * args , ** kwargs ) :
299- return self ._events .remove_handler (* args , ** kwargs )
309+ def remove_event_handler (self , callback : EventHandlerFunction , * types : str ) -> None :
310+ return self ._events .remove_handler (callback , * types )
300311
301- def submit_event (self , event ) :
312+ def submit_event (self , event : dict ) -> None :
302313 # Not strictly necessary for normal use-cases, but this allows
303314 # the ._event to be an implementation detail to subclasses, and it
304315 # allows users to e.g. emulate events in tests.
@@ -354,7 +365,13 @@ def _draw_frame(self):
354365 """
355366 pass
356367
357- def set_update_mode (self , update_mode , * , min_fps = None , max_fps = None ):
368+ def set_update_mode (
369+ self ,
370+ update_mode : UpdateMode ,
371+ * ,
372+ min_fps : Optional [float ] = None ,
373+ max_fps : Optional [float ] = None ,
374+ ) -> None :
358375 """Set the update mode for scheduling draws.
359376
360377 Arguments:
@@ -365,7 +382,7 @@ def set_update_mode(self, update_mode, *, min_fps=None, max_fps=None):
365382 """
366383 self .__scheduler .set_update_mode (update_mode , min_fps = min_fps , max_fps = max_fps )
367384
368- def request_draw (self , draw_function = None ):
385+ def request_draw (self , draw_function : Optional [ DrawFunction ] = None ) -> None :
369386 """Schedule a new draw event.
370387
371388 This function does not perform a draw directly, but schedules a draw at
@@ -388,7 +405,7 @@ def request_draw(self, draw_function=None):
388405 # storing it here, the gc can detect this case, and its fine. However,
389406 # this fails if we'd store _draw_frame on the scheduler!
390407
391- def force_draw (self ):
408+ def force_draw (self ) -> None :
392409 """Perform a draw right now.
393410
394411 In most cases you want to use ``request_draw()``. If you find yourself using
@@ -458,15 +475,15 @@ def _draw_frame_and_present(self):
458475
459476 # %% Primary canvas management methods
460477
461- def get_logical_size (self ):
478+ def get_logical_size (self ) -> Tuple [ float ] :
462479 """Get the logical size (width, height) in float pixels."""
463480 return self ._rc_get_logical_size ()
464481
465- def get_pixel_ratio (self ):
482+ def get_pixel_ratio (self ) -> float :
466483 """Get the float ratio between logical and physical pixels."""
467484 return self ._rc_get_pixel_ratio ()
468485
469- def close (self ):
486+ def close (self ) -> None :
470487 """Close the canvas."""
471488 # Clear the draw-function, to avoid it holding onto e.g. wgpu objects.
472489 self ._draw_frame = None
@@ -483,7 +500,7 @@ def close(self):
483500 # Let the subclass clean up.
484501 self ._rc_close ()
485502
486- def get_closed (self ):
503+ def get_closed (self ) -> bool :
487504 """Get whether the window is closed."""
488505 return self ._rc_get_closed ()
489506
@@ -498,14 +515,14 @@ def is_closed(self):
498515 # These methods provide extra control over the canvas. Subclasses should
499516 # implement the methods they can, but these features are likely not critical.
500517
501- def set_logical_size (self , width , height ) :
518+ def set_logical_size (self , width : float , height : float ) -> None :
502519 """Set the window size (in logical pixels)."""
503520 width , height = float (width ), float (height )
504521 if width < 0 or height < 0 :
505522 raise ValueError ("Canvas width and height must not be negative" )
506523 self ._rc_set_logical_size (width , height )
507524
508- def set_title (self , title ) :
525+ def set_title (self , title : str ) -> None :
509526 """Set the window title.
510527
511528 The words "$backend", "$loop", and "$fps" can be used as variables that
@@ -516,7 +533,7 @@ def set_title(self, title):
516533 title = title .replace ("$" + k , v )
517534 self ._rc_set_title (title )
518535
519- def set_cursor (self , cursor ) :
536+ def set_cursor (self , cursor : CursorShape ) -> None :
520537 """Set the cursor shape for the mouse pointer.
521538
522539 See :obj:`rendercanvas.CursorShape`:
@@ -658,50 +675,52 @@ class WrapperRenderCanvas(BaseRenderCanvas):
658675 _rc_canvas_group = None # No grouping for these wrappers
659676
660677 @classmethod
661- def select_loop (cls , loop ) :
678+ def select_loop (cls , loop : BaseLoop ) -> None :
662679 m = sys .modules [cls .__module__ ]
663680 return m .RenderWidget .select_loop (loop )
664681
665- def add_event_handler (self , * args , ** kwargs ):
666- return self ._subwidget ._events .add_handler (* args , ** kwargs )
682+ def add_event_handler (
683+ self , * args : str | EventHandlerFunction , order : float = 0
684+ ) -> None :
685+ return self ._subwidget ._events .add_handler (* args , order = order )
667686
668- def remove_event_handler (self , * args , ** kwargs ) :
669- return self ._subwidget ._events .remove_handler (* args , ** kwargs )
687+ def remove_event_handler (self , callback : EventHandlerFunction , * types : str ) -> None :
688+ return self ._subwidget ._events .remove_handler (callback , * types )
670689
671- def submit_event (self , event ) :
690+ def submit_event (self , event : dict ) -> None :
672691 return self ._subwidget ._events .submit (event )
673692
674- def get_context (self , * args , ** kwargs ) :
675- return self ._subwidget .get_context (* args , ** kwargs )
693+ def get_context (self , context_type : str ) -> object :
694+ return self ._subwidget .get_context (context_type )
676695
677- def request_draw (self , * args , ** kwargs ) :
678- return self ._subwidget .request_draw (* args , ** kwargs )
696+ def request_draw (self , draw_function : Optional [ DrawFunction ] = None ) -> None :
697+ return self ._subwidget .request_draw (draw_function )
679698
680- def force_draw (self ):
699+ def force_draw (self ) -> None :
681700 self ._subwidget .force_draw ()
682701
683- def get_physical_size (self ):
702+ def get_physical_size (self ) -> Tuple [ int ] :
684703 return self ._subwidget .get_physical_size ()
685704
686- def get_logical_size (self ):
705+ def get_logical_size (self ) -> Tuple [ float ] :
687706 return self ._subwidget .get_logical_size ()
688707
689- def get_pixel_ratio (self ):
708+ def get_pixel_ratio (self ) -> float :
690709 return self ._subwidget .get_pixel_ratio ()
691710
692- def set_logical_size (self , width , height ) :
711+ def set_logical_size (self , width : float , height : float ) -> None :
693712 self ._subwidget .set_logical_size (width , height )
694713
695- def set_title (self , * args ) :
696- self ._subwidget .set_title (* args )
714+ def set_title (self , title : str ) -> None :
715+ self ._subwidget .set_title (title )
697716
698- def set_cursor (self , * args ) :
699- self ._subwidget .set_cursor (* args )
717+ def set_cursor (self , cursor : CursorShape ) -> None :
718+ self ._subwidget .set_cursor (cursor )
700719
701- def close (self ):
720+ def close (self ) -> None :
702721 self ._subwidget .close ()
703722
704- def get_closed (self ):
723+ def get_closed (self ) -> bool :
705724 return self ._subwidget .get_closed ()
706725
707726 def is_closed (self ):
0 commit comments