Example #1
0
    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
Example #2
0
 def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0,0), wrap=True, id=None, **kwargs):
     """ An editable text box.
         When clicked, it has the focus and can receive keyboard events.
         With wrap=True, several lines of text will wrap around the width.
         Optional parameters can include fill, font, fontsize, fontweight.
     """
     txt = Text(value or " ", **{
            "fill" : _popdefault(kwargs, "fill", Color(0,0.9)),
            "font" : _popdefault(kwargs, "font", theme["fontname"]),
        "fontsize" : _popdefault(kwargs, "fontsize", theme["fontsize"]),
      "fontweight" : _popdefault(kwargs, "fontweight", theme["fontweight"]),
      "lineheight" : _popdefault(kwargs, "lineheight", 1),
           "align" : LEFT
     })
     kwargs["width"]  = width
     kwargs["height"] = height
     Control.__init__(self, x=x, y=y, id=id, **kwargs)
     self.reserved = kwargs.get("reserved", [ENTER, TAB])
     self._padding = padding
     self._i       = 0     # Index of character on which the mouse is pressed.
     self._empty   = value == "" and True or False
     self._editor  = IncrementalTextLayout(txt._label.document, width, height, multiline=wrap)
     self._editor.content_valign = wrap and "top" or "center"
     self._editor.selection_background_color = (170, 200, 230, 255)
     self._editor.selection_color = txt._label.color
     self._editor.caret = Caret(self._editor)
     self._editor.caret.visible = False
     self._editing = False # When True, cursor is blinking and text can be edited.
     Editable._pack(self)  # On init, call Editable._pack(), not the derived Field._pack().
Example #3
0
 def __init__(self):
     win_width, win_height = get_size()
     self.batch = Batch()
     self._doc = pyglet.text.document.UnformattedDocument('')
     self._doc.set_style(0, len(self._doc.text),
                         dict(color=(255, 255, 255, 255)))
     font = self._doc.get_font()
     self.text_height = font.ascent - font.descent
     self.pad = 2
     self._outline = Rectangle(5,
                               5 + self.pad,
                               get_size()[0] - self.pad - 10,
                               self.text_height + self.pad,
                               color=(0, 0, 0))
     self._outline.opacity = 150
     self._layout = IncrementalTextLayout(self._doc,
                                          get_size()[0] - 14,
                                          self.text_height,
                                          multiline=False,
                                          batch=self.batch)
     self._caret = Caret(self._layout, color=(255, 255, 255))
     self._caret.visible = False
     self._layout.x = 5
     self._layout.y = 5 + self.pad
     self._focus = False
     self._press = False
     self.last_press = [0, 0]
     super().__init__(5, 5 + self.pad,
                      get_size()[0] - self.pad - 10,
                      self.text_height + self.pad)
Example #4
0
 def __init__(self, text, color, x, y, width, pad=3):
     win_width, win_height = get_size()
     self.batch = Batch()
     self._doc = pyglet.text.document.UnformattedDocument(text)
     self._doc.set_style(0, len(self._doc.text),
                         dict(color=(255, 255, 255, 255)))
     font = self._doc.get_font()
     self.text_height = font.ascent - font.descent
     self.pad = pad
     self._outline = BorderedRectangle(x - self.pad,
                                       win_height - y - self.pad,
                                       width + self.pad,
                                       self.text_height + self.pad,
                                       color=color[:3],
                                       border_color=(100, 100, 100))
     self._outline.opacity = color[-1]
     self._layout = IncrementalTextLayout(width,
                                          self.text_height,
                                          multiline=False,
                                          batch=self.batch)
     self._caret = Caret(self._layout, color=(255, 255, 255))
     self._caret.visible = False
     self._layout.x = x
     self._layout.y = win_height - y
     self._focus = False
     self._press = False
     super().__init__(x, win_height - y, width, height)
Example #5
0
 def init_bar(self, weapons):
     try:
         if self.ammolayout._document:
             self.ammolayout.delete()
             for tri in self.tris:
                 tri.remove()
     except AttributeError:
         pass
     ammotext = '\t'.join(str(w.ammo) for key, w in weapons.iteritems()
                          if key != 'w0')
     self.ammos = ammotext.split('\t')
     self.ammodoc = FormattedDocument(ammotext)
     self.ammodoc.set_style(0, len(ammotext), dict(color=[255]*4,
                            tab_stops=[120*(i+1) for i in range(6)],
                            font_size=24, align='center', wrap=False))
     self.ammolayout = IncrementalTextLayout(self.ammodoc, width=600,
                                             height=50, batch=self.batch,
                                             multiline=True)
     self.ammolayout.x = (1280 / 2) * self.scale.x
     self.ammolayout.y = 20 * self.scale.y
     self.ammolayout.anchor_x = 'center'
     self.ammolayout.anchor_y = 'bottom'
     w = self.ammolayout.content_width
     colorlist = [weaponcolors[key] for key in weapons if key != 'w0']
     self.tris = [Triangle(640*self.scale.x-w/2-52+120*i, 35*self.scale.y,
                  50, 50, col, self.batch, 0, 0)
                  for i, col in enumerate(colorlist)]
