~ubuntu-branches/ubuntu/karmic/sugar-toolkit/karmic

« back to all changes in this revision

Viewing changes to src/sugar/graphics/alert.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-08-07 19:43:09 UTC
  • mfrom: (0.1.2 lenny) (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080807194309-03302c4lj0j0ipze
Tags: 0.82.0-1
* New upstream release.
* Unfuzz patch 2991.
* Add DEB_MAINTAINER_MODE in debian/rules (thanks to Romain Beauxis).
* Update copyright-hints.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2007, One Laptop Per Child
 
2
#
 
3
# This library is free software; you can redistribute it and/or
 
4
# modify it under the terms of the GNU Lesser General Public
 
5
# License as published by the Free Software Foundation; either
 
6
# version 2 of the License, or (at your option) any later version.
 
7
#
 
8
# This library is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
# Lesser General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU Lesser General Public
 
14
# License along with this library; if not, write to the
 
15
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
16
# Boston, MA 02111-1307, USA.
 
17
 
 
18
import gettext
 
19
 
 
20
import gtk
 
21
import gobject
 
22
import hippo
 
23
import math
 
24
        
 
25
from sugar.graphics import style
 
26
from sugar.graphics.icon import Icon
 
27
 
 
28
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
 
29
 
 
30
class Alert(gtk.EventBox):
 
31
    """UI interface for Alerts
 
32
 
 
33
    Alerts are used inside the activity window instead of being a
 
34
    separate popup window. They do not hide canvas content. You can
 
35
    use add_alert(widget) and remove_alert(widget) inside your activity
 
36
    to add and remove the alert. The position of the alert is below the
 
37
    toolbox or top in fullscreen mode.
 
38
 
 
39
    Properties:
 
40
        'title': the title of the alert,
 
41
        'message': the message of the alert,
 
42
        'icon': the icon that appears at the far left
 
43
    See __gproperties__
 
44
    """
 
45
 
 
46
    __gtype_name__ = 'SugarAlert'
 
47
 
 
48
    __gsignals__ = {
 
49
        'response': (gobject.SIGNAL_RUN_FIRST,
 
50
                        gobject.TYPE_NONE, ([object]))
 
51
        }
 
52
 
 
53
    __gproperties__ = {
 
54
        'title'  : (str, None, None, None,
 
55
                    gobject.PARAM_READWRITE),
 
56
        'msg'    : (str, None, None, None,
 
57
                    gobject.PARAM_READWRITE),
 
58
        'icon'   : (object, None, None,
 
59
                    gobject.PARAM_WRITABLE)
 
60
        }
 
61
 
 
62
    def __init__(self, **kwargs):
 
63
 
 
64
        self._title = None
 
65
        self._msg = None
 
66
        self._icon = None
 
67
        self._buttons = {}
 
68
 
 
69
        self._hbox = gtk.HBox()
 
70
        self._hbox.set_border_width(style.DEFAULT_SPACING)
 
71
        self._hbox.set_spacing(style.DEFAULT_SPACING)
 
72
 
 
73
        self._msg_box = gtk.VBox()
 
74
        self._title_label = gtk.Label()
 
75
        self._title_label.set_alignment(0, 0.5)
 
76
        self._msg_box.pack_start(self._title_label, False)
 
77
 
 
78
        self._msg_label = gtk.Label()
 
79
        self._msg_label.set_alignment(0, 0.5)
 
80
        self._msg_box.pack_start(self._msg_label, False)
 
81
        self._hbox.pack_start(self._msg_box, False)
 
82
        
 
83
        self._buttons_box = gtk.HButtonBox()
 
84
        self._buttons_box.set_layout(gtk.BUTTONBOX_END)
 
85
        self._buttons_box.set_spacing(style.DEFAULT_SPACING)
 
86
        self._hbox.pack_start(self._buttons_box)
 
87
        
 
88
        gtk.EventBox.__init__(self, **kwargs)        
 
89
 
 
90
        self.set_visible_window(True)        
 
91
        self.add(self._hbox)        
 
92
        self._title_label.show()
 
93
        self._msg_label.show()
 
94
        self._buttons_box.show()
 
95
        self._msg_box.show()
 
96
        self._hbox.show()
 
97
        self.show()
 
98
        
 
99
    def do_set_property(self, pspec, value):        
 
100
        if pspec.name == 'title':
 
101
            if self._title != value:
 
102
                self._title = value
 
103
                self._title_label.set_markup("<b>" + self._title + "</b>")
 
104
        elif pspec.name == 'msg':
 
105
            if self._msg != value:
 
106
                self._msg = value
 
107
                self._msg_label.set_markup(self._msg)
 
108
        elif pspec.name == 'icon':
 
109
            if self._icon != value:
 
110
                self._icon = value
 
111
                self._hbox.pack_start(self._icon, False)
 
112
                self._hbox.reorder_child(self._icon, 0)
 
113
 
 
114
    def do_get_property(self, pspec):
 
115
        if pspec.name == 'title':
 
116
            return self._title
 
117
        elif pspec.name == 'msg':
 
118
            return self._msg
 
119
 
 
120
    def add_button(self, response_id, label, icon=None, position=-1):
 
121
        """Add a button to the alert
 
122
 
 
123
        response_id: will be emitted with the response signal
 
124
                     a response ID should one of the pre-defined
 
125
                     GTK Response Type Constants or a positive number
 
126
        label: that will occure right to the buttom
 
127
        icon: this can be a SugarIcon or a gtk.Image
 
128
        position: the position of the button in the box (optional)
 
129
        """
 
130
        button = gtk.Button()
 
131
        self._buttons[response_id] = button
 
132
        if icon is not None:
 
133
            button.set_image(icon)
 
134
        button.set_label(label)
 
135
        self._buttons_box.pack_start(button)
 
136
        button.show()
 
137
        button.connect('clicked', self.__button_clicked_cb, response_id)
 
138
        if position != -1:
 
139
            self._buttons_box.reorder_child(button, position)
 
140
        return button
 
141
 
 
142
    def remove_button(self, response_id):
 
143
        """Remove a button from the alert by the given response id"""
 
144
        self._buttons_box.remove(self._buttons[response_id])
 
145
 
 
146
    def _response(self, response_id):
 
147
        """Emitting response when we have a result
 
148
 
 
149
        A result can be that a user has clicked a button or
 
150
        a timeout has occured, the id identifies the button
 
151
        that has been clicked and -1 for a timeout
 
152
        """
 
153
        self.emit('response', response_id)
 
154
 
 
155
    def __button_clicked_cb(self, button, response_id):
 
156
        self._response(response_id)
 
157
 
 
158
 
 
159
class ConfirmationAlert(Alert):
 
160
    """This is a ready-made two button (Cancel,Ok) alert"""
 
161
 
 
162
    def __init__(self, **kwargs):
 
163
        Alert.__init__(self, **kwargs)
 
164
 
 
165
        icon = Icon(icon_name='dialog-cancel')
 
166
        self.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), icon)
 
