~dreamsorcerer/simplegc/0.2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# Copyright 2013 the SGC project developers.
# See the LICENSE file at the top-level directory of this distribution
# and at http://program.sambull.org/sgc/license.html.

"""
Progress Bar widget. Indicates progress to the user with either a progress
estimate or activity throbber.

"""

import pygame
from pygame.locals import *
from pygame import draw

from _locals import *
from base_widget import Simple


class ProgressBar(Simple):
    """
    A Progress Bar.

    Images:
      'image': The background of the bar.
      'bar': The image to be used for the percent bar
          (bar will be cropped, not stretched).
      'throbber': The image used for the 'activity' throbber.
      'overlay': This image will always be displayed on top of the widget
          regardless of mode, it is by default blank, however passing the
          keyword 'text' to the config function will draw this text onto this
          surface.
    """

    _default_size = (100, 20)
    _extra_images = {"bar": ((1, -4), (1, -4)),
                     "throbber": ((.2, -6), (1, -6)),
                     "overlay": ((1, 0), (1, 0))}
    _settings_default = {"col": (118, 45, 215), "font": Font["widget"],
                         "text": "", "text_col": (10, 10, 10), "total_time": 1.,
                         "pulse_duration": .1}
    _surf_flags = SRCALPHA

    _bar_fraction = 0.
    _throbber_move_timer = 0
    _activity_mode = False

    def _config(self, **kwargs):
        """
          col: ``tuple`` (r,g,b) The color to be used for the bar, to avoid
              saturation of the throbber use values below 200
          pulse_duration: ``float`` time in seconds each pulse should last,
              useful if your update loop is slower than the default of .25.
          total_time: ``float`` time in seconds the throbber should take to
              travel the full distance of the bar.
          font: font to be used for the text.
          text: ``str`` the text to be shown in the center of the widget.
          text_col: the colour of the text.

        """
        for key in ("col", "font", "total_time",
                    "pulse_duration", "text_col"):
            if key in kwargs:
                self._settings[key] = kwargs[key]

        if "text" in kwargs:
            self._settings["text"] = kwargs["text"]
            overlay = self._images["overlay"]
            overlay.image.fill((0, 0, 0, 0))
            label = self._settings["font"].render(self._settings["text"], True,
                                                  self._settings["text_col"])
            overlay.image.blit(label, (overlay.rect.w / 2 -
                                       label.get_rect().w / 2,
                                       overlay.rect.h / 2 -
                                       label.get_rect().h / 2))

        if "total_time" in kwargs or "pulse_duration" in kwargs:
            total_time_ms = self._settings["total_time"] * 1000.
            self._throbber_velocity = self.rect.w / total_time_ms

        if "init" in kwargs:
            self._images["bar"]._show = False
            self._images["throbber"]._show = False
            self._images["throbber"].pos = [0, 3]

            total_time_ms = self._settings["total_time"] * 1000.
            self._throbber_velocity = self.rect.w / total_time_ms

            self._throbber_x = 0

    def _draw_base(self):
        draw.rect(self._images["image"], (100, 100, 100),
                  (0, 0, self.rect.w, self.rect.h))
        draw.rect(self._images["image"], (240, 240, 240),
                  (1, 1, self.rect.w - 2, self.rect.h - 2))

    def _draw_bar(self, image, size):
        draw.rect(image, self._settings["col"],
                  (0, 0, size[0], size[1]))

    def _draw_throbber(self, image, size):
        brightened_color = [x + 20 for x in self._settings["col"]]
        draw.rect(image, brightened_color, (0, 0, size[0], size[1]))

    def _draw_overlay(self, image, size):
        pass

    def update(self, time):
        if self._activity_mode:
            self._images["bar"]._show = False
            if self._throbber_move_timer > 0:
                self._throbber_move_timer -= time
                # Move throbber.
                self._throbber_x += self._throbber_velocity * time
                self._images["throbber"].rect.x = self._throbber_x
                # If outside box, change direction and move back in.
                left_edge = self._images["throbber"].rect.x - 3
                right_edge = left_edge + self._images["throbber"].rect.w + 6
                if left_edge < 0 or right_edge > self.rect.w:
                    self._throbber_velocity = - self._throbber_velocity
                    self._throbber_x += self._throbber_velocity * time
                    self._images["throbber"].rect.x = self._throbber_x
        else:
            bar_rect = (0, 0, self.rect.w * self._bar_fraction, self.rect.h)
            draw.rect(self.image, (100, 100, 100),
                      (0, 0, self.rect.w, self.rect.h))
            draw.rect(self.image, (240, 240, 240),
                      (1, 1, self.rect.w - 2, self.rect.h - 2))
            self.image.set_clip(bar_rect)
            self.image.blit(self._images["bar"].image, (2, 2))
            self.image.set_clip(None)

    def pulse(self):
        """
        Moves the activity mode throbber.

        The throbber will move for the number of seconds described by the
        pulse_duration config argument.

        Note: This will cause the Widget to change to activity mode if it
        was in percent mode before.

        """
        if not self._activity_mode:
            self._activity_mode = True
            bar_rect = (0, 0, self.rect.w * self._bar_fraction, self.rect.h)
            draw.rect(self.image, (100, 100, 100),
                      (0, 0, self.rect.w, self.rect.h))
            draw.rect(self.image, (240, 240, 240),
                      (1, 1, self.rect.w - 2, self.rect.h - 2))
            self._images["throbber"]._show = True
        self._throbber_move_timer = self._settings["pulse_duration"] * 1000

    @property
    def fraction(self):
        """Returns the current fraction the bar is at as a float."""
        return self._bar_fraction

    def set_fraction(self, fraction):
        """
        Sets the fraction the bar should be as a float.

        Note: This will cause the widget to change to percent mode if it
        was in activity mode before.
        """
        if self._activity_mode:
            self._activity_mode = False
            self._images["throbber"]._show = False
        self._bar_fraction = min(max(fraction, 0.), 1.)