Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/3334.2.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The web backend now supports the ScrollContainer widget.
6 changes: 4 additions & 2 deletions docs/reference/api/containers/scrollcontainer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ overflow controlled by scroll bars.
:align: center
:width: 450px

.. group-tab:: Web |no|
.. group-tab:: Web

Not supported
.. figure:: /reference/images/scrollcontainer-web.png
:align: center
:width: 450px

.. group-tab:: Textual |no|

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/data/widgets_by_platform.csv
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Tree,General Widget,:class:`~toga.Tree`,A widget for displaying a hierarchical t
WebView,General Widget,:class:`~toga.WebView`,A panel for displaying HTML,|y|,|y|,|y|,|y|,|y|,,
Widget,General Widget,:class:`~toga.Widget`,The base widget,|y|,|y|,|y|,|y|,|y|,|b|,|b|
Box,Layout Widget,:class:`~toga.Box`,Container for components,|y|,|y|,|y|,|y|,|y|,|b|,|b|
ScrollContainer,Layout Widget,:class:`~toga.ScrollContainer`,A container that can display a layout larger than the area of the container,|y|,|y|,|y|,|y|,|y|,,
ScrollContainer,Layout Widget,:class:`~toga.ScrollContainer`,A container that can display a layout larger than the area of the container,|y|,|y|,|y|,|y|,|y|,|b|,
SplitContainer,Layout Widget,:class:`~toga.SplitContainer`,A container that divides an area into two panels with a movable border,|y|,|y|,|y|,,,,
OptionContainer,Layout Widget,:class:`~toga.OptionContainer`,A container that can display multiple labeled tabs of content,|y|,|y|,|y|,|y|,|y|,,
Camera,Hardware,:class:`~toga.hardware.camera.Camera`,A sensor that can capture photos and/or video.,|y|,,,|y|,|y|,,
Expand Down
Binary file added docs/reference/images/scrollcontainer-web.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions web/src/toga_web/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
# from .widgets.optioncontainer import OptionContainer
from .widgets.passwordinput import PasswordInput
from .widgets.progressbar import ProgressBar
from .widgets.scrollcontainer import ScrollContainer

# from .widgets.scrollcontainer import ScrollContainer
# from .widgets.selection import Selection
# from .widgets.slider import Slider
# from .widgets.splitcontainer import SplitContainer
Expand Down Expand Up @@ -71,7 +71,7 @@ def not_implemented(feature):
"PasswordInput",
"ProgressBar",
"ActivityIndicator",
# 'ScrollContainer',
"ScrollContainer",
# 'Selection',
# 'Slider',
# 'SplitContainer',
Expand Down
4 changes: 3 additions & 1 deletion web/src/toga_web/widgets/button.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from toga_web.libs import create_proxy

from .base import Widget


class Button(Widget):
def create(self):
self.native = self._create_native_widget("sl-button")
self.native.onclick = self.dom_onclick
self.native.addEventListener("onclick", create_proxy(self.dom_onclick))

def dom_onclick(self, event):
self.interface.on_press()
Expand Down
6 changes: 0 additions & 6 deletions web/src/toga_web/widgets/passwordinput.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
from toga_web.libs import create_proxy

from .textinput import TextInput


class PasswordInput(TextInput):
def create(self):
super().create()
self.native.setAttribute("type", "password")
self.native.addEventListener("sl-change", create_proxy(self.dom_onchange))

def dom_onchange(self, event):
self.interface.on_change(None)

def is_valid(self):
self.interface.factory.not_implemented("PasswordInput.is_valid()")
Expand Down
79 changes: 79 additions & 0 deletions web/src/toga_web/widgets/scrollcontainer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from toga_web.libs import create_proxy

from .base import Widget


class ScrollContainer(Widget):
def __init__(self, interface):
super().__init__(interface)
self.native.addEventListener("scroll", create_proxy(self.dom_onscroll))

def create(self):
self._horizontal_enabled = True
self._vertical_enabled = True

self.native = self._create_native_widget(
"div",
classes=["container"],
)
self._content_div = self._create_native_widget(
"div",
classes=["toga-scroll-content"],
)
self.native.appendChild(self._content_div)
self._update_overflow()

def set_content(self, content_impl):
while self._content_div.firstChild:
self._content_div.removeChild(self._content_div.firstChild)

if content_impl is not None:
self._content_div.appendChild(content_impl.native)

def _update_overflow(self):
self.native.style.overflowX = "auto" if self._horizontal_enabled else "hidden"
self.native.style.overflowY = "auto" if self._vertical_enabled else "hidden"

def get_horizontal(self):
return self._horizontal_enabled

def set_horizontal(self, value):
self._horizontal_enabled = bool(value)
self._update_overflow()

def get_vertical(self):
return self._vertical_enabled

def set_vertical(self, value):
self._vertical_enabled = bool(value)
self._update_overflow()

def get_max_horizontal_position(self):
return max(0, self.native.scrollWidth - self.native.clientWidth)

def get_max_vertical_position(self):
return max(0, self.native.scrollHeight - self.native.clientHeight)

def get_horizontal_position(self):
return self.native.scrollLeft

def get_vertical_position(self):
return self.native.scrollTop

def set_position(self, horizontal, vertical):
if self._horizontal_enabled:
horizontal = max(
0, min(int(horizontal), self.get_max_horizontal_position())
)
else:
horizontal = self.native.scrollLeft

if self._vertical_enabled:
vertical = max(0, min(int(vertical), self.get_max_vertical_position()))
else:
vertical = self.native.scrollTop

self.native.scrollTo(horizontal, vertical)

def dom_onscroll(self, _evt):
self.interface.on_scroll()
14 changes: 10 additions & 4 deletions web/src/toga_web/widgets/textinput.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
from toga_web.libs import create_proxy

from .base import Widget


class TextInput(Widget):
def create(self):
self._return_listener = None
self.native = self._create_native_widget("sl-input")
self.native.onkeyup = self.dom_keyup
self.native.onkeyup = self.dom_onkeyup
self.native.addEventListener("onkeyup", create_proxy(self.dom_onkeyup))
self.native.addEventListener("sl-change", create_proxy(self.dom_sl_change))

def dom_onkeyup(self, event):
self.interface.on_change()

def dom_keyup(self, event):
if event.key == "Enter":
self.interface.on_confirm()
def dom_sl_change(self, event):
self.interface.on_confirm()

def set_readonly(self, value):
self.native.readOnly = value
Expand Down