File: progress_bar.py

package info (click to toggle)
python-enaml 0.19.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,284 kB
  • sloc: python: 31,443; cpp: 4,499; makefile: 140; javascript: 68; lisp: 53; sh: 20
file content (146 lines) | stat: -rw-r--r-- 5,101 bytes parent folder | download
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
#------------------------------------------------------------------------------
# Copyright (c) 2013-2025, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
#------------------------------------------------------------------------------
from atom.api import Typed, ForwardTyped, Property, Bool, Int, set_default

from enaml.core.declarative import d_, observe

from .control import Control, ProxyControl


class ProxyProgressBar(ProxyControl):
    """ The abstract definition of a proxy ProgressBar object.

    """
    #: A reference to the ProgressBar declaration.
    declaration = ForwardTyped(lambda: ProgressBar)

    def set_minimum(self, minimum):
        raise NotImplementedError

    def set_maximum(self, maximum):
        raise NotImplementedError

    def set_value(self, value):
        raise NotImplementedError

    def set_text_visible(self, visible):
        raise NotImplementedError


class ProgressBar(Control):
    """ A control which displays a value as a ticking progress bar.

    """
    #: The minimum progress value. If the minimum value is changed such
    #: that it becomes greater than the current value or the maximum
    #: value, then those values will be adjusted. The default is 0.
    minimum = d_(Int(0))

    #: The maximum progress value. If the maximum value is changed such
    #: that it becomes smaller than the current value or the minimum
    #: value, then those values will be adjusted. The default is 100.
    maximum = d_(Int(100))

    #: The position value of the Slider. The value will be clipped to
    #: always fall between the minimum and maximum.
    value = d_(Int(0))

    #: A read only cached property which computes the integer percentage.
    percentage = d_(Property(cached=True), writable=False)

    #: Whether or not to display progress percentage on the control.
    #: This may not be supported by all toolkits and platforms.
    text_visible = d_(Bool(False))

    #: How strongly a component hugs it's content. ProgressBars expand
    #: to fill the available horizontal space by default.
    hug_width = set_default('ignore')

    #: A reference to the ProxyProgressBar object.
    proxy = Typed(ProxyProgressBar)

    @percentage.getter
    def get_percentage(self):
        """ The getter function for the read only percentage property.

        """
        minimum = self.minimum
        maximum = self.maximum
        value = self.value
        dy = maximum - minimum
        if dy == 0:
            res = 0
        elif value == maximum:
            res = 100
        else:
            dx = float(value - minimum)
            res = int(round(100.0 * dx / dy))
            # We already excluded the case where the value was exactly
            # the maximum, so we can't really be at 100%, so round this
            # down to 99% if necessary.
            res = min(res, 99)
        return res

    #--------------------------------------------------------------------------
    # Observers
    #--------------------------------------------------------------------------
    @observe('minimum', 'maximum', 'value', 'text_visible')
    def _update_proxy(self, change):
        """ An observer which sends state change to the proxy.

        This observer also resets the 'percentage' property.

        """
        # The superclass handler implementation is sufficient.
        super(ProgressBar, self)._update_proxy(change)

    @observe('minimum', 'maximum', 'value')
    def _reset_percentage(self, change):
        """ An observer which resets the percentage property.

        """
        if change['type'] == 'update':
            self.get_member('percentage').reset(self)

    #--------------------------------------------------------------------------
    # PostSetAttr Handlers
    #--------------------------------------------------------------------------
    def _post_setattr_minimum(self, old, new):
        """ Post setattr the minimum value for the progress bar.

        If the new minimum is greater than the current value or maximum,
        those values are adjusted up.

        """
        if new > self.maximum:
            self.maximum = new
        if new > self.value:
            self.value = new

    def _post_setattr_maximum(self, old, new):
        """ Post setattr the maximum value for the progress bar.

        If the new maximum is less than the current value or the minimum,
        those values are adjusted down.

        """
        if new < self.minimum:
            self.minimum = new
        if new < self.value:
            self.value = new

    #--------------------------------------------------------------------------
    # PostValidate Handlers
    #--------------------------------------------------------------------------
    def _post_validate_value(self, old, new):
        """ Post validate the value for the progress bar.

        The value is clipped to minimum and maximum bounds.

        """
        return max(self.minimum, min(new, self.maximum))