improve keyboard & list

pull/34814/head
deanlee 2 months ago committed by Cameron Clough
parent 976b6f3201
commit 99f0c55ef2
  1. 2
      system/ui/lib/wifi_manager.py
  2. 40
      system/ui/widgets/keyboard.py
  3. 27
      system/ui/widgets/network.py

@ -225,7 +225,7 @@ class WifiManager:
# print("property changed", interface, changed, invalidated)
if 'LastScan' in changed:
asyncio.create_task(self._get_available_networks())
elif "ActiveAccessPoint" in changed:
elif interface == NM_WIRELESS_IFACE and "ActiveAccessPoint" in changed:
self.active_ap_path = changed["ActiveAccessPoint"].value
asyncio.create_task(self._get_available_networks())

@ -44,25 +44,30 @@ keyboard_layouts = {
class Keyboard:
def __init__(self, max_text_size: int = 255):
self._layout = keyboard_layouts["lowercase"]
self._input_text = ""
self._max_text_size = max_text_size
self._string_pointer = rl.ffi.new("char[]", max_text_size)
self._input_text: str = ''
self._clear()
@property
def text(self) -> str:
return self._input_text
def clear(self):
self._input_text = ""
result = rl.ffi.string(self._string_pointer).decode('utf-8')
self._clear()
return result
def render(self, rect, title, sub_title):
gui_label(rl.Rectangle(rect.x, rect.y, rect.width, 95), title, 90)
gui_label(rl.Rectangle(rect.x, rect.y + 95, rect.width, 60), sub_title, 55, rl.GRAY)
if gui_button(rl.Rectangle(rect.x + rect.width - 300, rect.y, 300, 100), "Cancel"):
return -1
self._clear()
return 0
# Text box for input
rl.gui_text_box(rl.Rectangle(rect.x, rect.y + 160, rect.width, 100), self._input_text, self._max_text_size, True)
self._sync_string_pointer()
rl.gui_text_box(
rl.Rectangle(rect.x, rect.y + 160, rect.width, 100), self._string_pointer, self._max_text_size, True
)
self._input_text = rl.ffi.string(self._string_pointer).decode('utf-8')
h_space, v_space = 15, 15
row_y_start = rect.y + 300 # Starting Y position for the first row
key_height = (rect.height - 300 - 3 * v_space) / 4
@ -77,7 +82,11 @@ class Keyboard:
if i > 0:
start_x += h_space
new_width = (key_width * 3 + h_space * 2) if key == SPACE_KEY else (key_width * 2 + h_space if key == ENTER_KEY else key_width)
new_width = (
(key_width * 3 + h_space * 2)
if key == SPACE_KEY
else (key_width * 2 + h_space if key == ENTER_KEY else key_width)
)
key_rect = rl.Rectangle(start_x, row_y_start + row * (key_height + v_space), new_width, key_height)
start_x += new_width
@ -87,7 +96,7 @@ class Keyboard:
else:
self.handle_key_press(key)
return 0
return -1
def handle_key_press(self, key):
if key in (SHIFT_DOWN_KEY, ABC_KEY):
@ -102,3 +111,14 @@ class Keyboard:
self._input_text = self._input_text[:-1]
elif key != BACKSPACE_KEY and len(self._input_text) < self._max_text_size:
self._input_text += key
def _clear(self):
self._input_text = ''
self._string_pointer[0] = b'\0'
def _sync_string_pointer(self):
"""Sync the C-string pointer with the internal Python string."""
encoded = self._input_text.encode("utf-8")[:self._max_text_size - 1] # Leave room for null terminator
buffer = rl.ffi.buffer(self._string_pointer)
buffer[:len(encoded)] = encoded
self._string_pointer[len(encoded)] = b'\0' # Null terminate

@ -11,7 +11,7 @@ from openpilot.system.ui.widgets.keyboard import Keyboard
from openpilot.system.ui.widgets.confirm_dialog import confirm_dialog
NM_DEVICE_STATE_NEED_AUTH = 60
ITEM_HEIGHT = 160
class ActionState(IntEnum):
NONE = 0
@ -28,7 +28,6 @@ class WifiManagerUI:
self.wifi_manager = wifi_manager
self.wifi_manager.need_auth_callback = self._need_auth
self._selected_network = None
self.item_height = 160
self.btn_width = 200
self.current_action: ActionState = ActionState.NONE
self.scroll_panel = GuiScrollPanel()
@ -57,28 +56,26 @@ class WifiManagerUI:
if self.current_action == ActionState.NEED_AUTH:
result = self.keyboard.render(rect, 'Enter password', f'for {self._selected_network.ssid}')
if result == 0:
return
elif result == 1:
self.current_action = ActionState.NONE
if result == 1:
asyncio.create_task(self.connect_to_network(self.keyboard.text))
else:
elif result == 0:
self.current_action = ActionState.NONE
return
self._draw_network_list(rect)
def _draw_network_list(self, rect: rl.Rectangle):
content_rect = rl.Rectangle(rect.x, rect.y, rect.width, len(self.wifi_manager.networks) * self.item_height)
content_rect = rl.Rectangle(rect.x, rect.y, rect.width, len(self.wifi_manager.networks) * ITEM_HEIGHT)
offset = self.scroll_panel.handle_scroll(rect, content_rect)
clicked = self.scroll_panel.is_click_valid()
rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height))
for i, network in enumerate(self.wifi_manager.networks):
y_offset = i * self.item_height + offset.y
item_rect = rl.Rectangle(rect.x, y_offset, rect.width, self.item_height)
y_offset = rect.y + i * ITEM_HEIGHT + offset.y
item_rect = rl.Rectangle(rect.x, y_offset, rect.width, ITEM_HEIGHT)
if not rl.check_collision_recs(item_rect, rect):
continue
if rl.check_collision_recs(item_rect, rect):
self._draw_network_item(item_rect, network, clicked)
if i < len(self.wifi_manager.networks) - 1:
line_y = int(item_rect.y + item_rect.height - 1)
@ -87,21 +84,21 @@ class WifiManagerUI:
rl.end_scissor_mode()
def _draw_network_item(self, rect, network: NetworkInfo, clicked: bool):
label_rect = rl.Rectangle(rect.x, rect.y, rect.width - self.btn_width * 2, self.item_height)
state_rect = rl.Rectangle(rect.x + rect.width - self.btn_width * 2 - 150, rect.y, 300, self.item_height)
label_rect = rl.Rectangle(rect.x, rect.y, rect.width - self.btn_width * 2, ITEM_HEIGHT)
state_rect = rl.Rectangle(rect.x + rect.width - self.btn_width * 2 - 150, rect.y, 300, ITEM_HEIGHT)
gui_label(label_rect, network.ssid, 55)
if network.is_connected and self.current_action == ActionState.NONE:
rl.gui_label(state_rect, "Connected")
elif self.current_action == "Connecting" and self._selected_network and self._selected_network.ssid == network.ssid:
elif self.current_action == ActionState.CONNECTING and self._selected_network and self._selected_network.ssid == network.ssid:
rl.gui_label(state_rect, "CONNECTING...")
# If the network is saved, show the "Forget" button
if self.wifi_manager.is_saved(network.ssid):
forget_btn_rect = rl.Rectangle(
rect.x + rect.width - self.btn_width,
rect.y + (self.item_height - 80) / 2,
rect.y + (ITEM_HEIGHT - 80) / 2,
self.btn_width,
80,
)

Loading…
Cancel
Save