Shofel2_T124_python/venv/lib/python3.10/site-packages/asciimatics/widgets/radiobuttons.py

118 lines
4.3 KiB
Python
Raw Normal View History

2024-05-25 16:45:07 +00:00
# -*- coding: utf-8 -*-
"""This module implements the widget for radio buttons"""
from __future__ import division
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
from asciimatics.event import KeyboardEvent, MouseEvent
from asciimatics.screen import Screen
from asciimatics.widgets.widget import Widget
class RadioButtons(Widget):
"""
A RadioButtons widget is used to ask for one of a list of values to be selected by the user.
It consists of an optional label and then a list of selection bullets with field names.
"""
__slots__ = ["_options", "_label", "_selection", "_start_column", "_on_change"]
def __init__(self, options, label=None, name=None, on_change=None, **kwargs):
"""
:param options: A list of (text, value) tuples for each radio button.
:param label: An optional label for the widget.
:param name: The internal name for the widget.
:param on_change: Optional function to call when text changes.
Also see the common keyword arguments in :py:obj:`.Widget`.
"""
super(RadioButtons, self).__init__(name, **kwargs)
self._options = options
self._label = label
self._selection = 0
self._start_column = 0
self._on_change = on_change
def update(self, frame_no):
self._draw_label()
# Decide on check char
check_char = u"" if self._frame.canvas.unicode_aware else "X"
# Render the list of radio buttons.
for i, (text, _) in enumerate(self._options):
fg, attr, bg = self._pick_colours("control", self._has_focus and i == self._selection)
fg2, attr2, bg2 = self._pick_colours("field", self._has_focus and i == self._selection)
check = check_char if i == self._selection else " "
self._frame.canvas.print_at(
"({}) ".format(check),
self._x + self._offset,
self._y + i,
fg, attr, bg)
self._frame.canvas.print_at(
text,
self._x + self._offset + 4,
self._y + i,
fg2, attr2, bg2)
def reset(self):
pass
def process_event(self, event):
if isinstance(event, KeyboardEvent):
if event.key_code == Screen.KEY_UP:
# Use property to trigger events.
self._selection = max(0, self._selection - 1)
self.value = self._options[self._selection][1]
elif event.key_code == Screen.KEY_DOWN:
# Use property to trigger events.
self._selection = min(self._selection + 1,
len(self._options) - 1)
self.value = self._options[self._selection][1]
else:
# Ignore any other key press.
return event
elif isinstance(event, MouseEvent):
# Mouse event - rebase coordinates to Frame context.
if event.buttons != 0:
if self.is_mouse_over(event, include_label=False):
# Use property to trigger events.
self._selection = event.y - self._y
self.value = self._options[self._selection][1]
return None
# Ignore other mouse events.
return event
else:
# Ignore non-keyboard events
return event
# If we got here, we processed the event - swallow it.
return None
def required_height(self, offset, width):
return len(self._options)
@property
def value(self):
"""
The current value for these RadioButtons.
"""
# The value is actually the value of the current selection.
return self._options[self._selection][1]
@value.setter
def value(self, new_value):
# Only trigger the notification after we've changed the value.
old_value = self._value
self._value = new_value
for i, (_, value) in enumerate(self._options):
if new_value == value:
self._selection = i
break
else:
self._selection = 0
self._value = new_value if new_value else None
if old_value != self._value and self._on_change:
self._on_change()