167
        icon.show()
 
168
 
 
169
        icon = Icon(icon_name='dialog-ok')
 
170
        self.add_button(gtk.RESPONSE_OK, _('Ok'), icon)
 
171
        icon.show()
 
172
 
 
173
 
 
174
class _TimeoutIcon(hippo.CanvasText, hippo.CanvasItem):
 
175
    """An icon with a round border"""
 
176
    __gtype_name__ = 'AlertTimeoutIcon'
 
177
 
 
178
    def __init__(self, **kwargs):
 
179
        hippo.CanvasText.__init__(self, **kwargs)
 
180
        
 
181
        self.props.orientation = hippo.ORIENTATION_HORIZONTAL
 
182
        self.props.border_left = style.DEFAULT_SPACING
 
183
        self.props.border_right = style.DEFAULT_SPACING
 
184
            
 
185
    def do_paint_background(self, cr, damaged_box):
 
186
        [width, height] = self.get_allocation()
 
187
        
 
188
        xval = width * 0.5
 
189
        yval = height * 0.5
 
190
        radius = min(width * 0.5, height * 0.5)         
 
191
        
 
192
        hippo.cairo_set_source_rgba32(cr, self.props.background_color)
 
193
        cr.arc(xval, yval, radius, 0, 2*math.pi)        
 
194
        cr.fill_preserve()    
 
195
 
 
196
 
 
197
class TimeoutAlert(Alert):
 
198
    """This is a ready-made two button (Cancel,Continue) alert
 
199
 
 
200
    It times out with a positive reponse after the given amount of seconds.
 
201
    """
 
202
 
 
203
    def __init__(self, timeout=5, **kwargs):
 
204
        Alert.__init__(self, **kwargs)
 
205
 
 
206
        self._timeout = timeout
 
207
        
 
208
        icon = Icon(icon_name='dialog-cancel')
 
209
        self.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), icon)
 
210
        icon.show()
 
211
        
 
212
        self._timeout_text = _TimeoutIcon(
 
213
            text=self._timeout,
 
214
            color=style.COLOR_BUTTON_GREY.get_int(),
 
215
            background_color=style.COLOR_WHITE.get_int())    
 
216
        canvas = hippo.Canvas()
 
217
        canvas.set_root(self._timeout_text)
 
218
        canvas.show()                       
 
219
        self.add_button(gtk.RESPONSE_OK, _('Continue'), canvas)
 
220
 
 
221
        gobject.timeout_add(1000, self.__timeout)
 
222
        
 
223
    def __timeout(self):
 
224
        self._timeout -= 1
 
225
        self._timeout_text.props.text = self._timeout
 
226
        if self._timeout == 0:
 
227
            self._response(gtk.RESPONSE_OK)
 
228
            return False
 
229
        return True
 
230
 
 
231
 
 
232
class NotifyAlert(Alert):
 
233
    """Timeout alert with only an "OK" button - just for notifications"""
 
234
 
 
235
    def __init__(self, timeout=5, **kwargs):
 
236
        Alert.__init__(self, **kwargs)
 
237
 
 
238
        self._timeout = timeout
 
239
 
 
240
        self._timeout_text = _TimeoutIcon(
 
241
            text=self._timeout,
 
242
            color=style.COLOR_BUTTON_GREY.get_int(),
 
243
            background_color=style.COLOR_WHITE.get_int())
 
244
        canvas = hippo.Canvas()
 
245
        canvas.set_root(self._timeout_text)
 
246
        canvas.show()
 
247
        self.add_button(gtk.RESPONSE_OK, _('Ok'), canvas)
 
248
 
 
249
        gobject.timeout_add(1000, self.__timeout)
 
250
 
 
251
    def __timeout(self):
 
252
        self._timeout -= 1
 
253
        self._timeout_text.props.text = self._timeout
 
254
        if self._timeout == 0:
 
255
            self._response(gtk.RESPONSE_OK)
 
256
            return False
 
257
        return True