示例#1
0
class SelectableText(Text):
    selected = widget.causes_redraw("_selected")

    selected_color = widget.auto_reconfig("_selected_color", "resolved",
                                          g.resolve_color_alias)
    resolved_selected_color = widget.causes_redraw("_resolved_selected_color")
    unselected_color = widget.auto_reconfig("_unselected_color", "resolved",
                                            g.resolve_color_alias)
    resolved_unselected_color = widget.causes_redraw(
        "_resolved_unselected_color")

    def __init__(self,
                 parent,
                 pos,
                 size,
                 border_color=None,
                 unselected_color=None,
                 selected_color=None,
                 **kwargs):
        super(SelectableText, self).__init__(parent, pos, size, **kwargs)

        self.border_color = border_color or "text_border"
        self.selected_color = selected_color or "text_background_selected"
        self.unselected_color = unselected_color or "text_background_unselected"

        self.selected = False

    def redraw(self):
        if self.selected:
            self.background_color = self.selected_color
        else:
            self.background_color = self.unselected_color
        super(SelectableText, self).redraw()
示例#2
0
class StyledText(ChunkedText):
    def resolve_styles(value):
        return tuple((g.resolve_color_alias(c), bg, u) for c, bg, u in value)

    styles = widget.auto_reconfig("_styles", "resolved", resolve_styles)
    resolved_styles = widget.causes_redraw("_resolved_styles")

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

        self.styles = styles

    def print_text(self):
        if self.styles:
            offset = 0
            styles = []
            for chunk, style in zip(self.chunks, self.resolved_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()
示例#3
0
class Image(widget.Widget):
    image = widget.auto_reconfig("_image", "resolved", g.resolve_image_alias)
    resolved_image = widget.causes_rebuild("_resolved_image")

    def __init__(self,
                 parent,
                 pos,
                 size=(1, 1),
                 anchor=constants.TOP_LEFT,
                 image=None):
        super(Image, self).__init__(parent, pos, size, anchor)

        self.old_size = None
        self.image = image

    def _calc_size(self):
        size = list(super(Image, self)._calc_size())
        if size[0] == size[1] == 0:
            raise ValueError("One image dimension must be specified!")

        image_size = self.resolved_image.get_size()
        ratio = image_size[0] / float(image_size[1])
        if size[0] == 0:
            size[0] = int(size[1] * ratio)
        elif size[1] == 0:
            size[1] = int(size[0] / ratio)

        return tuple(size)

    def rescale(self):
        self.resolved_scaled_image = scale(self.resolved_image, self.real_size)

    def resize(self):
        super(Image, self).resize()
        if self.real_size != self.old_size:
            self.rescale()
            self.old_size = self.real_size

    def redraw(self):
        super(Image, self).redraw()
        self.surface.blit(self.resolved_scaled_image, (0, 0))
示例#4
0
class ProgressText(SelectableText):
    progress = widget.causes_redraw("_progress")
    
    progress_color = widget.auto_reconfig("_progress_color", "resolved", g.resolve_color_alias)
    resolved_progress_color = widget.causes_redraw("_resolved_progress_color")


    def __init__(self, parent, pos, size, *args, **kwargs):
        self.parent = parent
        self.progress = kwargs.pop("progress", 0)
        self.progress_color = kwargs.pop("progress", "progress_background_progress")
        kwargs.setdefault("border_color", "progress_border")
        kwargs.setdefault("selected_color", "progress_background_selected")
        kwargs.setdefault("unselected_color", "progress_background_unselected")
        super(ProgressText, self).__init__(parent, pos, size, **kwargs)

    def redraw(self):
        super(ProgressText, self).redraw()
        width, height = self.real_size
        self.surface.fill(self.resolved_progress_color,
                          (0, 0, width * self.progress, height))
        self.draw_borders()
示例#5
0
class Text(widget.BorderedWidget):
    text = widget.call_on_change("_text", 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)

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

    color = widget.auto_reconfig("_color", "resolved", g.resolve_color_alias)
    resolved_color = widget.causes_redraw("_resolved_color")
    base_font = widget.auto_reconfig("_base_font", "resolved",
                                     g.resolve_font_alias)
    resolved_base_font = widget.call_on_change("_resolved_base_font",
                                               resize_redraw)

    text_size = widget.auto_reconfig("_text_size", "resolved",
                                     g.resolve_text_size)
    resolved_text_size = widget.causes_redraw("_resolved_text_size")

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

        self.text = text
        self.base_font = base_font or "normal"
        self.color = color or "text"
        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: min(
        len(self.resolved_base_font) - 1,
        convert_font_size(self._resolved_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)

        size = max(nice_size, mean_size - convert_font_size(5))

        return self.resolved_base_font[size]

    def font_bisect(self, test_font):
        left = 0
        right = (self.max_size or len(self.resolved_base_font) - 1) + 1

        def test_size(size):
            font = self.resolved_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] * self.shrink_factor)
        else:
            width = None
        height = int(dimensions[1] * 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.resolved_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, 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.resolved_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.resolved_color, None, False]
        underline = [self.resolved_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)
