class TextBox(Focusable, Caret, Hoverable): underline: Rectangle = None _on_enter: Callable = None ignore_enter: bool = False style: dict = {} def __init__(self, width: int, height: int = 0, multiline: bool = False, dpi: object = None, batch: Batch = None, group: Group = None, wrap_lines: bool = True, x: int = 0, y: int = 0, underlined: bool = True, caret_color: tuple = (0, 0, 0), numbers_only: bool = False, font_name=None, font_size=None, font_color=(255, 255, 255, 2555), max_chars=0) -> None: self.document = FormattedDocument() self.layout = IncrementalTextLayout(self.document, width, height, multiline, dpi, batch, group, wrap_lines) self.numbers_only = numbers_only self.style['color'] = font_color self.max_chars = max_chars if font_name: self.style['font_name'] = font_name if font_size: self.style['font_size'] = font_size self.reset_style() if not height: # If the dev didn't specify a height, make the height equal to the height of the font font = pyglet.font.load( font_name or self.document.get_style('font'), font_size or self.document.get_style('font_size')) self.height = font.ascent - font.descent self._hover_cursor = self.get_window().CURSOR_TEXT super().__init__(self.layout, color=caret_color) # TODO: Allow the dev to specify how x and y are treated self.x = x - self.width // 2 self.y = y - self.height // 2 if underlined: self.underline = Rectangle( x=self.x, y=self.y, width=self.width, height=1, ) def reset_style(self): self.document.set_style(0, len(self.document.text), self.style) @property def x(self): return self.layout.x @x.setter def x(self, value): if self.underline: self.underline.x = value self.layout.x = value @property def y(self): return self.layout.y @y.setter def y(self, value): print(value) if self.underline: self.underline.y = value self.layout.y = value @property def width(self): return self.layout.width @width.setter def width(self, value): if self.underline: self.underline.width = value self.layout.width = value @property def height(self): return self.layout.height @height.setter def height(self, value): print(value) self.layout.height = value def draw(self): if self.focused: self.on_activate() else: self.on_deactivate() self.layout.draw() if self.underline: self.underline.draw() def on_text(self, text: str): # Only type inside when the user is focused on the textbox # print(text) if not self.focused: return if ord(text) == 13: if self.ignore_enter: # Enter self.ignore_enter = False return else: return self.on_enter() # if self.max_chars and len(self.value) >= self.max_chars: # return # if self.numbers_only and not text.isnumeric(): # return res = super().on_text(text) print('res', res, 'text', text) self.reset_style() return res def _on_enter_base(self) -> None: """ The event handler that will be called by default if none are defined """ pass @property def value(self): return self.document.text @value.setter def value(self, val): self.document.text = val self.reset_style() @property def on_enter(self): if self._on_enter: return self._on_enter return self._on_enter_base @on_enter.setter def on_enter(self, func): def new_on_enter(): if self.focused: func() self._on_enter = new_on_enter
class LicensePageV2(UIObject, ABC): def __init__(self, logger, parent_viewport): super().__init__(logger, parent_viewport) self.license_text = '' self.document = None self.license_layout = None @final def on_activate(self): super().on_activate() if not self.document: self.document = FormattedDocument(text=self.license_text) self.document.set_style( 0, len(self.document.text), { 'font_name': 'Arial', 'font_size': get_bottom_bar_height(self.screen_resolution) // 5, 'bold': False, 'italic': False, 'color': (*WHITE_RGB, self.opacity), 'align': 'center' }) if not self.license_layout: self.license_layout = IncrementalTextLayout( document=self.document, width=self.viewport.x2 - self.viewport.x1, height=self.viewport.y2 - self.viewport.y1, multiline=True, batch=BATCHES['ui_batch'], group=GROUPS['button_text']) self.license_layout.x, self.license_layout.y = self.viewport.x1, self.viewport.y1 @final @window_size_has_changed def on_window_resize(self, width, height): super().on_window_resize(width, height) self.viewport.x1, self.viewport.x2 = self.parent_viewport.x1, self.parent_viewport.x2 self.viewport.y1 = self.parent_viewport.y1 + get_bottom_bar_height( self.screen_resolution) self.viewport.y2 = self.parent_viewport.y2 if self.is_activated: self.license_layout.x, self.license_layout.y = self.viewport.x1, self.viewport.y1 self.license_layout.width = self.viewport.x2 - self.viewport.x1 self.license_layout.height = self.viewport.y2 - self.viewport.y1 self.document.set_style(0, len(self.document.text), { 'font_size': get_bottom_bar_height(self.screen_resolution) // 5 }) @final @is_active @cursor_is_inside_the_text_box def on_mouse_scroll(self, x, y, scroll_x, scroll_y): self.license_layout.view_y += scroll_y * self.document.get_style( 'font_size') @final def on_update_opacity(self, new_opacity): super().on_update_opacity(new_opacity) if self.opacity <= 0: self.license_layout.delete() self.license_layout = None elif self.document: self.document.set_style(0, len(self.document.text), {'color': (*WHITE_RGB, self.opacity)})