Example #6
0
 def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0, 0), wrap=True, id=None, **kwargs):
     """ An editable text box.
         When clicked, it has the focus and can receive keyboard events.
         With wrap=True, several lines of text will wrap around the width.
         Optional parameters can include fill, font, fontsize, fontweight.
     """
     txt = Text(
         value or " ",
         **{
             "fill": _popdefault(kwargs, "fill", Color(0, 0.9)),
             "font": _popdefault(kwargs, "font", theme["fontname"]),
             "fontsize": _popdefault(kwargs, "fontsize", theme["fontsize"]),
             "fontweight": _popdefault(kwargs, "fontweight", theme["fontweight"]),
             "lineheight": _popdefault(kwargs, "lineheight", 1),
             "align": LEFT,
         }
     )
     kwargs["width"] = width
     kwargs["height"] = height
     Control.__init__(self, x=x, y=y, id=id, **kwargs)
     self.reserved = kwargs.get("reserved", [ENTER, TAB])
     self._padding = padding
     self._i = 0  # Index of character on which the mouse is pressed.
     self._empty = value == "" and True or False
     self._editor = IncrementalTextLayout(txt._label.document, width, height, multiline=wrap)
     self._editor.content_valign = wrap and "top" or "center"
     self._editor.selection_background_color = (170, 200, 230, 255)
     self._editor.selection_color = txt._label.color
     self._editor.caret = Caret(self._editor)
     self._editor.caret.visible = False
     self._editing = False  # When True, cursor is blinking and text can be edited.
     Editable._pack(self)  # On init, call Editable._pack(), not the derived Field._pack().
Example #7
0
 def __init__(self, text, color, x, y, width):
     win_width, win_height = get_size()
     self.batch = Batch()
     self._doc = pyglet.text.document.UnformattedDocument(text)
     self._doc.set_style(
         0, len(self._doc.text),
         dict(color=(255, 255, 255, 255), font_name='minecraftia'))
     font = self._doc.get_font()
     height = font.ascent - font.descent
     pad = 2
     self._outline = Rectangle(x - pad,
                               y - pad,
                               width + pad,
                               height + pad,
                               color=color[:3])
     self._outline.opacity = color[-1]
     self._layout = IncrementalTextLayout(self._doc,
                                          width,
                                          height,
                                          multiline=False,
                                          batch=self.batch)
     self._caret = Caret(self._layout, color=(255, 255, 255))
     self._caret.visible = False
     self._layout.x = x
     self._layout.y = y
     self._focus = False
     self._press = False
     super().__init__(x, y, width, height)
     self.last_char = ''
Example #8
0
 def __init__(self, batch, groups, on_click, on_enter, on_motion,
              on_search):
     # create document
     self.document = FormattedDocument(' ')
     self.document.set_style(
         0, 1,
         dict(font_name=FONT_NAME, font_size=FONT_SIZE, color=FONT_COLOR))
     # calculate font height and margin
     font = self.document.get_font(0)
     self.font_height = font.ascent - font.descent
     self.margin = self.font_height * TEXT_INPUT_MARGIN
     # create text input
     self.input = IncrementalTextLayout(self.document,
                                        100,
                                        self.font_height,
                                        batch=batch,
                                        group=groups[1])
     self.input.x = 100
     self.input.y = 100
     # creating a caret and push it to window handlers
     self.caret = Caret(self.input, FONT_COLOR[:3], on_click, on_enter,
                        on_motion, on_search)
     self.clear_text()
     # create background rectangle
     self.rect = Rectangle(0,
                           0,
                           100,
                           self.font_height + 2 * self.margin,
                           color=TEXT_INPUT_COLOR,
                           batch=batch,
                           group=groups[0])
Example #9
0
 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,
         )
Example #10
0
    def __init__(self, *args, **kwargs):
        super(TestWindow, self).__init__(*args, **kwargs)

        self.batch = pyglet.graphics.Batch()
        self.document = pyglet.text.decode_attributed(doctext)
        for i in range(0, len(doctext), 300):
            self.document.insert_element(i, TestElement(60, -10, 70))
        self.margin = 2
        self.layout = IncrementalTextLayout(self.document,
                                            self.width - self.margin * 2,
                                            self.height - self.margin * 2,
                                            multiline=True,
                                            batch=self.batch)
        self.caret = caret.Caret(self.layout)
        self.push_handlers(self.caret)

        self.set_mouse_cursor(self.get_system_mouse_cursor('text'))
