Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/sugar/graphics/alert.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/sugar/graphics/alert.py')
-rw-r--r--src/sugar/graphics/alert.py436
1 files changed, 436 insertions, 0 deletions
diff --git a/src/sugar/graphics/alert.py b/src/sugar/graphics/alert.py
new file mode 100644
index 0000000..2c3c4ca
--- /dev/null
+++ b/src/sugar/graphics/alert.py
@@ -0,0 +1,436 @@
+"""
+Alerts appear at the top of the body of your activity.
+
+At a high level, Alert and its different variations (TimeoutAlert,
+ConfirmationAlert, etc.) have a title, an alert message and then several
+buttons that the user can click. The Alert class will pass "response" events
+to your activity when any of these buttons are clicked, along with a
+response_id to help you identify what button was clicked.
+
+
+Examples
+--------
+create a simple alert message.
+
+.. code-block:: python
+ from sugar.graphics.alert import Alert
+ ...
+ # Create a new simple alert
+ alert = Alert()
+ # Populate the title and text body of the alert.
+ alert.props.title=_('Title of Alert Goes Here')
+ alert.props.msg = _('Text message of alert goes here')
+ # Call the add_alert() method (inherited via the sugar.graphics.Window
+ # superclass of Activity) to add this alert to the activity window.
+ self.add_alert(alert)
+ alert.show()
+
+STABLE.
+"""
+# Copyright (C) 2007, One Laptop Per Child
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+import gettext
+
+import gtk
+import gobject
+import hippo
+import math
+
+from sugar.graphics import style
+from sugar.graphics.icon import Icon
+
+_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
+
+class Alert(gtk.EventBox):
+ """
+ UI interface for Alerts
+
+ Alerts are used inside the activity window instead of being a
+ separate popup window. They do not hide canvas content. You can
+ use add_alert(widget) and remove_alert(widget) inside your activity
+ to add and remove the alert. The position of the alert is below the
+ toolbox or top in fullscreen mode.
+
+ Properties:
+ 'title': the title of the alert,
+ 'message': the message of the alert,
+ 'icon': the icon that appears at the far left
+
+ See __gproperties__
+
+ """
+
+ __gtype_name__ = 'SugarAlert'
+
+ __gsignals__ = {
+ 'response': (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, ([object]))
+ }
+
+ __gproperties__ = {
+ 'title' : (str, None, None, None,
+ gobject.PARAM_READWRITE),
+ 'msg' : (str, None, None, None,
+ gobject.PARAM_READWRITE),
+ 'icon' : (object, None, None,
+ gobject.PARAM_WRITABLE)
+ }
+
+ def __init__(self, **kwargs):
+
+ self._title = None
+ self._msg = None
+ self._icon = None
+ self._buttons = {}
+
+ self._hbox = gtk.HBox()
+ self._hbox.set_border_width(style.DEFAULT_SPACING)
+ self._hbox.set_spacing(style.DEFAULT_SPACING)
+
+ self._msg_box = gtk.VBox()
+ self._title_label = gtk.Label()
+ self._title_label.set_alignment(0, 0.5)
+ self._msg_box.pack_start(self._title_label, False)
+
+ self._msg_label = gtk.Label()
+ self._msg_label.set_alignment(0, 0.5)
+ self._msg_box.pack_start(self._msg_label, False)
+ self._hbox.pack_start(self._msg_box, False)
+
+ self._buttons_box = gtk.HButtonBox()
+ self._buttons_box.set_layout(gtk.BUTTONBOX_END)
+ self._buttons_box.set_spacing(style.DEFAULT_SPACING)
+ self._hbox.pack_start(self._buttons_box)
+
+ gobject.GObject.__init__(self, **kwargs)
+
+ self.set_visible_window(True)
+ self.add(self._hbox)
+ self._title_label.show()
+ self._msg_label.show()
+ self._buttons_box.show()
+ self._msg_box.show()
+ self._hbox.show()
+ self.show()
+
+ def do_set_property(self, pspec, value):
+ """
+ Set alert property
+
+ Parameters
+ ----------
+ pspec :
+
+ value :
+
+ Returns
+ -------
+ None
+
+ """
+ if pspec.name == 'title':
+ if self._title != value:
+ self._title = value
+ self._title_label.set_markup("<b>" + self._title + "</b>")
+ elif pspec.name == 'msg':
+ if self._msg != value:
+ self._msg = value
+ self._msg_label.set_markup(self._msg)
+ self._msg_label.set_line_wrap(True)
+ elif pspec.name == 'icon':
+ if self._icon != value:
+ self._icon = value
+ self._hbox.pack_start(self._icon, False)
+ self._hbox.reorder_child(self._icon, 0)
+
+ def do_get_property(self, pspec):
+ """
+ Get alert property
+
+ Parameters
+ ----------
+ pspec :
+ property for which the value will be returned
+
+ Returns
+ -------
+ value of the property specified
+
+ """
+ if pspec.name == 'title':
+ return self._title
+ elif pspec.name == 'msg':
+ return self._msg
+
+ def add_button(self, response_id, label, icon=None, position=-1):
+ """
+ Add a button to the alert
+
+ Parameters
+ ----------
+ response_id :
+ will be emitted with the response signal a response ID should one
+ of the pre-defined GTK Response Type Constants or a positive number
+ label :
+ that will occure right to the buttom
+
+ icon :
+ this can be a SugarIcon or a gtk.Image
+
+ postion :
+ the position of the button in the box (optional)
+
+ Returns
+ -------
+ button :gtk.Button
+
+ """
+ button = gtk.Button()
+ self._buttons[response_id] = button
+ if icon is not None:
+ button.set_image(icon)
+ button.set_label(label)
+ self._buttons_box.pack_start(button)
+ button.show()
+ button.connect('clicked', self.__button_clicked_cb, response_id)
+ if position != -1:
+ self._buttons_box.reorder_child(button, position)
+ return button
+
+ def remove_button(self, response_id):
+ """
+ Remove a button from the alert by the given response id
+
+ Parameters
+ ----------
+ response_id :
+
+ Returns
+ -------
+ None
+
+ """
+ self._buttons_box.remove(self._buttons[response_id])
+
+ def _response(self, response_id):
+ """Emitting response when we have a result
+
+ A result can be that a user has clicked a button or
+ a timeout has occured, the id identifies the button
+ that has been clicked and -1 for a timeout
+ """
+ self.emit('response', response_id)
+
+ def __button_clicked_cb(self, button, response_id):
+ self._response(response_id)
+
+
+class ConfirmationAlert(Alert):
+ """
+ This is a ready-made two button (Cancel,Ok) alert.
+
+ A confirmation alert is a nice shortcut from a standard Alert because it
+ comes with 'OK' and 'Cancel' buttons already built-in. When clicked, the
+ 'OK' button will emit a response with a response_id of gtk.RESPONSE_OK,
+ while the 'Cancel' button will emit gtk.RESPONSE_CANCEL.
+
+ Examples
+ --------
+
+ .. code-block:: python
+ from sugar.graphics.alert import ConfirmationAlert
+ ...
+ #### Method: _alert_confirmation, create a Confirmation alert (with ok
+ and cancel buttons standard)
+ # and add it to the UI.
+ def _alert_confirmation(self):
+ alert = ConfirmationAlert()
+ alert.props.title=_('Title of Alert Goes Here')
+ alert.props.msg = _('Text message of alert goes here')
+ alert.connect('response', self._alert_response_cb)
+ self.add_alert(alert)
+
+
+ #### Method: _alert_response_cb, called when an alert object throws a
+ response event.
+ def _alert_response_cb(self, alert, response_id):
+ #remove the alert from the screen, since either a response button
+ #was clicked or there was a timeout
+ self.remove_alert(alert)
+
+ #Do any work that is specific to the type of button clicked.
+ if response_id is gtk.RESPONSE_OK:
+ print 'Ok Button was clicked. Do any work upon ok here ...'
+ elif response_id is gtk.RESPONSE_CANCEL:
+ print 'Cancel Button was clicked.'
+
+ """
+
+ def __init__(self, **kwargs):
+ Alert.__init__(self, **kwargs)
+
+ icon = Icon(icon_name='dialog-cancel')
+ self.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), icon)
+ icon.show()
+
+ icon = Icon(icon_name='dialog-ok')
+ self.add_button(gtk.RESPONSE_OK, _('Ok'), icon)
+ icon.show()
+
+
+class _TimeoutIcon(hippo.CanvasText, hippo.CanvasItem):
+ """An icon with a round border"""
+ __gtype_name__ = 'AlertTimeoutIcon'
+
+ def __init__(self, **kwargs):
+ hippo.CanvasText.__init__(self, **kwargs)
+
+ self.props.orientation = hippo.ORIENTATION_HORIZONTAL
+ self.props.border_left = style.DEFAULT_SPACING
+ self.props.border_right = style.DEFAULT_SPACING
+
+ def do_paint_background(self, cr, damaged_box):
+ [width, height] = self.get_allocation()
+
+ xval = width * 0.5
+ yval = height * 0.5
+ radius = min(width * 0.5, height * 0.5)
+
+ hippo.cairo_set_source_rgba32(cr, self.props.background_color)
+ cr.arc(xval, yval, radius, 0, 2*math.pi)
+ cr.fill_preserve()
+
+
+class TimeoutAlert(Alert):
+ """
+ This is a ready-made two button (Cancel,Continue) alert
+
+ It times out with a positive response after the given amount of seconds.
+
+
+ Examples
+ --------
+
+ .. code-block:: python
+ from sugar.graphics.alert import TimeoutAlert
+ ...
+ #### Method: _alert_timeout, create a Timeout alert (with ok and cancel
+ buttons standard)
+ # and add it to the UI.
+ def _alert_timeout(self):
+ #Notice that for a TimeoutAlert, you pass the number of seconds in
+ #which to timeout. By default, this is 5.
+ alert = TimeoutAlert(10)
+ alert.props.title=_('Title of Alert Goes Here')
+ alert.props.msg = _('Text message of timeout alert goes here')
+ alert.connect('response', self._alert_response_cb)
+ self.add_alert(alert)
+
+ #### Method: _alert_response_cb, called when an alert object throws a
+ response event.
+ def _alert_response_cb(self, alert, response_id):
+ #remove the alert from the screen, since either a response button
+ #was clicked or there was a timeout
+ self.remove_alert(alert)
+
+ #Do any work that is specific to the type of button clicked.
+ if response_id is gtk.RESPONSE_OK:
+ print 'Ok Button was clicked. Do any work upon ok here ...'
+ elif response_id is gtk.RESPONSE_CANCEL:
+ print 'Cancel Button was clicked.'
+ elif response_id == -1:
+ print 'Timout occurred'
+
+ """
+
+ def __init__(self, timeout=5, **kwargs):
+ Alert.__init__(self, **kwargs)
+
+ self._timeout = timeout
+
+ icon = Icon(icon_name='dialog-cancel')
+ self.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), icon)
+ icon.show()
+
+ self._timeout_text = _TimeoutIcon(
+ text=self._timeout,
+ color=style.COLOR_BUTTON_GREY.get_int(),
+ background_color=style.COLOR_WHITE.get_int())
+ canvas = hippo.Canvas()
+ canvas.set_root(self._timeout_text)
+ canvas.show()
+ self.add_button(gtk.RESPONSE_OK, _('Continue'), canvas)
+
+ gobject.timeout_add_seconds(1, self.__timeout)
+
+ def __timeout(self):
+ self._timeout -= 1
+ self._timeout_text.props.text = self._timeout
+ if self._timeout == 0:
+ self._response(gtk.RESPONSE_OK)
+ return False
+ return True
+
+
+class NotifyAlert(Alert):
+ """
+ Timeout alert with only an "OK" button - just for notifications
+
+ Examples
+ --------
+
+ .. code-block:: python
+ from sugar.graphics.alert import NotifyAlert
+ ...
+ #### Method: _alert_notify, create a Notify alert (with only an 'OK'
+ button)
+ # and add it to the UI.
+ def _alert_notify(self):
+ #Notice that for a NotifyAlert, you pass the number of seconds in
+ #which to notify. By default, this is 5.
+ alert = NotifyAlert(10)
+ alert.props.title=_('Title of Alert Goes Here')
+ alert.props.msg = _('Text message of notify alert goes here')
+ alert.connect('response', self._alert_response_cb)
+ self.add_alert(alert)
+
+ """
+
+ def __init__(self, timeout=5, **kwargs):
+ Alert.__init__(self, **kwargs)
+
+ self._timeout = timeout
+
+ self._timeout_text = _TimeoutIcon(
+ text=self._timeout,
+ color=style.COLOR_BUTTON_GREY.get_int(),
+ background_color=style.COLOR_WHITE.get_int())
+ canvas = hippo.Canvas()
+ canvas.set_root(self._timeout_text)
+ canvas.show()
+ self.add_button(gtk.RESPONSE_OK, _('Ok'), canvas)
+
+ gobject.timeout_add(1000, self.__timeout)
+
+ def __timeout(self):
+ self._timeout -= 1
+ self._timeout_text.props.text = self._timeout
+ if self._timeout == 0:
+ self._response(gtk.RESPONSE_OK)
+ return False
+ return True