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

Class for scanning for games on the lan.

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

The nearby tab in the gather UI

NearbyGatherTab(window: bastd.ui.gather.GatherWindow)
95    def __init__(self, window: GatherWindow) -> None:
96        super().__init__(window)
97        self._net_scanner: NetScanner | None = None
98        self._container: ba.Widget | None = None
def on_activate( self, parent_widget: _ba.Widget, tab_button: _ba.Widget, region_width: float, region_height: float, region_left: float, region_bottom: float) -> _ba.Widget:
100    def on_activate(
101        self,
102        parent_widget: ba.Widget,
103        tab_button: ba.Widget,
104        region_width: float,
105        region_height: float,
106        region_left: float,
107        region_bottom: float,
108    ) -> ba.Widget:
109        c_width = region_width
110        c_height = region_height - 20
111        sub_scroll_height = c_height - 85
112        sub_scroll_width = 650
113        self._container = ba.containerwidget(
114            parent=parent_widget,
115            position=(region_left,
116                      region_bottom + (region_height - c_height) * 0.5),
117            size=(c_width, c_height),
118            background=False,
119            selection_loops_to_parent=True)
120        v = c_height - 30
121        ba.textwidget(parent=self._container,
122                      position=(c_width * 0.5, v - 3),
123                      color=(0.6, 1.0, 0.6),
124                      scale=1.3,
125                      size=(0, 0),
126                      maxwidth=c_width * 0.9,
127                      h_align='center',
128                      v_align='center',
129                      text=ba.Lstr(resource='gatherWindow.'
130                                   'localNetworkDescriptionText'))
131        v -= 15
132        v -= sub_scroll_height + 23
133        scrollw = ba.scrollwidget(parent=self._container,
134                                  position=((region_width - sub_scroll_width) *
135                                            0.5, v),
136                                  size=(sub_scroll_width, sub_scroll_height))
137
138        self._net_scanner = NetScanner(self,
139                                       scrollw,
140                                       tab_button,
141                                       width=sub_scroll_width)
142
143        ba.widget(edit=scrollw, autoselect=True, up_widget=tab_button)
144        return self._container

Called when the tab becomes the active one.

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

def on_deactivate(self) -> None:
146    def on_deactivate(self) -> None:
147        self._net_scanner = None

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