Example #11
0
class TestWindow(pyglet.window.Window):
    def __init__(self, *args, **kwargs):
        super(TestWindow, self).__init__(*args, **kwargs)

        self.batch = pyglet.graphics.Batch()
        self.document = pyglet.text.decode_attributed(doctext)
        for i in range(0, len(doctext), 300):
            self.document.insert_element(i, TestElement(60, -10, 70))
        self.margin = 2
        self.layout = IncrementalTextLayout(self.document,
                                            self.width - self.margin * 2,
                                            self.height - self.margin * 2,
                                            multiline=True,
                                            batch=self.batch)
        self.caret = caret.Caret(self.layout)
        self.push_handlers(self.caret)

        self.set_mouse_cursor(self.get_system_mouse_cursor('text'))

    def on_resize(self, width, height):
        super(TestWindow, self).on_resize(width, height)
        self.layout.begin_update()
        self.layout.x = self.margin
        self.layout.y = self.margin
        self.layout.width = width - self.margin * 2
        self.layout.height = height - self.margin * 2
        self.layout.end_update()

    def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
        self.layout.view_x -= scroll_x
        self.layout.view_y += scroll_y * 16

    def on_draw(self):
        pyglet.gl.glClearColor(0, 0, 0, 1)
        self.clear()
        self.batch.draw()

    def on_key_press(self, symbol, modifiers):
        super(TestWindow, self).on_key_press(symbol, modifiers)
        if symbol == pyglet.window.key.TAB:
            self.caret.on_text('\t')
Example #12
0
    def __init__(self,
                 text,
                 x,
                 y,
                 width,
                 color=(255, 255, 255, 255),
                 batch=None,
                 group=None):
        self._doc = pyglet.text.document.UnformattedDocument(text)
        self._doc.set_style(0, len(self._doc.text), dict(color=(0, 0, 0, 255)))
        font = self._doc.get_font()
        height = font.ascent - font.descent

        self._user_group = group
        bg_group = OrderedGroup(0, parent=group)
        fg_group = OrderedGroup(1, parent=group)

        # Rectangular outline:
        pad = 2
        x1 = x - pad
        y1 = y - pad
        x2 = x + width + pad
        y2 = y + height + pad
        self._outline = batch.add(4, pyglet.gl.GL_QUADS, bg_group,
                                  ('v2i', [x1, y1, x2, y1, x2, y2, x1, y2]),
                                  ('c4B', color * 4))
        # Text and Caret:
        self._layout = IncrementalTextLayout(self._doc,
                                             width,
                                             height,
                                             multiline=False,
                                             batch=batch,
                                             group=fg_group)
        self._caret = Caret(self._layout)
        self._caret.visible = False

        self._layout.x = x
        self._layout.y = y

        self._focus = False

        super().__init__(x, y, width, height)
Example #13
0
    def __init__(self,
                 text,
                 x,
                 y,
                 width,
                 color=(255, 255, 255, 255),
                 batch=None,
                 group=None):
        self._doc = pyglet.text.document.UnformattedDocument(text)
        self._doc.set_style(0, len(self._doc.text), dict(color=(0, 0, 0, 255)))
        font = self._doc.get_font()
        height = font.ascent - font.descent

        self._user_group = group
        bg_group = Group(order=0, parent=group)
        fg_group = Group(order=1, parent=group)

        # Rectangular outline with 2-pixel pad:
        p = 2
        self._outline = pyglet.shapes.Rectangle(x - p, y - p, width + p + p,
                                                height + p + p, color[:3],
                                                batch, bg_group)
        self._outline.opacity = color[3]

        # Text and Caret:
        self._layout = IncrementalTextLayout(self._doc,
                                             width,
                                             height,
                                             multiline=False,
                                             batch=batch,
                                             group=fg_group)
        self._layout.x = x
        self._layout.y = y
        self._caret = Caret(self._layout)
        self._caret.visible = False

        self._focus = False

        super().__init__(x, y, width, height)
