Exemplo n.º 1
0
class UpdateListbox(Listbox):
    """Listbox with a function called on selection change"""
    def _on_selection_change(self):
        self.update_func(self.list_pos)

    _list_pos = widget.call_on_change("__list_pos", _on_selection_change)
    _list = widget.call_on_change("__list", _on_selection_change)

    def __init__(self, *args, **kwargs):
        self.update_func = kwargs.pop("update_func", lambda value: None)
        super(UpdateListbox, self).__init__(*args, **kwargs)
Exemplo n.º 2
0
class FastText(Text):
    """
       Reduces font searches by assuming a monospace font and single-line text.
    """
    text = widget.call_on_change("_text", text_changed)
    old_len = 0
    maybe_needs_refont = False
Exemplo n.º 3
0
class StyledText(Text):
    def update_text(self):
        self.text = "".join(self.chunks)

    chunks = widget.call_on_change("_chunks", update_text)
    styles = widget.causes_redraw("_styles")

    def __init__(self, *args, **kwargs):
        chunks = kwargs.pop("chunks", ())
        styles = kwargs.pop("styles", ())
        super(StyledText, self).__init__(*args, **kwargs)

        self.chunks = chunks
        self.styles = styles

    def print_text(self):
        if self.styles:
            offset = 0
            styles = []
            for chunk, style in zip(self.chunks, self.styles):
                offset += len(chunk)
                styles.append(list(style) + [offset])
            styles[-1][-1] = 0

            print_string(self.surface, self.text, (3, 2), self.font, styles,
                         self.align, self.valign, self.real_size, self.wrap)
        else:
            super(StyledText, self).print_text()
Exemplo n.º 4
0
class UpdateSlider(Slider):
    def _on_slider_move(self):
        self.update_func(self.slider_pos)

    _slider_pos = widget.call_on_change("__slider_pos", _on_slider_move)

    def __init__(self, *args, **kwargs):
        self.update_func = kwargs.pop("update_func", lambda value: None)
        super(UpdateSlider, self).__init__(*args, **kwargs)
Exemplo n.º 5
0
class UpdateEditableText(EditableText):
    def _on_text_change(self):
        self.update_func(self.text)

    _text = widget.call_on_change("__text", _on_text_change)

    def __init__(self, *args, **kwargs):
        self.update_func = kwargs.pop("update_func", lambda value: None)
        super(UpdateEditableText, self).__init__(*args, **kwargs)
Exemplo n.º 6
0
class ChunkedText(Text):
    def update_text(self):
        self.text = "".join(self.chunks)

    chunks = widget.call_on_change("_chunks", update_text)

    def __init__(self, *args, **kwargs):
        chunks = kwargs.pop("chunks", ())
        super(ChunkedText, self).__init__(*args, **kwargs)

        self.chunks = chunks
