class TextBox(FocusableWidget): """ Represents a text entry control with associated label. """ label_text = None text = '' text_width = 100 max_length = None allow_alpha = True allow_numeric = True allow_space = True allow_negative = True allow_decimal = True def __init__(self, display, page, label=None, text=None, text_width=100): super(TextBox, self).__init__(display, page) if text: text = str(text) self.text = text self.label_text = label self.label = TextBlock(display, page, label) self.glyph = TextGlyph(display, page) self.text_width = text_width self.panel = StackPanel(display, page, is_horizontal=True) self.panel.center_align = True self.panel.children = [self.label, self.glyph] def arrange(self): # Pass along our values to the children self.label.text = self.label_text self.glyph.text_width = self.text_width self.glyph.text = self.text self.desired_size = self.panel.arrange() return super(TextBox, self).arrange() def render(self): """ Renders the TextBox with its current state :return: The rectangle of the TextBox """ # Render the panel's contents self.panel.set_dimensions_from(self) self.panel.render() return self.set_dimensions_from(self.panel) def set_alphanumeric(self): self.allow_alpha = True self.allow_negative = True self.allow_numeric = True self.allow_decimal = True self.allow_space = True def set_numeric(self, allow_negative=True, allow_decimal=True): self.allow_alpha = False self.allow_negative = allow_negative self.allow_decimal = allow_decimal self.allow_numeric = True self.allow_space = False def got_focus(self): """ Occurs when the control gets focus """ self.label.is_highlighted = True self.glyph.render_focus = True super(TextBox, self).got_focus() def lost_focus(self): """ Occurs when the control loses focus """ self.label.is_highlighted = False self.glyph.render_focus = False super(TextBox, self).lost_focus() def can_input_more(self): """ Returns whether or not there is room to enter more characters (according to max_length) :return: whether or not there is room to enter more characters (according to max_length) """ return self.max_length is None or len(self.text) < self.max_length def handle_key(self, key): """ Handles a keypress :param key: The keycode :returns: True if the event was handled; otherwise False """ # ensure we have text in the textbox if not self.text: self.text = '' if key == Keycodes.KEY_BACKSPACE: if self.text and len(self.text) > 0: self.text = self.text[:-1] # TODO: This is simplistic and needs to work with a cursor index return True if key == Keycodes.KEY_DELETE: if self.text and len(self.text) > 0: self.text = self.text[1:] # TODO: This is simplistic and needs to work with a cursor index return True if self.allow_numeric and Keycodes.KEY_0 <= key <= Keycodes.KEY_9 and self.can_input_more(): char = key - Keycodes.KEY_0 self.text += str(char) # TODO: This will need to take cursor location into account self.state_changed() return True if self.allow_alpha and Keycodes.KEY_a <= key <= Keycodes.KEY_z and self.can_input_more(): char = chr(key) self.text += str(char).upper() # TODO: This will need to take cursor location into account self.state_changed() return True if self.allow_negative and key in [Keycodes.KEY_KP_MINUS, Keycodes.KEY_MINUS]: self.text += '-' self.state_changed() return True if self.allow_decimal and key in [Keycodes.KEY_KP_PERIOD, Keycodes.KEY_PERIOD]: self.text += '.' self.state_changed() return True if self.allow_space and key == Keycodes.KEY_SPACE and self.can_input_more(): self.text += ' ' self.state_changed() return True return super(TextBox, self).handle_key(key) def has_text(self): return self.text and len(self.text) > 0
class CheckBox(FocusableWidget): """ A CheckBox with an associated label. """ text = None panel = None label = None glyph = None checked = False def __init__(self, display, page, label): super(CheckBox, self).__init__(display, page) self.text = label self.label = TextBlock(display, page, label) self.glyph = CheckBoxGlyph(display, page) self.panel = StackPanel(display, page, is_horizontal=True) self.panel.center_align = True self.panel.children = [self.label, self.glyph] def arrange(self): self.desired_size = self.panel.arrange() return super(CheckBox, self).arrange() def render(self): """ Renders the checkbox with its current state :return: The rectangle of the checkbox """ # Pass along our values to the children self.label.text = self.text self.glyph.checked = self.checked # Render the panel's contents self.panel.set_dimensions_from(self) self.panel.render() return self.set_dimensions_from(self.panel) def got_focus(self): """ Occurs when the control gets focus """ self.label.is_highlighted = True self.glyph.render_focus = True super(CheckBox, self).got_focus() def lost_focus(self): """ Occurs when the control loses focus """ self.label.is_highlighted = False self.glyph.render_focus = False super(CheckBox, self).lost_focus() def handle_key(self, key): """ Handles a keypress :param key: The keycode :returns: True if the event was handled; otherwise False """ if is_enter_key(key) or key == Keycodes.KEY_SPACE: if self.checked: self.checked = False else: self.checked = True self.state_changed() return True else: return super(CheckBox, self).handle_key(key)