Example #14
0
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)})
Example #15
0
class Editable(Control):
    def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0, 0), wrap=True, id=None, **kwargs):
        """ An editable text box.
            When clicked, it has the focus and can receive keyboard events.
            With wrap=True, several lines of text will wrap around the width.
            Optional parameters can include fill, font, fontsize, fontweight.
        """
        txt = Text(
            value or " ",
            **{
                "fill": _popdefault(kwargs, "fill", Color(0, 0.9)),
                "font": _popdefault(kwargs, "font", theme["fontname"]),
                "fontsize": _popdefault(kwargs, "fontsize", theme["fontsize"]),
                "fontweight": _popdefault(kwargs, "fontweight", theme["fontweight"]),
                "lineheight": _popdefault(kwargs, "lineheight", 1),
                "align": LEFT,
            }
        )
        kwargs["width"] = width
        kwargs["height"] = height
        Control.__init__(self, x=x, y=y, id=id, **kwargs)
        self.reserved = kwargs.get("reserved", [ENTER, TAB])
        self._padding = padding
        self._i = 0  # Index of character on which the mouse is pressed.
        self._empty = value == "" and True or False
        self._editor = IncrementalTextLayout(txt._label.document, width, height, multiline=wrap)
        self._editor.content_valign = wrap and "top" or "center"
        self._editor.selection_background_color = (170, 200, 230, 255)
        self._editor.selection_color = txt._label.color
        self._editor.caret = Caret(self._editor)
        self._editor.caret.visible = False
        self._editing = False  # When True, cursor is blinking and text can be edited.
        Editable._pack(self)  # On init, call Editable._pack(), not the derived Field._pack().

    def _pack(self):
        self._editor.x = self._padding[0]
        self._editor.y = self._padding[1]
        self._editor.width = max(0, self.width - self._padding[0] * 2)
        self._editor.height = max(0, self.height - self._padding[1] * 2)

    def _get_value(self):
        # IncrementalTextLayout in Pyglet 1.1.4 has a bug with empty strings.
        # We keep track of empty strings with Editable._empty to avoid this.
        return not self._empty and self._editor.document.text or u""

    def _set_value(self, string):
        self._editor.begin_update()
        self._editor.document.text = string or " "
        self._editor.end_update()
        self._empty = string == "" and True or False

    value = property(_get_value, _set_value)

    def _get_editing(self):
        return self._editing

    def _set_editing(self, b):
        self._editing = b
        self._editor.caret.visible = b
        global EDITING
        if b is False and EDITING == self:
            EDITING = None
        if b is True:
            EDITING = self
            # Cursor is blinking and text can be edited.
            # Visit all layers on the canvas.
            # Remove the caret from all other Editable controls.
            for layer in self.root.canvas and self.root.canvas.layers or []:
                layer.traverse(
                    visit=lambda layer: isinstance(layer, Editable)
                    and layer != self
                    and setattr(layer, "editing", False)
                )

    editing = property(_get_editing, _set_editing)

    @property
    def selection(self):
        # Yields a (start, stop)-tuple with the indices of the current selected text.
        return (self._editor.selection_start, self._editor.selection_end)

    @property
    def selected(self):
        # Yields True when text is currently selected.
        return self.selection[0] != self.selection[1]

    @property
    def cursor(self):
        # Yields the index at the text cursor (caret).
        return self._editor.caret.position

    def index(self, x, y):
        """ Returns the index of the character in the text at position x, y.
        """
        x0, y0 = self.absolute_position()
        i = self._editor.get_position_from_point(x - x0, y - y0)
        if self._editor.get_point_from_position(0)[0] > x - x0:  # Pyglet bug?
            i = 0
        if self._empty:
            i = 0
        return i

    def on_mouse_enter(self, mouse):
        mouse.cursor = TEXT

    def on_mouse_press(self, mouse):
        i = self._i = self.index(mouse.x, mouse.y)
        self._editor.set_selection(0, 0)
        self.editing = True
        self._editor.caret.position = i
        Control.on_mouse_press(self, mouse)

    def on_mouse_release(self, mouse):
        if not self.dragged:
            self._editor.caret.position = self.index(mouse.x, mouse.y)
        Control.on_mouse_release(self, mouse)

    def on_mouse_drag(self, mouse):
        i = self.index(mouse.x, mouse.y)
        self._editor.selection_start = max(min(self._i, i), 0)
        self._editor.selection_end = min(max(self._i, i), len(self.value))
        self._editor.caret.visible = False
        Control.on_mouse_drag(self, mouse)

    def on_mouse_doubleclick(self, mouse):
        # Select the word at the mouse position.
        # Words are delimited by non-alphanumeric characters.
        i = self.index(mouse.x, mouse.y)
        delimiter = lambda ch: not (ch.isalpha() or ch.isdigit())
        if i < len(self.value) and delimiter(self.value[i]):
            self._editor.set_selection(i, i + 1)
        if i == len(self.value) and self.value != "" and delimiter(self.value[i - 1]):
            self._editor.set_selection(i - 1, i)
        a = _find(lambda (i, ch): delimiter(ch), enumerate(reversed(self.value[:i])))
        b = _find(lambda (i, ch): delimiter(ch), enumerate(self.value[i:]))
        a = a and i - a[0] or 0
        b = b and i + b[0] or len(self.value)
        self._editor.set_selection(a, b)

    def on_key_press(self, keys):
        if self._editing:
            self._editor.caret.visible = True
            i = self._editor.caret.position
            if keys.code == LEFT:
                # The left arrow moves the text cursor to the left.
                self._editor.caret.position = max(i - 1, 0)
            elif keys.code == RIGHT:
                # The right arrow moves the text cursor to the right.
                self._editor.caret.position = min(i + 1, len(self.value))
            elif keys.code in (UP, DOWN):
                # The up arrows moves the text cursor to the previous line.
                # The down arrows moves the text cursor to the next line.
                y = keys.code == UP and -1 or +1
                n = self._editor.get_line_count()
                i = self._editor.get_position_on_line(
                    max(self._editor.get_line_from_position(i) + y, 0), self._editor.get_point_from_position(i)[0]
                )
                self._editor.caret.position = i
            elif keys.code == TAB and TAB in self.reserved:
                # The tab key navigates away from the control.
                self._editor.caret.position = 0
                self.editing = False
            elif keys.code == ENTER and ENTER in self.reserved:
                # The enter key executes on_action() and navigates away from the control.
                self._editor.caret.position = 0
                self.editing = False
                self.on_action()
            elif keys.code == BACKSPACE and self.selected:
                # The backspace key removes the current text selection.
                self.value = self.value[: self.selection[0]] + self.value[self.selection[1] :]
                self._editor.caret.position = max(self.selection[0], 0)
            elif keys.code == BACKSPACE and i > 0:
                # The backspace key removes the character at the text cursor.
                self.value = self.value[: i - 1] + self.value[i:]
                self._editor.caret.position = max(i - 1, 0)
            elif keys.char:
                if self.selected:
                    # Typing replaces any text currently selected.
                    self.value = self.value[: self.selection[0]] + self.value[self.selection[1] :]
                    self._editor.caret.position = i = max(self.selection[0], 0)
                ch = keys.char
                ch = ch.replace("\r", "\n\r")
                self.value = self.value[:i] + ch + self.value[i:]
                self._editor.caret.position = min(i + 1, len(self.value))
            self._editor.set_selection(0, 0)

    def draw(self):
        self._editor.draw()
    def __init__(self,
                 *,
                 highscores,
                 ui_batch,
                 cb_start_game=None,
                 cb_add_highscore=None,
                 add_score=None):
        super().__init__()

        # Make sure we can handle events
        self.event_handlers = [self]

        # Store callbacks, the ui batch and our optional score3
        self.cb_start_game = cb_start_game
        self.cb_add_highscore = cb_add_highscore
        self.ui_batch = ui_batch
        self.add_score = add_score

        # We need to keep track of our children so we can remove them in self.delete()
        self.children = []

        # Show title
        self.children.append(
            Label('WELCOME TO',
                  font_name='m5x7',
                  font_size=128,
                  x=WIDTH / 2,
                  y=HEIGHT - 16,
                  anchor_x='center',
                  anchor_y='top',
                  batch=self.ui_batch))
        self.children.append(
            Label('HELL',
                  font_name='m5x7',
                  font_size=512,
                  x=WIDTH / 2 + 50,
                  y=HEIGHT,
                  anchor_x='center',
                  anchor_y='top',
                  batch=self.ui_batch))

        # If we need to add a score
        if add_score is not None:
            # Make sure that self.continue_label exists so we don't crash in self.tick()
            self.continue_label = None

            # Show some text
            self.children.append(
                Label('Your score was:',
                      font_name='m5x7',
                      font_size=48,
                      x=WIDTH / 2,
                      y=400,
                      align='center',
                      anchor_x='center',
                      anchor_y='bottom',
                      batch=self.ui_batch))
            self.children.append(
                Label(f'{add_score}',
                      font_name='m5x7',
                      font_size=128,
                      x=WIDTH / 2,
                      y=280,
                      align='center',
                      anchor_x='center',
                      anchor_y='bottom',
                      batch=self.ui_batch))
            self.children.append(
                Label('Enter name for highscore:',
                      font_name='m5x7',
                      font_size=32,
                      x=WIDTH / 2,
                      y=200,
                      align='center',
                      anchor_x='center',
                      anchor_y='bottom',
                      batch=self.ui_batch))

            # Prepare a document with styling
            self.document = UnformattedDocument()
            self.document.set_style(
                0, 1, {
                    'font_name': 'm5x7',
                    'font_size': 64,
                    'color': (255, 255, 255, 255),
                    'align': 'center'
                })
            # Find the height of the font
            font = self.document.get_font()
            height = font.ascent - font.descent
            # Make a TextLayout that handles dynamically adding text
            # Make it multiline even though we don't want multiple lines because otherwise align=center doesn't work
            self.layout = IncrementalTextLayout(self.document,
                                                WIDTH / 3,
                                                height,
                                                multiline=True,
                                                batch=self.ui_batch)
            self.layout.anchor_y = 'top'
            self.layout.anchor_x = 'center'
            self.layout.x = WIDTH / 2
            self.layout.y = 200
            # Add a carat (cursor)
            self.caret = Caret(self.layout,
                               batch=self.ui_batch,
                               color=(255, 255, 255))
            # Type q and then backspace
            # This ensures that the carat is visible as it only shows up after something has been typed
            self.caret.on_text('q')
            self.caret.on_text_motion(key.MOTION_BACKSPACE)
            # Make sure we can delete layout and carat in self.delete()
            self.children.append(self.layout)
            self.children.append(self.caret)
        else:
            # If we have some highscores to show
            if highscores:
                # Show a title
                self.children.append(
                    Label('Highscores:',
                          font_name='m5x7',
                          font_size=48,
                          x=WIDTH / 2,
                          y=420,
                          align='center',
                          anchor_x='center',
                          anchor_y='bottom',
                          batch=self.ui_batch))
                # ... followed by each highscore
                for i, highscore in enumerate(highscores):
                    self.children.append(
                        Label(f'{highscore.name} - {highscore.score}',
                              font_name='m5x7',
                              font_size=32,
                              x=WIDTH / 2,
                              y=380 - i * 32,
                              align='center',
                              anchor_x='center',
                              anchor_y='bottom',
                              batch=self.ui_batch))

            # Show continue label, and make sure to have it below highscores if any
            self.continue_label = Label('Press SPACE to start game...',
                                        font_name='m5x7',
                                        font_size=48,
                                        x=WIDTH / 2,
                                        y=32 if highscores else HEIGHT / 4,
                                        align='center',
                                        anchor_x='center',
                                        anchor_y='bottom',
                                        batch=self.ui_batch)
            # Timer for blinking
            self.continue_timer = 0

            self.children.append(self.continue_label)