Exemplo n.º 7
0
class Text(widget.BorderedWidget):
    text = widget.call_on_change("_text", resize_redraw)
    base_font = widget.call_on_change("_base_font", resize_redraw)
    shrink_factor = widget.call_on_change("_shrink_factor", resize_redraw)
    underline = widget.call_on_change("_underline", resize_redraw)
    wrap = widget.call_on_change("_wrap", resize_redraw)
    bold = widget.call_on_change("_bold", resize_redraw)

    color = widget.causes_redraw("_color")
    align = widget.causes_redraw("_align")
    valign = widget.causes_redraw("_valign")

    def __init__(self,
                 parent,
                 pos,
                 size=(0, .05),
                 anchor=constants.TOP_LEFT,
                 text=None,
                 base_font=None,
                 shrink_factor=1,
                 color=None,
                 align=constants.CENTER,
                 valign=constants.MID,
                 underline=-1,
                 wrap=True,
                 bold=False,
                 text_size=36,
                 **kwargs):
        super(Text, self).__init__(parent, pos, size, anchor, **kwargs)

        self.text = text
        self.base_font = base_font or g.font[0]
        self.color = color or g.colors["white"]
        self.shrink_factor = shrink_factor
        self.underline = underline
        self.align = align
        self.valign = valign
        self.wrap = wrap
        self.bold = bold
        self.text_size = text_size

    max_size = property(lambda self: convert_font_size(self.text_size))
    font = property(lambda self: self._font)

    def pick_font(self, dimensions):
        nice_size = self.pick_font_size(dimensions, False)
        mean_size = self.pick_font_size(dimensions)

        if nice_size > mean_size - convert_font_size(5):
            size = nice_size
        else:
            size = mean_size

        return self.base_font[size]

    def font_bisect(self, test_font):
        left = 0
        right = len(self.base_font)
        if self.max_size:
            right = min(right, self.max_size)

        def test_size(size):
            font = self.base_font[size]

            font.set_bold(self.bold)
            result = test_font(font)
            font.set_bold(False)

            return result

        return do_bisect(left, right, test_size)

    def pick_font_size(self, dimensions, break_words=True):
        if dimensions[0]:
            width = int((dimensions[0] - 4) * self.shrink_factor)
        else:
            width = None
        height = int((dimensions[1] - 4) * self.shrink_factor)

        basic_line_count = self.text.count("\n") + 1

        def test_size(test_font):
            too_wide = False
            if width:
                if self.wrap:
                    try:
                        lines = split_wrap(self.text, test_font, width,
                                           break_words)
                    except WrapError:
                        lines = []
                        too_wide = True
                else:
                    lines = split_wrap(self.text, test_font, 0)
                    for line in lines:
                        if test_font.size(line)[0] > width:
                            too_wide = True
                            break
                line_count = len(lines)
            else:
                line_count = basic_line_count

            too_tall = (test_font.get_linesize() * line_count) > height

            return not (too_tall or too_wide)

        return self.font_bisect(test_size)

    def size_using_font(self, font, width=0):
        #Calculate the size of the text block.
        raw_width, raw_height = size_of_block(self.text, font, width)

        #Adjust for shrink_factor and borders.
        width = int(raw_width / self.shrink_factor) + 4
        height = int(raw_height / self.shrink_factor) + 4

        return width, height

    def calc_text_size(self, initial_dimensions):
        if not (initial_dimensions[0] and initial_dimensions[1]):
            if not self.max_size:
                raise ValueError("No font size given, but a dimension is 0.")

            max_font = self.base_font[self.max_size]
            if initial_dimensions[0] == initial_dimensions[1] == 0:
                # No size specified, use the natural size of the max font.
                width, height = self.size_using_font(max_font)
                return (width, height), max_font
            elif not initial_dimensions[1]:
                # Width specified, use the size of the max font, word-wrapped.
                text_width = int(
                    (initial_dimensions[0] - 4) * self.shrink_factor)
                width, height = self.size_using_font(max_font,
                                                     width=text_width)
                return (initial_dimensions[0], height), max_font
            else:
                # Height specified.  Try the natural size of the max font.
                width, height = self.size_using_font(max_font)

                if height <= initial_dimensions[1]:
                    return (width, initial_dimensions[1]), max_font
                else:
                    # Too tall.  Run a binary search to find the largest font
                    # size that fits.
                    def test_size(font):
                        width, height = self.size_using_font(font)
                        width, raw_height = size_of_block(self.text, font)
                        height = int(raw_height / self.shrink_factor) + 4
                        return height <= initial_dimensions[1]

                    font_size = self.font_bisect(test_size)
                    font = self.base_font[font_size]
                    width, height = self.size_using_font(font)

                    return (width, initial_dimensions[1]), font
        else:
            # Both sizes specified.  Search for a usable font size.
            return initial_dimensions, self.pick_font(initial_dimensions)

    def _calc_size(self):
        base_size = list(super(Text, self)._calc_size())

        if self.text is None:
            return tuple(base_size)
        else:
            # Determine the true size and font of the text area.
            text_size, font = self.calc_text_size(base_size)
            self._font = font
            return tuple(text_size)

    def redraw(self):
        super(Text, self).redraw()

        if self.text != None:
            self.print_text()

    def print_text(self):
        # Mark the character to be underlined (if any).
        no_underline = [self.color, None, False]
        underline = [self.color, None, True]
        styles = [no_underline + [0]]
        if 0 <= self.underline < len(self.text):
            styles.insert(0, underline + [self.underline + 1])
            if self.underline != 0:
                styles.insert(0, no_underline + [self.underline])

        self.font.set_bold(self.bold)
        # Print the string itself.
        print_string(self.surface, self.text, (3, 2), self.font, styles,
                     self.align, self.valign, self.real_size, self.wrap)
        self.font.set_bold(False)