bauiv1lib.gather.nearbytab

Defines the nearby tab in the gather UI.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Defines the nearby tab in the gather UI."""
  4
  5from __future__ import annotations
  6
  7import weakref
  8from typing import TYPE_CHECKING, override
  9
 10import bauiv1 as bui
 11import bascenev1 as bs
 12
 13from bauiv1lib.gather import GatherTab
 14
 15if TYPE_CHECKING:
 16    from typing import Any
 17
 18    from bauiv1lib.gather import GatherWindow
 19
 20
 21class NetScanner:
 22    """Class for scanning for nearby games (lan, bluetooth, etc)."""
 23
 24    def __init__(
 25        self,
 26        tab: GatherTab,
 27        scrollwidget: bui.Widget,
 28        tab_button: bui.Widget,
 29        width: float,
 30    ):
 31        self._tab = weakref.ref(tab)
 32        self._scrollwidget = scrollwidget
 33        self._tab_button = tab_button
 34        self._columnwidget = bui.columnwidget(
 35            parent=self._scrollwidget, border=2, margin=0, left_border=10
 36        )
 37        bui.widget(edit=self._columnwidget, up_widget=tab_button)
 38        self._width = width
 39        self._last_selected_host: dict[str, Any] | None = None
 40
 41        self._update_timer = bui.AppTimer(
 42            1.0, bui.WeakCall(self.update), repeat=True
 43        )
 44        # Go ahead and run a few *almost* immediately so we don't
 45        # have to wait a second.
 46        self.update()
 47        bui.apptimer(0.25, bui.WeakCall(self.update))
 48
 49    def __del__(self) -> None:
 50        bs.end_host_scanning()
 51
 52    def _on_select(self, host: dict[str, Any]) -> None:
 53        self._last_selected_host = host
 54
 55    def _on_activate(self, host: dict[str, Any]) -> None:
 56        bs.connect_to_party(host['address'])
 57
 58    def update(self) -> None:
 59        """(internal)"""
 60
 61        # In case our UI was killed from under us.
 62        if not self._columnwidget:
 63            print(
 64                f'ERROR: NetScanner running without UI at time {bui.apptime()}.'
 65            )
 66            return
 67
 68        t_scale = 1.6
 69        for child in self._columnwidget.get_children():
 70            child.delete()
 71
 72        # Grab this now this since adding widgets will change it.
 73        last_selected_host = self._last_selected_host
 74        hosts = bs.host_scan_cycle()
 75        for i, host in enumerate(hosts):
 76            txt3 = bui.textwidget(
 77                parent=self._columnwidget,
 78                size=(self._width / t_scale, 30),
 79                selectable=True,
 80                color=(1, 1, 1),
 81                on_select_call=bui.Call(self._on_select, host),
 82                on_activate_call=bui.Call(self._on_activate, host),
 83                click_activate=True,
 84                text=host['display_string'],
 85                h_align='left',
 86                v_align='center',
 87                corner_scale=t_scale,
 88                maxwidth=(self._width / t_scale) * 0.93,
 89            )
 90            if host == last_selected_host:
 91                bui.containerwidget(
 92                    edit=self._columnwidget,
 93                    selected_child=txt3,
 94                    visible_child=txt3,
 95                )
 96            if i == 0:
 97                bui.widget(edit=txt3, up_widget=self._tab_button)
 98
 99
100class NearbyGatherTab(GatherTab):
101    """The nearby tab in the gather UI"""
102
103    def __init__(self, window: GatherWindow) -> None:
104        super().__init__(window)
105        self._net_scanner: NetScanner | None = None
106        self._container: bui.Widget | None = None
107
108    @override
109    def on_activate(
110        self,
111        parent_widget: bui.Widget,
112        tab_button: bui.Widget,
113        region_width: float,
114        region_height: float,
115        region_left: float,
116        region_bottom: float,
117    ) -> bui.Widget:
118        c_width = region_width
119        c_height = region_height - 20
120        sub_scroll_height = c_height - 85
121        sub_scroll_width = 650
122        self._container = bui.containerwidget(
123            parent=parent_widget,
124            position=(
125                region_left,
126                region_bottom + (region_height - c_height) * 0.5,
127            ),
128            size=(c_width, c_height),
129            background=False,
130            selection_loops_to_parent=True,
131        )
132        v = c_height - 30
133        bui.textwidget(
134            parent=self._container,
135            position=(c_width * 0.5, v - 3),
136            color=(0.6, 1.0, 0.6),
137            scale=1.3,
138            size=(0, 0),
139            maxwidth=c_width * 0.9,
140            h_align='center',
141            v_align='center',
142            text=bui.Lstr(
143                resource='gatherWindow.' 'localNetworkDescriptionText'
144            ),
145        )
146        v -= 15
147        v -= sub_scroll_height + 23
148        scrollw = bui.scrollwidget(
149            parent=self._container,
150            position=((region_width - sub_scroll_width) * 0.5, v),
151            size=(sub_scroll_width, sub_scroll_height),
152        )
153
154        self._net_scanner = NetScanner(
155            self, scrollw, tab_button, width=sub_scroll_width
156        )
157
158        bui.widget(edit=scrollw, autoselect=True, up_widget=tab_button)
159        return self._container
160
161    @override
162    def on_deactivate(self) -> None:
163        self._net_scanner = None
class NetScanner:
22class NetScanner:
23    """Class for scanning for nearby games (lan, bluetooth, etc)."""
24
25    def __init__(
26        self,
27        tab: GatherTab,
28        scrollwidget: bui.Widget,
29        tab_button: bui.Widget,
30        width: float,
31    ):
32        self._tab = weakref.ref(tab)
33        self._scrollwidget = scrollwidget
34        self._tab_button = tab_button
35        self._columnwidget = bui.columnwidget(
36            parent=self._scrollwidget, border=2, margin=0, left_border=10
37        )
38        bui.widget(edit=self._columnwidget, up_widget=tab_button)
39        self._width = width
40        self._last_selected_host: dict[str, Any] | None = None
41
42        self._update_timer = bui.AppTimer(
43            1.0, bui.WeakCall(self.update), repeat=True
44        )
45        # Go ahead and run a few *almost* immediately so we don't
46        # have to wait a second.
47        self.update()
48        bui.apptimer(0.25, bui.WeakCall(self.update))
49
50    def __del__(self) -> None:
51        bs.end_host_scanning()
52
53    def _on_select(self, host: dict[str, Any]) -> None:
54        self._last_selected_host = host
55
56    def _on_activate(self, host: dict[str, Any]) -> None:
57        bs.connect_to_party(host['address'])
58
59    def update(self) -> None:
60        """(internal)"""
61
62        # In case our UI was killed from under us.
63        if not self._columnwidget:
64            print(
65                f'ERROR: NetScanner running without UI at time {bui.apptime()}.'
66            )
67            return
68
69        t_scale = 1.6
70        for child in self._columnwidget.get_children():
71            child.delete()
72
73        # Grab this now this since adding widgets will change it.
74        last_selected_host = self._last_selected_host
75        hosts = bs.host_scan_cycle()
76        for i, host in enumerate(hosts):
77            txt3 = bui.textwidget(
78                parent=self._columnwidget,
79                size=(self._width / t_scale, 30),
80                selectable=True,
81                color=(1, 1, 1),
82                on_select_call=bui.Call(self._on_select, host),
83                on_activate_call=bui.Call(self._on_activate, host),
84                click_activate=True,
85                text=host['display_string'],
86                h_align='left',
87                v_align='center',
88                corner_scale=t_scale,
89                maxwidth=(self._width / t_scale) * 0.93,
90            )
91            if host == last_selected_host:
92                bui.containerwidget(
93                    edit=self._columnwidget,
94                    selected_child=txt3,
95                    visible_child=txt3,
96                )
97            if i == 0:
98                bui.widget(edit=txt3, up_widget=self._tab_button)

Class for scanning for nearby games (lan, bluetooth, etc).

NetScanner( tab: bauiv1lib.gather.GatherTab, scrollwidget: _bauiv1.Widget, tab_button: _bauiv1.Widget, width: float)
25    def __init__(
26        self,
27        tab: GatherTab,
28        scrollwidget: bui.Widget,
29        tab_button: bui.Widget,
30        width: float,
31    ):
32        self._tab = weakref.ref(tab)
33        self._scrollwidget = scrollwidget
34        self._tab_button = tab_button
35        self._columnwidget = bui.columnwidget(
36            parent=self._scrollwidget, border=2, margin=0, left_border=10
37        )
38        bui.widget(edit=self._columnwidget, up_widget=tab_button)
39        self._width = width
40        self._last_selected_host: dict[str, Any] | None = None
41
42        self._update_timer = bui.AppTimer(
43            1.0, bui.WeakCall(self.update), repeat=True
44        )
45        # Go ahead and run a few *almost* immediately so we don't
46        # have to wait a second.
47        self.update()
48        bui.apptimer(0.25, bui.WeakCall(self.update))
class NearbyGatherTab(bauiv1lib.gather.GatherTab):
101class NearbyGatherTab(GatherTab):
102    """The nearby tab in the gather UI"""
103
104    def __init__(self, window: GatherWindow) -> None:
105        super().__init__(window)
106        self._net_scanner: NetScanner | None = None
107        self._container: bui.Widget | None = None
108
109    @override
110    def on_activate(
111        self,
112        parent_widget: bui.Widget,
113        tab_button: bui.Widget,
114        region_width: float,
115        region_height: float,
116        region_left: float,
117        region_bottom: float,
118    ) -> bui.Widget:
119        c_width = region_width
120        c_height = region_height - 20
121        sub_scroll_height = c_height - 85
122        sub_scroll_width = 650
123        self._container = bui.containerwidget(
124            parent=parent_widget,
125            position=(
126                region_left,
127                region_bottom + (region_height - c_height) * 0.5,
128            ),
129            size=(c_width, c_height),
130            background=False,
131            selection_loops_to_parent=True,
132        )
133        v = c_height - 30
134        bui.textwidget(
135            parent=self._container,
136            position=(c_width * 0.5, v - 3),
137            color=(0.6, 1.0, 0.6),
138            scale=1.3,
139            size=(0, 0),
140            maxwidth=c_width * 0.9,
141            h_align='center',
142            v_align='center',
143            text=bui.Lstr(
144                resource='gatherWindow.' 'localNetworkDescriptionText'
145            ),
146        )
147        v -= 15
148        v -= sub_scroll_height + 23
149        scrollw = bui.scrollwidget(
150            parent=self._container,
151            position=((region_width - sub_scroll_width) * 0.5, v),
152            size=(sub_scroll_width, sub_scroll_height),
153        )
154
155        self._net_scanner = NetScanner(
156            self, scrollw, tab_button, width=sub_scroll_width
157        )
158
159        bui.widget(edit=scrollw, autoselect=True, up_widget=tab_button)
160        return self._container
161
162    @override
163    def on_deactivate(self) -> None:
164        self._net_scanner = None

The nearby tab in the gather UI

NearbyGatherTab(window: bauiv1lib.gather.GatherWindow)
104    def __init__(self, window: GatherWindow) -> None:
105        super().__init__(window)
106        self._net_scanner: NetScanner | None = None
107        self._container: bui.Widget | None = None
@override
def on_activate( self, parent_widget: _bauiv1.Widget, tab_button: _bauiv1.Widget, region_width: float, region_height: float, region_left: float, region_bottom: float) -> _bauiv1.Widget:
109    @override
110    def on_activate(
111        self,
112        parent_widget: bui.Widget,
113        tab_button: bui.Widget,
114        region_width: float,
115        region_height: float,
116        region_left: float,
117        region_bottom: float,
118    ) -> bui.Widget:
119        c_width = region_width
120        c_height = region_height - 20
121        sub_scroll_height = c_height - 85
122        sub_scroll_width = 650
123        self._container = bui.containerwidget(
124            parent=parent_widget,
125            position=(
126                region_left,
127                region_bottom + (region_height - c_height) * 0.5,
128            ),
129            size=(c_width, c_height),
130            background=False,
131            selection_loops_to_parent=True,
132        )
133        v = c_height - 30
134        bui.textwidget(
135            parent=self._container,
136            position=(c_width * 0.5, v - 3),
137            color=(0.6, 1.0, 0.6),
138            scale=1.3,
139            size=(0, 0),
140            maxwidth=c_width * 0.9,
141            h_align='center',
142            v_align='center',
143            text=bui.Lstr(
144                resource='gatherWindow.' 'localNetworkDescriptionText'
145            ),
146        )
147        v -= 15
148        v -= sub_scroll_height + 23
149        scrollw = bui.scrollwidget(
150            parent=self._container,
151            position=((region_width - sub_scroll_width) * 0.5, v),
152            size=(sub_scroll_width, sub_scroll_height),
153        )
154
155        self._net_scanner = NetScanner(
156            self, scrollw, tab_button, width=sub_scroll_width
157        )
158
159        bui.widget(edit=scrollw, autoselect=True, up_widget=tab_button)
160        return self._container

Called when the tab becomes the active one.

The tab should create and return a container widget covering the specified region.

@override
def on_deactivate(self) -> None:
162    @override
163    def on_deactivate(self) -> None:
164        self._net_scanner = None

Called when the tab will no longer be the active one.