示例#6
0
class Slider(button.Button):
    slider_pos = widget.causes_rebuild("_slider_pos")
    slider_max = widget.causes_rebuild("_slider_max")
    slider_size = widget.causes_rebuild("_slider_size")
    horizontal = widget.causes_rebuild("_horizontal")

    slider_color = widget.auto_reconfig("_slider_color", "resolved", g.resolve_color_alias)
    resolved_slider_color = widget.causes_redraw("_resolved_slider_color")

    def __init__(self, parent, pos = (-1,0), size = (-.1, -1),
                 anchor = constants.TOP_RIGHT, borders = constants.ALL,
                 border_color=None, background_color=None, slider_color=None,
                 slider_pos=0, slider_max=10, slider_size=5, horizontal=False,
                 **kwargs):
        kwargs.setdefault("priority", 80)
        super(Slider, self).__init__(parent, pos, size, anchor=anchor, **kwargs)

        border_color = border_color or "slider_border"
        background_color = background_color or "slider_background"
        slider_color = slider_color or "slider_background_slider"

        self.borders = borders
        self.border_color = border_color
        self.background_color = background_color
        self.selected_color = background_color
        self.unselected_color = background_color
        self.slider_color = slider_color

        self.slider_pos = slider_pos
        self.slider_max = slider_max
        self.slider_size = slider_size
        self.horizontal = horizontal

        self.drag_state = None
        self.button = button.Button(self, pos = None, size = None,
                                    anchor = constants.TOP_LEFT,
                                    border_color = border_color,
                                    selected_color = slider_color,
                                    unselected_color = slider_color,
                                    priority = self.priority - 5)

    def redraw(self):
        super(Slider, self).redraw()
        self.button.selected_color = self.slider_color
        self.button.unselected_color = self.slider_color

    def add_hooks(self):
        super(Slider, self).add_hooks()
        self.parent.add_handler(constants.DRAG, self.handle_drag)
        self.parent.add_handler(constants.CLICK, self.handle_click, 50)

    def remove_hooks(self):
        super(Slider, self).remove_hooks()
        self.parent.remove_handler(constants.DRAG, self.handle_drag)
        self.parent.remove_handler(constants.CLICK, self.handle_click)

    def _calc_length(self, items):
        return items / float(self.slider_size + self.slider_max)

    def rebuild(self):
        super(Slider, self).rebuild()
        self.needs_resize = True

    def resize(self):
        super(Slider, self).resize()
        bar_start = self._calc_length(self.slider_pos)
        bar_length = self._calc_length(self.slider_size)

        if self.horizontal:
            self.button.pos = (-bar_start, 0)
            self.button.size = (-bar_length, -1)
            borders = [constants.TOP, constants.BOTTOM]

            self.button.resize()
            real_pos = self.button.real_pos[0]
            real_size = self.button.real_size[0]
            if real_pos == 0:
                borders.append(constants.LEFT)
            if real_pos + real_size == self.real_size[0]:
                borders.append(constants.RIGHT)
            self.button.borders = tuple(borders)
        else:
            self.button.pos = (0, -bar_start)
            self.button.size = (-1, -bar_length)
            borders = [constants.LEFT, constants.RIGHT]

            self.button.resize()
            real_pos = self.button.real_pos[1]
            real_size = self.button.real_size[1]
            if real_pos == 0:
                borders.append(constants.TOP)
            if real_pos + real_size == self.real_size[1]:
                borders.append(constants.BOTTOM)
            self.button.borders = tuple(borders)

    def handle_drag(self, event):
        if not self.visible:
            return

        if self.drag_state == None:
            self.start_pos = tuple(event.pos[i]-event.rel[i] for i in range(2))
            self.start_slider_pos = self.slider_pos
            if self.button.is_over(self.start_pos):
                self.drag_state = True
            else:
                self.drag_state = False

        if self.drag_state == True:
            if self.horizontal:
                dir = 0
            else:
                dir = 1

            mouse_pos = pygame.mouse.get_pos()
            rel = mouse_pos[dir] - self.start_pos[dir]
            unit = self._calc_length(1) * self.real_size[dir]
            movement = int( ( rel + (unit / 2.) ) // unit )

            new_pos = self.safe_pos(self.start_slider_pos + movement)
            self.slider_pos = new_pos

            raise constants.Handled

    def safe_pos(self, value):
        return max(0, min(self.slider_max, value))

    def handle_click(self, event):
        if self.drag_state == True:
            self.drag_state = None
            if not self.is_over(pygame.mouse.get_pos()):
                raise constants.Handled
        else:
            self.drag_state = None

    def jump(self, go_lower, big_jump=False, tiny_jump=False):
        if big_jump:
            jump_dist = max(1, self.slider_max // 2)
        elif tiny_jump:
            jump_dist = max(1, self.slider_max // 100)
        else:
            jump_dist = max(1, self.slider_size - 1)
        if go_lower:
            self.slider_pos = self.safe_pos(self.slider_pos - jump_dist)
        else:
            self.slider_pos = self.safe_pos(self.slider_pos + jump_dist)

    def activated(self, event):
        assert event.type == pygame.MOUSEBUTTONUP
        if self.horizontal:
            self.jump(go_lower=(event.pos[0] < self.button.collision_rect[0]))
        else:
            self.jump(go_lower = event.pos[1] < self.button.collision_rect[1])
        raise constants.Handled