Example #17
0
class WeaponBar(object):
    """docstring for WeaponBar"""
    def __init__(self, batch, scale):
        super(WeaponBar, self).__init__()
        self.batch = batch
        self.weapons = {}
        self.ammos = []
        self.tris = []
        self.scale = scale

    def __len__(self):
        return len(self.weapons)

    def init_bar(self, weapons):
        try:
            if self.ammolayout._document:
                self.ammolayout.delete()
                for tri in self.tris:
                    tri.remove()
        except AttributeError:
            pass
        ammotext = '\t'.join(str(w.ammo) for key, w in weapons.iteritems()
                             if key != 'w0')
        self.ammos = ammotext.split('\t')
        self.ammodoc = FormattedDocument(ammotext)
        self.ammodoc.set_style(0, len(ammotext), dict(color=[255]*4,
                               tab_stops=[120*(i+1) for i in range(6)],
                               font_size=24, align='center', wrap=False))
        self.ammolayout = IncrementalTextLayout(self.ammodoc, width=600,
                                                height=50, batch=self.batch,
                                                multiline=True)
        self.ammolayout.x = (1280 / 2) * self.scale.x
        self.ammolayout.y = 20 * self.scale.y
        self.ammolayout.anchor_x = 'center'
        self.ammolayout.anchor_y = 'bottom'
        w = self.ammolayout.content_width
        colorlist = [weaponcolors[key] for key in weapons if key != 'w0']
        self.tris = [Triangle(640*self.scale.x-w/2-52+120*i, 35*self.scale.y,
                     50, 50, col, self.batch, 0, 0)
                     for i, col in enumerate(colorlist)]

    def update(self, weapons):
        if len(weapons) != len(self.weapons):
            self.init_bar(weapons)
            self.weapons = weapons.copy()
        else:
            ammotext = '\t'.join(str(w.ammo) for key, w in weapons.iteritems()
                                 if key != 'w0')
            ammos = ammotext.split('\t')
            self.ammolayout.begin_update()
            for i, a in enumerate(ammos):
                if a != self.ammos[i]:
                    ln = sum(len(self.ammos[j]) for j in range(i)) + i
                    self.ammodoc.delete_text(ln, ln + len(self.ammos[i]))
                    self.ammodoc.insert_text(ln, a)
            self.ammolayout.end_update()

            self.ammos = ammos

    def remove(self):
        try:
            self.weapons = {}
            self.ammolayout.delete()
            for tri in self.tris:
                tri.remove()
        except AttributeError:
            pass
