diff options
Diffstat (limited to 'sugar-toolkit/src/sugar/tutorius/actions.py')
-rw-r--r-- | sugar-toolkit/src/sugar/tutorius/actions.py | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/sugar-toolkit/src/sugar/tutorius/actions.py b/sugar-toolkit/src/sugar/tutorius/actions.py new file mode 100644 index 0000000..da8219e --- /dev/null +++ b/sugar-toolkit/src/sugar/tutorius/actions.py @@ -0,0 +1,152 @@ +# 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 +""" +This module defines Actions that can be done and undone on a state +""" + +from sugar.tutorius import gtkutils +from dialog import TutoriusDialog +from sugar.tutorius.services import ObjectStore +import overlayer + + +class Action(object): + """Base class for Actions""" + def __init__(self): + object.__init__(self) + + def do(self, **kwargs): + """ + Perform the action + """ + raise NotImplementedError("Not implemented") + + def undo(self): + """ + Revert anything the action has changed + """ + pass #Should raise NotImplemented? + + +class OnceWrapper(object): + """ + Wraps a class to perform an action once only + + This ConcreteActions's do() method will only be called on the first do() + and the undo() will be callable after do() has been called + """ + def __init__(self, action): + self._action = action + self._called = False + self._need_undo = False + + def do(self): + """ + Do the action only on the first time + """ + if not self._called: + self._called = True + self._action.do() + self._need_undo = True + + def undo(self): + """ + Undo the action if it's been done + """ + if self._need_undo: + self._action.undo() + self._need_undo = False + +class DialogMessage(Action): + """ + Shows a dialog with a given text, at the given position on the screen. + + @param message A string to display to the user + @param pos A list of the form [x, y] + """ + def __init__(self, message, pos=[0,0]): + super(DialogMessage, self).__init__() + self._message = message + self.position = pos + self._dialog = None + + def do(self): + """ + Show the dialog + """ + self._dialog = TutoriusDialog(self._message) + self._dialog.set_button_clicked_cb(self._dialog.close_self) + self._dialog.set_modal(False) + self._dialog.move(self.position[0], self.position[1]) + self._dialog.show() + + def undo(self): + """ + Destroy the dialog + """ + if self._dialog: + self._dialog.destroy() + self._dialog = None + + +class BubbleMessage(Action): + """ + Shows a dialog with a given text, at the given position on the screen. + + @param message A string to display to the user + @param pos A list of the form [x, y] + @param speaker treeish representation of the speaking widget + """ + def __init__(self, message, pos=[0,0], speaker=None, tailpos=None): + Action.__init__(self) + self._message = message + self.position = pos + + self.overlay = None + self._bubble = None + self._speaker = None + self._tailpos = tailpos + + + def do(self): + """ + Show the dialog + """ + # 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._bubble: + x, y = self.position + # TODO: tails are relative to tailpos. They should be relative to + # the speaking widget. Same of the bubble position. + self._bubble = overlayer.TextBubble(text=self._message, + tailpos=self._tailpos) + self._bubble.show() + self.overlay.put(self._bubble, x, y) + self.overlay.queue_draw() + + def undo(self): + """ + Destroy the dialog + """ + if self._bubble: + self._bubble.destroy() + self._bubble = None + |