97 lines
3.2 KiB
Python
97 lines
3.2 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
"""This module defines a checkbox widget"""
|
||
|
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.widgets.widget import Widget
|
||
|
|
||
|
|
||
|
class CheckBox(Widget):
|
||
|
"""
|
||
|
A CheckBox widget is used to ask for Boolean (i.e. yes/no) input.
|
||
|
|
||
|
It consists of an optional label (typically used for the first in a group of CheckBoxes),
|
||
|
the box and a field name.
|
||
|
"""
|
||
|
|
||
|
__slots__ = ["_text", "_label", "_on_change"]
|
||
|
|
||
|
def __init__(self, text, label=None, name=None, on_change=None, **kwargs):
|
||
|
"""
|
||
|
:param text: The text to explain this specific field to the user.
|
||
|
: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(CheckBox, self).__init__(name, **kwargs)
|
||
|
self._text = text
|
||
|
self._label = label
|
||
|
self._on_change = on_change
|
||
|
|
||
|
def update(self, frame_no):
|
||
|
self._draw_label()
|
||
|
|
||
|
# Render this checkbox.
|
||
|
check_char = u"✓" if self._frame.canvas.unicode_aware else "X"
|
||
|
(colour, attr, bg) = self._pick_colours("control", self._has_focus)
|
||
|
self._frame.canvas.print_at(
|
||
|
"[{}] ".format(check_char if self._value else " "),
|
||
|
self._x + self._offset,
|
||
|
self._y,
|
||
|
colour, attr, bg)
|
||
|
(colour, attr, bg) = self._pick_colours("field", self._has_focus)
|
||
|
self._frame.canvas.print_at(
|
||
|
self._text,
|
||
|
self._x + self._offset + 4,
|
||
|
self._y,
|
||
|
colour, attr, bg)
|
||
|
|
||
|
def reset(self):
|
||
|
pass
|
||
|
|
||
|
def process_event(self, event):
|
||
|
if isinstance(event, KeyboardEvent):
|
||
|
if event.key_code in [ord(" "), 10, 13]:
|
||
|
# Use property to trigger events.
|
||
|
self.value = not self._value
|
||
|
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.value = not self._value
|
||
|
return None
|
||
|
# Ignore other mouse events.
|
||
|
return event
|
||
|
else:
|
||
|
# Ignore other events
|
||
|
return event
|
||
|
|
||
|
# If we got here, we processed the event - swallow it.
|
||
|
return None
|
||
|
|
||
|
def required_height(self, offset, width):
|
||
|
return 1
|
||
|
|
||
|
@property
|
||
|
def value(self):
|
||
|
"""
|
||
|
The current value for this Checkbox.
|
||
|
"""
|
||
|
return self._value
|
||
|
|
||
|
@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 if new_value else False
|
||
|
if old_value != self._value and self._on_change:
|
||
|
self._on_change()
|