Example #18
0
File: console.py Project: vrx/idia
    def __init__(self, window,
                 x=0, y=0, width=100, height=100,
                 anchor_x='left', anchor_y='bottom',
                 style = Default['terminal'], prompt = '> ', banner = ''):
        '''Create a new console.

        :Parameters:
            `window` : pyglet.window.Window
                Window this console will be embedded in.
            `x` : int
                X coordinate of the console.
            `y` : int
                Y coordinate of the console.
            `width` : int
                Width of the console in pixels, or None
            `height` : int
                Height of the console in pixels, or None
            `anchor_x` : str
                Anchor point of the X coordinate: one of ``"left"``,
                ``"center"`` or ``"right"``.
            `anchor_y` : str
                Anchor point of the Y coordinate: one of ``"bottom"``,
                ``"center"`` or ``"top"``.
            `style` : dict
                Style dictionnary describing element styles
            `prompt` : str
                Console prompt
            `banner` : str
                Text to be displayed prior to any input.
        '''

        super(Console, self).__init__()
        self._window = window
        self._style = style
        self._prompt = prompt
        self._prompt_start, self._prompt_end = 0, 0
        batch = pyglet.graphics.Batch()
        document = Document()
        margin = self._style['margin']
        layout = Layout(document,
                        width=width-2*margin, height=height-2*margin,
                        multiline=True, batch=batch)
        layout.anchor_x = anchor_x
        layout.anchor_y = anchor_y
        layout.x = int(margin)
        layout.y = int(margin)
        layout.view_y = 0
        layout.selection_color = self._style['selection_fg']
        layout.selection_background_color = self._style['selection_bg']
        caret = Caret(layout)
        caret.position = 0
        caret.visible = True
        r,g,b,a = self._style['text_fg']
        caret.color = (r,g,b)
        self._batch = batch
        self._document = document
        self._layout = layout
        self._caret = caret
        x,y,z = int(layout.x-margin), int(layout.y-margin), -.5
        w,h = layout.width+2*margin, layout.height+2*margin
        self._background = batch.add(
            4, pyglet.gl.GL_QUADS, None,
            ('v3f', (x,y,z, x+w,y,z, x+w,y+h,z,  x,y+h,z)),
            ('c4B', self._style['text_bg']*4))
        z += .1
        self._border = batch.add(
            4, pyglet.gl.GL_LINE_LOOP, None,
            ('v3f', (x,y,z, x+w,y,z, x+w,y+h,z,  x,y+h,z)),
            ('c4B', self._style['border_fg']*4))
        if banner:
            self.write(banner)
        if window:
            self._cursor = window.get_system_mouse_cursor('text')
        else:
            self._cursor = None
        self.resize(width,height)
    def __init__(self,
                 text,
                 x,
                 y,
                 width,
                 color=(255, 255, 255, 255),
                 text_color=(0, 0, 0, 255),
                 caret_color=(0, 0, 0),
                 batch=None,
                 group=None):
        """Create a text entry widget.

        :Parameters:
            `text` : str
                Initial text to display.
            `x` : int
                X coordinate of the text entry widget.
            `y` : int
                Y coordinate of the text entry widget.
            `width` : int
                The width of the text entry widget.
            `color` : (int, int, int, int)
                The color of the outline box in RGBA format.
            `text_color` : (int, int, int, int)
                The color of the text in RGBA format.
            `text_color` : (int, int, int)
                The color of the caret in RGB format.
            `batch` : `~pyglet.graphics.Batch`
                Optional batch to add the text entry widget to.
            `group` : `~pyglet.graphics.Group`
                Optional parent group of text entry widget.
        """
        self._doc = pyglet.text.document.UnformattedDocument(text)
        self._doc.set_style(0, len(self._doc.text), dict(color=text_color))
        font = self._doc.get_font()
        height = font.ascent - font.descent

        self._user_group = group
        bg_group = Group(order=0, parent=group)
        fg_group = Group(order=1, parent=group)

        # Rectangular outline with 2-pixel pad:
        self._pad = p = 2
        self._outline = pyglet.shapes.Rectangle(x - p, y - p, width + p + p,
                                                height + p + p, color[:3],
                                                batch, bg_group)
        self._outline.opacity = color[3]

        # Text and Caret:
        self._layout = IncrementalTextLayout(self._doc,
                                             width,
                                             height,
                                             multiline=False,
                                             batch=batch,
                                             group=fg_group)
        self._layout.x = x
        self._layout.y = y
        self._caret = Caret(self._layout, color=caret_color)
        self._caret.visible = False

        self._focus = False

        super().__init__(x, y, width, height)
