Example #1
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 #2
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 #3
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()
Example #4
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()