~dreamsorcerer/simplegc/0.2

« back to all changes in this revision

Viewing changes to sgc/widgets/progress.py

  • Committer: Sam Bull
  • Date: 2014-04-20 16:12:40 UTC
  • mfrom: (355.1.9 ProgressBar)
  • Revision ID: sam@sambull.org-20140420161240-gug8nz04rbffg0zh
Add ProgressBar widget.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2013 the SGC project developers.
 
2
# See the LICENSE file at the top-level directory of this distribution
 
3
# and at http://program.sambull.org/sgc/license.html.
 
4
 
 
5
"""
 
6
Progress Bar widget. Indicates progress to the user with either a progress
 
7
estimate or activity throbber.
 
8
 
 
9
"""
 
10
 
 
11
import pygame
 
12
from pygame.locals import *
 
13
from pygame import draw
 
14
 
 
15
from _locals import *
 
16
from base_widget import Simple
 
17
 
 
18
 
 
19
class ProgressBar(Simple):
 
20
    """
 
21
    A Progress Bar.
 
22
 
 
23
    Images:
 
24
      'image': The background of the bar.
 
25
      'bar': The image to be used for the percent bar
 
26
          (bar will be cropped, not stretched).
 
27
      'throbber': The image used for the 'activity' throbber.
 
28
      'overlay': This image will always be displayed on top of the widget
 
29
          regardless of mode, it is by default blank, however passing the
 
30
          keyword 'text' to the config function will draw this text onto this
 
31
          surface.
 
32
    """
 
33
 
 
34
    _default_size = (100, 20)
 
35
    _extra_images = {"bar": ((1, -4), (1, -4)),
 
36
                     "throbber": ((.2, -6), (1, -6)),
 
37
                     "overlay": ((1, 0), (1, 0))}
 
38
    _settings_default = {"col": (118, 45, 215), "font": Font["widget"],
 
39
                         "text": "", "text_col": (10, 10, 10), "total_time": 1.,
 
40
                         "pulse_duration": .1}
 
41
    _surf_flags = SRCALPHA
 
42
 
 
43
    _bar_fraction = 0.
 
44
    _throbber_move_timer = 0
 
45
    _activity_mode = False
 
46
 
 
47
    def _config(self, **kwargs):
 
48
        """
 
49
          col: ``tuple`` (r,g,b) The color to be used for the bar, to avoid
 
50
              saturation of the throbber use values below 200
 
51
          pulse_duration: ``float`` time in seconds each pulse should last,
 
52
              useful if your update loop is slower than the default of .25.
 
53
          total_time: ``float`` time in seconds the throbber should take to
 
54
              travel the full distance of the bar.
 
55
          font: font to be used for the text.
 
56
          text: ``str`` the text to be shown in the center of the widget.
 
57
          text_col: the colour of the text.
 
58
 
 
59
        """
 
60
        for key in ("col", "font", "total_time",
 
61
                    "pulse_duration", "text_col"):
 
62
            if key in kwargs:
 
63
                self._settings[key] = kwargs[key]
 
64
 
 
65
        if "text" in kwargs:
 
66
            self._settings["text"] = kwargs["text"]
 
67
            overlay = self._images["overlay"]
 
68
            overlay.image.fill((0, 0, 0, 0))
 
69
            label = self._settings["font"].render(self._settings["text"], True,
 
70
                                                  self._settings["text_col"])
 
71
            overlay.image.blit(label, (overlay.rect.w / 2 -
 
72
                                       label.get_rect().w / 2,
 
73
                                       overlay.rect.h / 2 -
 
74
                                       label.get_rect().h / 2))
 
75
 
 
76
        if "total_time" in kwargs or "pulse_duration" in kwargs:
 
77
            total_time_ms = self._settings["total_time"] * 1000.
 
78
            self._throbber_velocity = self.rect.w / total_time_ms
 
79
 
 
80
        if "init" in kwargs:
 
81
            self._images["bar"]._show = False
 
82
            self._images["throbber"]._show = False
 
83
            self._images["throbber"].pos = [0, 3]
 
