Skip to content

Commit b066ee0

Browse files
chore: improve typing (#562)
1 parent ec1bf2a commit b066ee0

9 files changed

Lines changed: 372 additions & 73 deletions

File tree

libs/pyTermTk/TermTk/TTkAbstract/abstractscrollarea.py

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@
2323
__all__ = ['TTkAbstractScrollArea']
2424

2525
from dataclasses import dataclass
26-
from typing import List,Any,Type
26+
from typing import List,Any,Type,Optional
2727

2828
from TermTk.TTkCore.constant import TTkK
2929
# from TermTk.TTkCore.log import TTkLog
3030
from TermTk.TTkCore.signal import pyTTkSlot
3131
from TermTk.TTkWidgets.widget import TTkWidget
3232
from TermTk.TTkWidgets.container import TTkContainer
3333
from TermTk.TTkWidgets.scrollbar import TTkScrollBar
34+
from TermTk.TTkLayouts.layout import TTkLayout
3435
from TermTk.TTkLayouts.gridlayout import TTkGridLayout
3536
from TermTk.TTkAbstract.abstractscrollview import TTkAbstractScrollViewInterface
3637

@@ -42,12 +43,25 @@ class _ForwardData():
4243
methods: List[str]
4344

4445
class TTkAbstractScrollArea(TTkContainer):
46+
'''
47+
The :py:class:`TTkAbstractScrollArea` provides a scrolling area with on-demand scroll bars.
48+
49+
This abstract class manages vertical and horizontal scroll bars that appear automatically
50+
based on the viewport size and content.
51+
'''
4552
__slots__ = (
4653
'_processing', # this flag is required to avoid unnecessary loop on edge cases
4754
'_viewport',
4855
'_verticalScrollBar', '_verticalScrollBarPolicy',
4956
'_horizontalScrollBar', '_horizontalScrollBarPolicy',)
5057

58+
_processing:bool
59+
_viewport:Optional[TTkAbstractScrollViewInterface]
60+
_verticalScrollBar:TTkScrollBar
61+
_horizontalScrollBar:TTkScrollBar
62+
_verticalScrollBarPolicy:TTkK.ScrollBarPolicy
63+
_horizontalScrollBarPolicy:TTkK.ScrollBarPolicy
64+
5165
def __init__(self, *,
5266
verticalScrollBarPolicy:TTkK.ScrollBarPolicy=TTkK.ScrollBarPolicy.ScrollBarAsNeeded,
5367
horizontalScrollBarPolicy:TTkK.ScrollBarPolicy=TTkK.ScrollBarPolicy.ScrollBarAsNeeded,
@@ -63,8 +77,10 @@ def __init__(self, *,
6377
self.layout().addWidget(self._verticalScrollBar)
6478
self.layout().addWidget(self._horizontalScrollBar)
6579

66-
def _resizeEvent(self):
67-
if self._processing: return
80+
def _resizeEvent(self) -> None:
81+
''' Internal method to handle resize events and reposition scroll bars '''
82+
if self._processing:
83+
return
6884
self._processing = True
6985
w,h = self.size()
7086
vert = 1 if self._verticalScrollBar.isVisible() else 0
@@ -73,16 +89,24 @@ def _resizeEvent(self):
7389
self._verticalScrollBar.setGeometry(w-1,0,1,h-hori)
7490
if hori:
7591
self._horizontalScrollBar.setGeometry(0,h-1,w-vert,1)
76-
if self._viewport:
92+
if isinstance(self._viewport, (TTkWidget, TTkLayout)):
7793
self._viewport.setGeometry(0,0,w-vert,h-hori)
7894
self._processing = False
7995

80-
def resizeEvent(self, w: int, h: int):
96+
def resizeEvent(self, w: int, h: int) -> None:
97+
''' Handle resize events
98+
99+
:param w: the new width
100+
:type w: int
101+
:param h: the new height
102+
:type h: int
103+
'''
81104
self._resizeEvent()
82105

83106
@pyTTkSlot()
84-
def _viewportChanged(self):
85-
if not self.isVisible(): return
107+
def _viewportChanged(self) -> None:
108+
''' Internal slot to handle viewport changes and update scroll bar ranges and visibility '''
109+
if not self._viewport or not self.isVisible(): return
86110
w,h = self.size()
87111
fw, fh = self._viewport.viewFullAreaSize()
88112
dw, dh = self._viewport.viewDisplayedSize()
@@ -125,16 +149,37 @@ def _viewportChanged(self):
125149
self._resizeEvent()
126150

127151
@pyTTkSlot(int)
128-
def _vscrollMoved(self, val):
152+
def _vscrollMoved(self, val: int) -> None:
153+
''' Internal slot to handle vertical scroll bar movement
154+
155+
:param val: the new vertical scroll position
156+
:type val: int
157+
'''
158+
if not self._viewport:
159+
return
129160
ox, _ = self._viewport.getViewOffsets()
130161
self._viewport.viewMoveTo(ox, val)
131162

132163
@pyTTkSlot(int)
133-
def _hscrollMoved(self, val):
164+
def _hscrollMoved(self, val: int) -> None:
165+
''' Internal slot to handle horizontal scroll bar movement
166+
167+
:param val: the new horizontal scroll position
168+
:type val: int
169+
'''
170+
if not self._viewport:
171+
return
134172
_, oy = self._viewport.getViewOffsets()
135173
self._viewport.viewMoveTo(val, oy)
136174

137-
def setViewport(self, viewport):
175+
def setViewport(self, viewport: TTkAbstractScrollViewInterface) -> None:
176+
''' Set the viewport widget
177+
178+
:param viewport: the viewport widget implementing TTkAbstractScrollViewInterface
179+
:type viewport: :py:class:`TTkAbstractScrollViewInterface`
180+
181+
:raises TypeError: if viewport does not implement TTkAbstractScrollViewInterface
182+
'''
138183
if not isinstance(viewport, TTkAbstractScrollViewInterface):
139184
raise TypeError("TTkAbstractScrollViewInterface is required in TTkAbstractScrollArea.setVewport(viewport)")
140185
if self._viewport:
@@ -157,20 +202,44 @@ def setViewport(self, viewport):
157202
self.layout().addItem(viewport)
158203
self._resizeEvent()
159204

160-
def setVerticalScrollBarPolicy(self, policy):
205+
def setVerticalScrollBarPolicy(self, policy: TTkK.ScrollBarPolicy) -> None:
206+
''' Set the vertical scroll bar policy
207+
208+
:param policy: the scroll bar policy (ScrollBarAsNeeded, ScrollBarAlwaysOn, ScrollBarAlwaysOff)
209+
:type policy: :py:class:`TTkK.ScrollBarPolicy`
210+
'''
161211
if policy != self._verticalScrollBarPolicy:
162212
self._verticalScrollBarPolicy = policy
163213
self._viewportChanged()
164214

165-
def setHorizontalScrollBarPolicy(self, policy):
215+
def setHorizontalScrollBarPolicy(self, policy: TTkK.ScrollBarPolicy) -> None:
216+
''' Set the horizontal scroll bar policy
217+
218+
:param policy: the scroll bar policy (ScrollBarAsNeeded, ScrollBarAlwaysOn, ScrollBarAlwaysOff)
219+
:type policy: :py:class:`TTkK.ScrollBarPolicy`
220+
'''
166221
if policy != self._horizontalScrollBarPolicy:
167222
self._horizontalScrollBarPolicy = policy
168223
self._viewportChanged()
169224

170-
def viewport(self) -> TTkAbstractScrollViewInterface:
225+
def viewport(self) -> Optional[TTkAbstractScrollViewInterface]:
226+
''' Return the current viewport
227+
228+
:return: the viewport widget or None
229+
:rtype: :py:class:`TTkAbstractScrollViewInterface`, optional
230+
'''
171231
return self._viewport
172232

173-
def update(self, repaint=True, updateLayout=False, updateParent=False):
174-
if self._viewport:
233+
def update(self, repaint: bool = True, updateLayout: bool = False, updateParent: bool = False) -> None:
234+
''' Update the scroll area and viewport
235+
236+
:param repaint: trigger a repaint, defaults to True
237+
:type repaint: bool, optional
238+
:param updateLayout: trigger a layout update, defaults to False
239+
:type updateLayout: bool, optional
240+
:param updateParent: trigger a parent update, defaults to False
241+
:type updateParent: bool, optional
242+
'''
243+
if isinstance(self._viewport, (TTkWidget, TTkLayout)):
175244
self._viewport.update(repaint, updateLayout, updateParent=False)
176245
return super().update(repaint, updateLayout, updateParent)

0 commit comments

Comments
 (0)