Example #20
0
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
Example #21
0
class Editable(Control):
    
    def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0,0), wrap=True, id=None, **kwargs):
        """ An editable text box.
            When clicked, it has the focus and can receive keyboard events.
            With wrap=True, several lines of text will wrap around the width.
            Optional parameters can include fill, font, fontsize, fontweight.
        """
        txt = Text(value or " ", **{
               "fill" : _popdefault(kwargs, "fill", Color(0,0.9)),
               "font" : _popdefault(kwargs, "font", theme["fontname"]),
           "fontsize" : _popdefault(kwargs, "fontsize", theme["fontsize"]),
         "fontweight" : _popdefault(kwargs, "fontweight", theme["fontweight"]),
         "lineheight" : _popdefault(kwargs, "lineheight", 1),
              "align" : LEFT
        })
        kwargs["width"]  = width
        kwargs["height"] = height
        Control.__init__(self, x=x, y=y, id=id, **kwargs)
        self.reserved = kwargs.get("reserved", [ENTER, TAB])
        self._padding = padding
        self._i       = 0     # Index of character on which the mouse is pressed.
        self._empty   = value == "" and True or False
        self._editor  = IncrementalTextLayout(txt._label.document, width, height, multiline=wrap)
        self._editor.content_valign = wrap and "top" or "center"
        self._editor.selection_background_color = (170, 200, 230, 255)
        self._editor.selection_color = txt._label.color
        self._editor.caret = Caret(self._editor)
        self._editor.caret.visible = False
        self._editing = False # When True, cursor is blinking and text can be edited.
        Editable._pack(self)  # On init, call Editable._pack(), not the derived Field._pack().
        
    def _pack(self):
        self._editor.x = self._padding[0]
        self._editor.y = self._padding[1]
        self._editor.width  = max(0, self.width  - self._padding[0] * 2)
        self._editor.height = max(0, self.height - self._padding[1] * 2)

    def _get_value(self):
        # IncrementalTextLayout in Pyglet 1.1.4 has a bug with empty strings.
        # We keep track of empty strings with Editable._empty to avoid this.
        return not self._empty and self._editor.document.text or u""
    def _set_value(self, string):
        self._editor.begin_update()
        self._editor.document.text = string or " "
        self._editor.end_update()
        self._empty = string == "" and True or False
        
    value = property(_get_value, _set_value)

    def _get_editing(self):
        return self._editing
    def _set_editing(self, b):
        self._editing = b
        self._editor.caret.visible = b
        global EDITING
        if b is False and EDITING == self:
            EDITING = None
        if b is True:
            EDITING = self
            # Cursor is blinking and text can be edited.
            # Visit all layers on the canvas.
            # Remove the caret from all other Editable controls.
            for layer in (self.root.canvas and self.root.canvas.layers or []):
                layer.traverse(visit=lambda layer: \
                    isinstance(layer, Editable) and layer != self and \
                        setattr(layer, "editing", False))
                        
    editing = property(_get_editing, _set_editing)

    @property
    def selection(self):
        # Yields a (start, stop)-tuple with the indices of the current selected text.
        return (self._editor.selection_start,
                self._editor.selection_end)
    
    @property
    def selected(self):
        # Yields True when text is currently selected.
        return self.selection[0] != self.selection[1]
        
    @property
    def cursor(self):
        # Yields the index at the text cursor (caret).
        return self._editor.caret.position
    
    def index(self, x, y):
        """ Returns the index of the character in the text at position x, y.
        """
        x0, y0 = self.absolute_position()
        i = self._editor.get_position_from_point(x-x0, y-y0)
        if self._editor.get_point_from_position(0)[0] > x-x0: # Pyglet bug?
            i = 0
        if self._empty:
            i = 0
        return i
    
    def on_mouse_enter(self, mouse):
        mouse.cursor = TEXT
        
    def on_mouse_press(self, mouse):
        i = self._i = self.index(mouse.x, mouse.y)
        self._editor.set_selection(0, 0)
        self.editing = True
        self._editor.caret.position = i
        Control.on_mouse_press(self, mouse)
        
    def on_mouse_release(self, mouse):
        if not self.dragged:
            self._editor.caret.position = self.index(mouse.x, mouse.y)
        Control.on_mouse_release(self, mouse)
        
    def on_mouse_drag(self, mouse):
        i = self.index(mouse.x, mouse.y)
        self._editor.selection_start = max(min(self._i, i), 0)
        self._editor.selection_end   = min(max(self._i, i), len(self.value))
        self._editor.caret.visible = False
        Control.on_mouse_drag(self, mouse)

    def on_mouse_doubleclick(self, mouse):
        # Select the word at the mouse position. 
        # Words are delimited by non-alphanumeric characters.
        i = self.index(mouse.x, mouse.y)
        delimiter = lambda ch: not (ch.isalpha() or ch.isdigit())
        if i  < len(self.value) and delimiter(self.value[i]):
            self._editor.set_selection(i, i+1)
        if i == len(self.value) and self.value != "" and delimiter(self.value[i-1]):
            self._editor.set_selection(i-1, i)
        a = _find(lambda (i,ch): delimiter(ch), enumerate(reversed(self.value[:i])))
        b = _find(lambda (i,ch): delimiter(ch), enumerate(self.value[i:]))
        a = a and i-a[0] or 0
        b = b and i+b[0] or len(self.value)
        self._editor.set_selection(a, b)

    def on_key_press(self, key):
        if self._editing:
            self._editor.caret.visible = True
            i = self._editor.caret.position
            if   key.code == LEFT:
                # The left arrow moves the text cursor to the left.
                self._editor.caret.position = max(i-1, 0)
            elif key.code == RIGHT:
                # The right arrow moves the text cursor to the right.
                self._editor.caret.position = min(i+1, len(self.value))
            elif key.code in (UP, DOWN):
                # The up arrows moves the text cursor to the previous line.
                # The down arrows moves the text cursor to the next line.
                y = key.code == UP and -1 or +1
                n = self._editor.get_line_count()
                i = self._editor.get_position_on_line(
                    max(self._editor.get_line_from_position(i)+y, 0),
                        self._editor.get_point_from_position(i)[0])
                self._editor.caret.position = i
            elif key.code == TAB and TAB in self.reserved:
                # The tab key navigates away from the control.
                self._editor.caret.position = 0
                self.editing = False
            elif key.code == ENTER and ENTER in self.reserved:
                # The enter key executes on_action() and navigates away from the control.
                self._editor.caret.position = 0
                self.editing = False
                self.on_action()
            elif key.code == BACKSPACE and self.selected:
                # The backspace key removes the current text selection.
                self.value = self.value[:self.selection[0]] + self.value[self.selection[1]:]
                self._editor.caret.position = max(self.selection[0], 0)
            elif key.code == BACKSPACE and i > 0:
                # The backspace key removes the character at the text cursor.
                self.value = self.value[:i-1] + self.value[i:]
                self._editor.caret.position = max(i-1, 0)
            elif key.char:
                if self.selected:
                    # Typing replaces any text currently selected.
                    self.value = self.value[:self.selection[0]] + self.value[self.selection[1]:]
                    self._editor.caret.position = i = max(self.selection[0], 0)
                ch = key.char
                ch = ch.replace("\r", "\n\r")
                self.value = self.value[:i] + ch + self.value[i:]
                self._editor.caret.position = min(i+1, len(self.value))
            self._editor.set_selection(0, 0)
    
    def draw(self):
        self._editor.draw()