84
 
 
85
            total_time_ms = self._settings["total_time"] * 1000.
 
86
            self._throbber_velocity = self.rect.w / total_time_ms
 
87
 
 
88
            self._throbber_x = 0
 
89
 
 
90
    def _draw_base(self):
 
91
        draw.rect(self._images["image"], (100, 100, 100),
 
92
                  (0, 0, self.rect.w, self.rect.h))
 
93
        draw.rect(self._images["image"], (240, 240, 240),
 
94
                  (1, 1, self.rect.w - 2, self.rect.h - 2))
 
95
 
 
96
    def _draw_bar(self, image, size):
 
97
        draw.rect(image, self._settings["col"],
 
98
                  (0, 0, size[0], size[1]))
 
99
 
 
100
    def _draw_throbber(self, image, size):
 
101
        brightened_color = [x + 20 for x in self._settings["col"]]
 
102
        draw.rect(image, brightened_color, (0, 0, size[0], size[1]))
 
103
 
 
104
    def _draw_overlay(self, image, size):
 
105
        pass
 
106
 
 
107
    def update(self, time):
 
108
        if self._activity_mode:
 
109
            self._images["bar"]._show = False
 
110
            if self._throbber_move_timer > 0:
 
111
                self._throbber_move_timer -= time
 
112
                # Move throbber.
 
113
                self._throbber_x += self._throbber_velocity * time
 
114
                self._images["throbber"].rect.x = self._throbber_x
 
115
                # If outside box, change direction and move back in.
 
116
                left_edge = self._images["throbber"].rect.x - 3
 
117
                right_edge = left_edge + self._images["throbber"].rect.w + 6
 
118
                if left_edge < 0 or right_edge > self.rect.w:
 
119
                    self._throbber_velocity = - self._throbber_velocity
 
120
                    self._throbber_x += self._throbber_velocity * time
 
121
                    self._images["throbber"].rect.x = self._throbber_x
 
122
        else:
 
123
            bar_rect = (0, 0, self.rect.w * self._bar_fraction, self.rect.h)
 
124
            draw.rect(self.image, (100, 100, 100),
 
125
                      (0, 0, self.rect.w, self.rect.h))
 
126
            draw.rect(self.image, (240, 240, 240),
 
127
                      (1, 1, self.rect.w - 2, self.rect.h - 2))
 
128
            self.image.set_clip(bar_rect)
 
129
            self.image.blit(self._images["bar"].image, (2, 2))
 
130
            self.image.set_clip(None)
 
131
 
 
132
    def pulse(self):
 
133
        """
 
134
        Moves the activity mode throbber.
 
135
 
 
136
        The throbber will move for the number of seconds described by the
 
137
        pulse_duration config argument.
 
138
 
 
139
        Note: This will cause the Widget to change to activity mode if it
 
140
        was in percent mode before.
 
141
 
 
142
        """
 
143
        if not self._activity_mode:
 
144
            self._activity_mode = True
 
145
            bar_rect = (0, 0, self.rect.w * self._bar_fraction, self.rect.h)
 
146
            draw.rect(self.image, (100, 100, 100),
 
147
                      (0, 0, self.rect.w, self.rect.h))
 
148
            draw.rect(self.image, (240, 240, 240),
 
149
                      (1, 1, self.rect.w - 2, self.rect.h - 2))
 
150
            self._images["throbber"]._show = True
 
151
        self._throbber_move_timer = self._settings["pulse_duration"] * 1000
 
152
 
 
153
    @property
 
154
    def fraction(self):
 
155
        """Returns the current fraction the bar is at as a float."""
 
156
        return self._bar_fraction
 
157
 
 
158
    def set_fraction(self, fraction):
 
159
        """
 
160
        Sets the fraction the bar should be as a float.
 
161
 
 
162
        Note: This will cause the widget to change to percent mode if it
 
163
        was in activity mode before.
 
164
        """
 
165
        if self._activity_mode:
 
166
            self._activity_mode = False
 
167
            self._images["throbber"]._show = False
 
168
        self._bar_fraction = min(max(fraction, 0.), 1.)