From d3a006f11993435cf9a9e14b59ff626bfa09e7ba Mon Sep 17 00:00:00 2001 From: dave Date: Tue, 27 Oct 2009 00:31:16 +0000 Subject: added new actions and events --- diff --git a/addons/changecolor.py b/addons/changecolor.py new file mode 100644 index 0000000..ae20e8a --- /dev/null +++ b/addons/changecolor.py @@ -0,0 +1,66 @@ +# Copyright (C) 2009, Tutorius.org +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +from sugar.tutorius.actions import Action + +class ChangeColor(Action): + + def __init__(self, target, color, state): + """Constructor - Change a widget color + @param target: the widget for which you want to change the color + @param color: the color you want the widget to be colorized with \ + (string)(ex: "#ffff00000000", or "red") + @param: state of the widget when you want a color change \ + (ex: gtk.STATE_NORMAL) + @return : nothing! + """ + Action.__init__(self) + self._target = target + self._state = state + #We have to get the initial color in the sugar rc theme + current_style = self._target.rc_get_style() + + self._old_color = current_style.bg[self._state] + self._new_color = gtk.gdk.color_parse(color) + + def do(self): + """Action do + Change the color of the targeted widget with the chosen color + """ + self._target.modify_bg(state,self._new_color) + + def undo(self): + """Action undo + Go back to the original color + """ + self._target.modify_bg(state,self._old_color) + + def enter_editmode(self, *args): + """ + Enters edit mode. The action should display itself in some way, + without affecting the currently running application. + """ + self._target.modify_bg(state,self._new_color) + + def exit_editmode(self, *args): + self._target.modify_bg(state,self._old_color) + +__action__ = { + "name" : "ChangeColor", + "display_name" : "Change widget color", + "icon" : "message-bubble", + "class" : ChangeColor +} + diff --git a/addons/intromessage.py b/addons/intromessage.py new file mode 100644 index 0000000..f4f19a9 --- /dev/null +++ b/addons/intromessage.py @@ -0,0 +1,161 @@ +# Copyright (C) 2009, Tutorius.org +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import logging + +import gobject + +import gtk, gtk.gdk + +from sugar.tutorius.filters import EventFilter +from sugar.tutorius.properties import TStringProperty, TArrayProperty, TIntProperty +from sugar.tutorius import overlayer +from sugar.tutorius.services import ObjectStore + +from sugar import profile + +# for easy profile access +xo_line_color = profile.get_color().get_stroke_color() +xo_fill_color = profile.get_color().get_fill_color() + +class IntroMessage(EventFilter): + """ + IntroMessage is a special EventFilter that uses gobject + start button to trigger a state change after user click on it. + It must be used inside a gobject main loop to work. + """ + message = TStringProperty("Message") + + def __init__(self, message=None): + """Constructor. + + @param message message to display + """ + super(IntroMessage,self).__init__() + + if message: + self.message = message + + self.overlay = None + self.msgnext = None + + def install_handlers(self, callback, **kwargs): + """install_handlers creates the introduction message and shows it""" + super(IntroMessage,self).install_handlers(callback, **kwargs) + + # get or inject overlayer + self.overlay = ObjectStore().activity._overlayer + + if not self.overlay: + self.overlay = ObjectStore().activity._overlayer + + self.msgnext = None + + #Create the introduction message + if not self.msgnext: + # create an eventbox + self.msgnext = gtk.EventBox() + self.msgnext.set_visible_window(True) + + # create a vbox + self.box = gtk.VBox() + + # get position (center of screen) + screen = gtk.gdk.Screen() + scr_width_half = screen.get_width()/2 #self.overlayer.get_screen().get_width()/2 + scr_height_half = screen.get_height()/2 #self.overlayer.get_screen().get_height()/2 + + # get user name + name = profile.get_nick_name() + if not name or not len(name): + name = "User" + + # create a label + self._label = gtk.Label("Hello " + name + "!\n\n" + self.message) + self._text = "%s" % self.message + self._label.set_markup(self._text) + self._label.set_line_wrap(True) + + self._colortext = gtk.gdk.color_parse("white") + self._label.modify_fg(gtk.STATE_NORMAL, self._colortext) + self._label.modify_fg(gtk.STATE_PRELIGHT, self._colortext) + self._label.modify_fg(gtk.STATE_ACTIVE, self._colortext) + self._label.modify_fg(gtk.STATE_INSENSITIVE, self._colortext) + + self._label.show() + + # create a hbox (holding button) + self._hbox = gtk.HBox() + + # create a button inside hbox + self._btnnext = gtk.Button("START") + self._btnnext.connect("clicked", self.btnnext_clicked) + + self._colorbtn = gtk.gdk.color_parse(xo_fill_color) + + self._btnnext.modify_bg(gtk.STATE_NORMAL, self._colorbtn) + self._btnnext.modify_bg(gtk.STATE_PRELIGHT, self._colorbtn) + self._btnnext.modify_bg(gtk.STATE_ACTIVE, self._colorbtn) + + self._btnnext.show() + + self._hbox.pack_end(self._btnnext, expand=False) + + self._hbox.show() + + self.box.pack_start(self._label, expand=True) + self.box.pack_start(self._hbox, expand=True) + + self.box.show() + + self.msgnext.add(self.box) + + self._colormsgnext = gtk.gdk.color_parse(xo_fill_color) + self.msgnext.modify_bg(gtk.STATE_NORMAL, self._colormsgnext) + + # add space around minimum need size + wid_width, wid_height = self.msgnext.size_request() + self.msgnext.set_size_request(wid_width+40, wid_height+40) + + self.msgnext.show() + + # set position + wid_width, wid_height = self.msgnext.size_request() + self.position = (scr_width_half-wid_width/2, scr_height_half-wid_height/2) + x, y = self.position + + self.overlay.put(self.msgnext, x, y) + + self.overlay.queue_draw() + + def remove_handlers(self): + """remove handler removes the introduction message""" + super(IntroMessage,self).remove_handlers() + + if self.msgnext: + self.msgnext.destroy() + self.msgnext = None + + def btnnext_clicked(self, widget): + self.do_callback() + +__event__ = { + "name" : "IntroMessage", + "display_name" : "Introduction message", + "icon" : "message-bubble", + "class" : IntroMessage, + "mandatory_props" : ["message"] +} diff --git a/addons/messagebuttonnext.py b/addons/messagebuttonnext.py new file mode 100644 index 0000000..ed6dd9d --- /dev/null +++ b/addons/messagebuttonnext.py @@ -0,0 +1,158 @@ +# Copyright (C) 2009, Tutorius.org +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import logging + +import gobject + +import gtk, gtk.gdk + +from sugar.tutorius.filters import EventFilter +from sugar.tutorius.properties import TStringProperty, TArrayProperty, TIntProperty +from sugar.tutorius import overlayer +from sugar.tutorius.services import ObjectStore + +from sugar import profile + +# for easy profile access +xo_line_color = profile.get_color().get_stroke_color() +xo_fill_color = profile.get_color().get_fill_color() + +class MessageButtonNext(EventFilter): + """ + MessageButtonNext is a special EventFilter that uses gobject + next button to trigger a state change after user click on it. + It must be used inside a gobject main loop to work. + """ + message = TStringProperty("Message") + + # Create the position as an array of fixed-size 2 + position = TArrayProperty((0,0), 2, 2) + + def __init__(self, message=None, position=None): + """Constructor. + + @param message message to display + @param position message position + """ + super(MessageButtonNext,self).__init__() + + if position: + self.position = position + else: + self.position = (300, 200) + + if message: + self.message = message + + self.overlay = None + self.msgnext = None + + def install_handlers(self, callback, **kwargs): + """install_handlers creates the message button next and shows it""" + super(MessageButtonNext,self).install_handlers(callback, **kwargs) + + x, y = self.position + + # get or inject overlayer + self.overlay = ObjectStore().activity._overlayer + + if not self.overlay: + self.overlay = ObjectStore().activity._overlayer + + self.msgnext = None + + #Create the message button next + if not self.msgnext: + # create an eventbox + self.msgnext = gtk.EventBox() + self.msgnext.set_visible_window(True) + + # create a vbox + self.box = gtk.VBox() + + # create a label + self._label = gtk.Label(self.message) + self._text = "%s" % self.message + self._label.set_markup(self._text) + self._label.set_line_wrap(True) + + self._colortext = gtk.gdk.color_parse("white") + self._label.modify_fg(gtk.STATE_NORMAL, self._colortext) + self._label.modify_fg(gtk.STATE_PRELIGHT, self._colortext) + self._label.modify_fg(gtk.STATE_ACTIVE, self._colortext) + self._label.modify_fg(gtk.STATE_INSENSITIVE, self._colortext) + + self._label.show() + + # create a hbox (holding button) + self._hbox = gtk.HBox() + + # create a button inside hbox + self._btnnext = gtk.Button("NEXT") + self._btnnext.connect("clicked", self.btnnext_clicked) + + self._colorbtn = gtk.gdk.color_parse(xo_fill_color) + + self._btnnext.modify_bg(gtk.STATE_NORMAL, self._colorbtn) + self._btnnext.modify_bg(gtk.STATE_PRELIGHT, self._colorbtn) + self._btnnext.modify_bg(gtk.STATE_ACTIVE, self._colorbtn) + + self._btnnext.show() + + self._hbox.pack_end(self._btnnext, expand=False) + + self._hbox.show() + + self.box.pack_start(self._label, expand=True) + self.box.pack_start(self._hbox, expand=True) + + self.box.show() + + self.msgnext.add(self.box) + + self._colormsgnext = gtk.gdk.color_parse(xo_fill_color) + self.msgnext.modify_bg(gtk.STATE_NORMAL, self._colormsgnext) + + # add space around minimum need size + wid_width, wid_height = self.msgnext.size_request() + + self.msgnext.set_size_request(wid_width+40, wid_height+40) + + self.msgnext.show() + + self.overlay.put(self.msgnext, x, y) + + self.overlay.queue_draw() + + def remove_handlers(self): + """remove handler removes the message button next""" + super(MessageButtonNext,self).remove_handlers() + + if self.msgnext: + self.msgnext.destroy() + self.msgnext = None + + def btnnext_clicked(self, widget): + self.do_callback() + +__event__ = { + "name" : "MessageButtonNext", + "display_name" : "Message button next", + "icon" : "message-bubble", + "class" : MessageButtonNext, + "mandatory_props" : ["message"] +} diff --git a/addons/openactivity.py b/addons/openactivity.py new file mode 100644 index 0000000..1b4d4b7 --- /dev/null +++ b/addons/openactivity.py @@ -0,0 +1,180 @@ +# Copyright (C) 2009, Tutorius.org +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import logging + +import gobject + +import gtk, gtk.gdk + +import os +import dbus + +from sugar.tutorius.filters import EventFilter +from sugar.tutorius.properties import TStringProperty, TArrayProperty, TIntProperty +from sugar.tutorius import overlayer +from sugar.tutorius.services import ObjectStore + +from sugar import profile + +from sugar.activity import activityfactory +from sugar.bundle.activitybundle import ActivityBundle + +# for easy profile access +xo_line_color = profile.get_color().get_stroke_color() +xo_fill_color = profile.get_color().get_fill_color() + +class OpenActivity(EventFilter): + """ + IntroMessage is a special EventFilter that uses gobject + start button to trigger a state change after user click on it. + It must be used inside a gobject main loop to work. + """ + message = TStringProperty("Message") + + def __init__(self, message=None): + """Constructor. + + @param message message to display + """ + super(OpenActivity,self).__init__() + + if message: + self.message = message + + self.overlay = None + self.msgnext = None + + def install_handlers(self, callback, **kwargs): + """install_handlers creates the open activity message and shows it""" + super(OpenActivity,self).install_handlers(callback, **kwargs) + + # get or inject overlayer + self.overlay = ObjectStore().activity._overlayer + + if not self.overlay: + self.overlay = ObjectStore().activity._overlayer + + self.msgnext = None + + #Create the open activity message + if not self.msgnext: + # create an eventbox + self.msgnext = gtk.EventBox() + self.msgnext.set_visible_window(True) + + # create a vbox + self.box = gtk.VBox() + + # get position (center of screen) + screen = gtk.gdk.Screen() + scr_width_half = screen.get_width()/2 #self.overlayer.get_screen().get_width()/2 + scr_height_half = screen.get_height()/2 #self.overlayer.get_screen().get_height()/2 + + # get user name + name = profile.get_nick_name() + if not name or not len(name): + name = "User" + + # create a label + self._label = gtk.Label("Hello " + name + "!\n\n" + self.message) + self._text = "%s" % self.message + self._label.set_markup(self._text) + self._label.set_line_wrap(True) + + self._colortext = gtk.gdk.color_parse("white") + self._label.modify_fg(gtk.STATE_NORMAL, self._colortext) + self._label.modify_fg(gtk.STATE_PRELIGHT, self._colortext) + self._label.modify_fg(gtk.STATE_ACTIVE, self._colortext) + self._label.modify_fg(gtk.STATE_INSENSITIVE, self._colortext) + + self._label.show() + + # create a hbox (holding button) + self._hbox = gtk.HBox() + + # create a button inside hbox + self._btnnext = gtk.Button("OPEN") + self._btnnext.connect("clicked", self.btnnext_clicked) + + self._colorbtn = gtk.gdk.color_parse(xo_fill_color) + + self._btnnext.modify_bg(gtk.STATE_NORMAL, self._colorbtn) + self._btnnext.modify_bg(gtk.STATE_PRELIGHT, self._colorbtn) + self._btnnext.modify_bg(gtk.STATE_ACTIVE, self._colorbtn) + + self._btnnext.show() + + self._hbox.pack_end(self._btnnext, expand=False) + + self._hbox.show() + + self.box.pack_start(self._label, expand=True) + self.box.pack_start(self._hbox, expand=True) + + self.box.show() + + self.msgnext.add(self.box) + + self._colormsgnext = gtk.gdk.color_parse(xo_fill_color) + self.msgnext.modify_bg(gtk.STATE_NORMAL, self._colormsgnext) + + # add space around minimum need size + wid_width, wid_height = self.msgnext.size_request() + self.msgnext.set_size_request(wid_width+40, wid_height+40) + + self.msgnext.show() + + # set position + wid_width, wid_height = self.msgnext.size_request() + self.position = (scr_width_half-wid_width/2, scr_height_half-wid_height/2) + x, y = self.position + + self.overlay.put(self.msgnext, x, y) + + self.overlay.queue_draw() + + def remove_handlers(self): + """remove handler removes the open activity message""" + super(OpenActivity,self).remove_handlers() + + if self.msgnext: + self.msgnext.destroy() + self.msgnext = None + + def btnnext_clicked(self, widget): + # temporary activity name hardcoded + activity_name = "org.laptop.Terminal" + + bus = dbus.SessionBus() + proxy = bus.get_object('org.laptop.Shell', '/org/laptop/Shell') + path = dbus.Interface(proxy, 'org.laptop.Shell').GetBundlePath(activity_name) + if not path: + print 'Cannot find %s bundle.' % activity_name + else: + activity = ActivityBundle(path) + activityfactory.create(activity) + + self.do_callback() + +__event__ = { + "name" : "OpenActivity", + "display_name" : "Open activity message", + "icon" : "message-bubble", + "class" : OpenActivity, + "mandatory_props" : ["message"] +} + diff --git a/addons/playsound.py b/addons/playsound.py new file mode 100644 index 0000000..b657c8a --- /dev/null +++ b/addons/playsound.py @@ -0,0 +1,50 @@ +# Copyright (C) 2009, Tutorius.org +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +from sugar.tutorius.actions import Action + +class PlaySound(Action): + + def __init__(self, target): + """Constructor + @param target: name of the sound you want to play + """ + Action.__init__(self) + self._target = target + + def do(self): + """Action do + Play a sound in the mixer + """ + pygame.mixer.init() + #We wait for a "place" in the mixer + if not pygame.mixer.music.get_busy(): + pygame.mixer.music.load(self._target) + pygame.mixer.music.play() + + def undo(self): + """Action undo + Quit the mixer + """ + pygame.mixer.music.stop() + pygame.mixer.quit() + +__action__ = { + "name" : "PlaySound", + "display_name" : "Play sound", + "icon" : "message-bubble", + "class" : PlaySound +} + diff --git a/addons/smiley.py b/addons/smiley.py new file mode 100644 index 0000000..b50de0c --- /dev/null +++ b/addons/smiley.py @@ -0,0 +1,82 @@ +# Copyright (C) 2009, Tutorius.org +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +from sugar.tutorius.actions import Action +from sugar.tutorius import overlayer +from sugar.tutorius.services import ObjectStore + +class Smiley(Action): + + def __init__(self): + """ + Draw a big smiley at the center of the screen + """ + Action.__init__(self) + + self.overlay = None + self._smiley = None + + def do(self): + """ + Do + """ + # get or inject overlayer + self.overlay = ObjectStore().activity._overlayer + # FIXME: subwindows, are left to overlap this. This behaviour is + # undesirable. subwindows (i.e. child of top level windows) should be + # handled either by rendering over them, or by finding different way to + # draw the overlay. + + if not self.overlay: + self.overlay = ObjectStore().activity._overlayer + if not self._smiley: + self._smiley = overlayer.Smiley() + self._smiley.show() + self.overlay.put(self._smiley, 0, 0) + self.overlay.queue_draw() + + def undo(self): + """ + Undo + """ + if self._smiley: + self._smiley.destroy() + self._smiley = None + + def enter_editmode(self, *args): + """ + Enters edit mode. The action should display itself in some way, + without affecting the currently running application. + """ + if not self.overlay: + self.overlay = ObjectStore().activity._overlayer + + self._smiley = overlayer.Smiley() + self.overlay.put(self._smiley, 0, 0) + self._smiley.show() + + def exit_editmode(self, *args): + if self._smiley: + self.overlay.remove(self._smiley) + self._smiley = None + self.overlay = None + +__action__ = { + "name" : "Smiley", + "display_name" : "Big smiley", + "icon" : "message-bubble", + "class" : Smiley +} + diff --git a/data/icons/smiley.svg b/data/icons/smiley.svg new file mode 100644 index 0000000..9756352 --- /dev/null +++ b/data/icons/smiley.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/tutorius/overlayer.py b/tutorius/overlayer.py index 0a3d542..7ebe347 100644 --- a/tutorius/overlayer.py +++ b/tutorius/overlayer.py @@ -58,7 +58,7 @@ class Overlayer(gtk.Layout): @param overlayed widget to be overlayed. Will be resized to full size. """ def __init__(self, overlayed=None): - gtk.Layout.__init__(self) + super(Overlayer, self).__init__() self._overlayed = overlayed if overlayed: @@ -83,7 +83,7 @@ class Overlayer(gtk.Layout): if hasattr(child, "draw_with_context"): # if the widget has the CanvasDrawable protocol, use it. child.no_expose = True - gtk.Layout.put(self, child, x, y) + super(Overlayer, self).put(child, x, y) # be sure to redraw or the overlay may not show self.queue_draw() @@ -151,6 +151,85 @@ class Overlayer(gtk.Layout): # some cases. self._overlayed.set_size_request(allocation.width, allocation.height) +class Smiley(gtk.Widget): + """ + Draw a smiley + """ + def __init__(self): + """ + Creates a new Smiley + """ + gtk.Widget.__init__(self) + + self.__realizer = self.connect_after("realize", self.do_realize_init) + self.connect("size-allocate", self.do_size_allocate_init) + + def draw_with_context(self, context): + # DRAW SMILEY + + scr_width_half = self.get_screen().get_width()/2 + scr_height_half = self.get_screen().get_height()/2 + + # face + context.set_source_rgb(1.0, 1.0, 0.0) # rgb + context.arc(scr_width_half, scr_height_half, 150, 0, 2 * 3.14159) + context.fill() + + # face stroke + context.set_source_rgb(0.0, 0.0, 0.0) # rgb + context.arc(scr_width_half, scr_height_half, 150, 0, 2 * 3.14159) + context.set_line_width(10) + context.stroke() + + # eye + context.set_source_rgb(0.0, 0.0, 0.0) # rgb + context.arc(scr_width_half-50, scr_height_half-40, 25, 0, 2 * 3.14159) + context.fill() + + # eye + context.set_source_rgb(0.0, 0.0, 0.0) # rgb + context.arc(scr_width_half+50, scr_height_half-40, 25, 0, 2 * 3.14159) + context.fill() + + # mouth + context.set_source_rgb(0.0, 0.0, 0.0) # rgb + context.arc(scr_width_half, scr_height_half+40, 60, 0, 3.14159) + context.set_line_width(10) + context.stroke() + + # END OF DRAW SMILEY + + def do_realize(self): + """ Setup gdk window creation. """ + self.set_flags(gtk.REALIZED | gtk.NO_WINDOW) + + self.window = self.get_parent_window() + if not isinstance(self.parent, Overlayer): + assert False, "%s should not realize" % type(self).__name__ + print "Danger, Will Robinson! Rectangle parent is not Overlayer" + + def do_realize_init(self, widget): + """ Setup gdk window creation. """ + self.set_flags(gtk.REALIZED | gtk.NO_WINDOW) + + self.window = self.get_parent_window() + if not isinstance(self.parent, Overlayer): + assert False, "%s should not realize" % type(self).__name__ + print "Danger, Will Robinson! Rectangle parent is not Overlayer" + + ctx = self.window.cairo_create() + + self.draw_with_context(ctx) + + def do_size_allocate(self, allocation): + """Save zone allocated to the widget.""" + self.allocation = allocation + + def do_size_allocate_init(self, widget, allocation): + """Save zone allocated to the widget.""" + self.allocation = allocation + +gobject.type_register(Smiley) class TextBubble(gtk.Widget): """ -- cgit v0.9.1