From 6584510d390a37153c20974da6704a907058fea0 Mon Sep 17 00:00:00 2001 From: mike Date: Mon, 19 Oct 2009 04:38:32 +0000 Subject: Merge gitorious@git.sugarlabs.org:tutorius/michaeljm-dev into merge_michaeljm-dev --- (limited to 'addons') diff --git a/addons/bubblemessage.py b/addons/bubblemessage.py index a859ef8..c499bdb 100644 --- a/addons/bubblemessage.py +++ b/addons/bubblemessage.py @@ -22,22 +22,22 @@ class BubbleMessage(Action): # Do the same for the tail position tail_pos = TArrayProperty([0,0], 2, 2) - def __init__(self, message=None, pos=None, speaker=None, tailpos=None): + def __init__(self, message=None, position=None, speaker=None, tail_pos=None): """ 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 position A list of the form [x, y] @param speaker treeish representation of the speaking widget - @param tailpos The position of the tail of the bubble; useful to point to + @param tail_pos The position of the tail of the bubble; useful to point to specific elements of the interface """ Action.__init__(self) - if pos: - self.position = pos - if tailpos: - self.tail_pos = tailpos + if position: + self.position = position + if tail_pos: + self.tail_pos = tail_pos if message: self.message = message diff --git a/addons/chainaction.py b/addons/chainaction.py new file mode 100644 index 0000000..43c4fa4 --- /dev/null +++ b/addons/chainaction.py @@ -0,0 +1,44 @@ +# 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 * + +class ChainAction(Action): + actions = TAddonListProperty() + + """Utility class to allow executing actions in a specific order""" + def __init__(self, actions=[]): + """ChainAction(action1, ... ) builds a chain of actions""" + Action.__init__(self) + self.actions = actions + + def do(self,**kwargs): + """do() each action in the chain""" + for act in self.actions: + act.do(**kwargs) + + def undo(self): + """undo() each action in the chain, starting with the last""" + for act in reversed(self.actions): + act.undo() + +__action__ = { + 'name': 'ChainAction', + 'display_name' : 'Chain of actions', + 'icon' : 'chain', + 'class' : ChainAction, + 'mandatory_props' : ['actions'] +} diff --git a/addons/clickaction.py b/addons/clickaction.py new file mode 100644 index 0000000..828dd75 --- /dev/null +++ b/addons/clickaction.py @@ -0,0 +1,52 @@ +# 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 import gtkutils +from sugar.tutorius.actions import * + +class ClickAction(Action): + """ + Action that simulate a click on a widget + Work on any widget that implements a clicked() method + + @param widget The threehish representation of the widget + """ + widget = TStringProperty("") + def __init__(self, widget): + Action.__init__(self) + self.widget = widget + + def do(self): + """ + click the widget + """ + realWidget = gtkutils.find_widget(ObjectStore().activity, self.widget) + if hasattr(realWidget, "clicked"): + realWidget.clicked() + + def undo(self): + """ + No undo + """ + pass + +__action__ = { + 'name' : 'ClickAction', + 'display_name' : 'Click', + 'icon' : 'format-justify-center', + 'class' : ClickAction, + 'mandatory_props' : ['widget'] +} diff --git a/addons/dialogmessage.py b/addons/dialogmessage.py index 22a223b..298466a 100644 --- a/addons/dialogmessage.py +++ b/addons/dialogmessage.py @@ -22,19 +22,19 @@ class DialogMessage(Action): message = TStringProperty("Message") position = TArrayProperty([0, 0], 2, 2) - def __init__(self, message=None, pos=None): + def __init__(self, message=None, position=None): """ 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 position A list of the form [x, y] """ super(DialogMessage, self).__init__() self._dialog = None if message: self.message = message - if pos: self.position = pos + if position: self.position = position def do(self): """ diff --git a/addons/disablewidget.py b/addons/disablewidget.py new file mode 100644 index 0000000..ce3f235 --- /dev/null +++ b/addons/disablewidget.py @@ -0,0 +1,59 @@ +# 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 * +from sugar.tutorius import gtkutils +from sugar.tutorius.services import ObjectStore + +class DisableWidgetAction(Action): + target = TStringProperty("0") + + def __init__(self, target): + """Constructor + @param target target treeish + """ + Action.__init__(self) + if target is not None: + self.target = target + self._widget = None + + def do(self): + """Action do""" + os = ObjectStore() + if os.activity: + self._widget = gtkutils.find_widget(os.activity, self.target) + if self._widget: + # If we have an object whose sensitivity we can query, we will + # keep it to reset it in the undo() method + if hasattr(self._widget, 'get_sensitive') and callable(self._widget.get_sensitive): + self._previous_sensitivity = self._widget.get_sensitive() + self._widget.set_sensitive(False) + + def undo(self): + """Action undo""" + if self._widget: + if hasattr(self, '_previous_sensitivity'): + self._widget.set_sensitive(self._previous_sensitivity) + else: + self._widget.set_sensitive(True) + +__action__ = { + 'name' : 'DisableWidgetAction', + 'display_name' : 'Disable Widget', + 'icon' : 'stop', + 'class' : DisableWidgetAction, + 'mandatory_props' : ['target'] +} diff --git a/addons/gtkwidgettypefilter.py b/addons/gtkwidgettypefilter.py new file mode 100644 index 0000000..16673c1 --- /dev/null +++ b/addons/gtkwidgettypefilter.py @@ -0,0 +1,100 @@ +# 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.filters import * +from sugar.tutorius.properties import * +from sugar.tutorius.services import ObjectStore +from sugar.tutorius.gtkutils import find_widget + +import logging +logger = logging.getLogger("GtkWidgetTypeFilter") + +class GtkWidgetTypeFilter(EventFilter): + """ + Event Filter that listens for keystrokes on a widget + """ + object_id = TStringProperty("") + text = TStringProperty("") + strokes = TArrayProperty([]) + + def __init__(self, next_state, object_id, text=None, strokes=None): + """Constructor + @param next_state default EventFilter param, passed on to EventFilter + @param object_id object tree-ish identifier + @param text resulting text expected + @param strokes list of strokes expected + + At least one of text or strokes must be supplied + """ + super(GtkWidgetTypeFilter, self).__init__(next_state) + self.object_id = object_id + self.text = text + self._captext = "" + self.strokes = strokes + self._capstrokes = [] + self._widget = None + self._handler_id = None + + def install_handlers(self, callback, **kwargs): + """install handlers + @param callback default EventFilter callback arg + """ + super(GtkWidgetTypeFilter, self).install_handlers(callback, **kwargs) + logger.debug("~~~GtkWidgetTypeFilter install") + activity = ObjectStore().activity + if activity is None: + logger.error("No activity") + raise RuntimeWarning("no activity in the objectstore") + + self._widget = find_widget(activity, self.object_id) + if self._widget: + self._handler_id= self._widget.connect("key-press-event",self.__keypress_cb) + logger.debug("~~~Connected handler %d on %s" % (self._handler_id,self.object_id) ) + + def remove_handlers(self): + """remove handlers""" + super(GtkWidgetTypeFilter, self).remove_handlers() + #if an event was connected, disconnect it + if self._handler_id: + self._widget.handler_disconnect(self._handler_id) + self._handler_id=None + + def __keypress_cb(self, widget, event, *args): + """keypress callback""" + logger.debug("~~~keypressed!") + key = event.keyval + keystr = event.string + logger.debug("~~~Got key: " + str(key) + ":"+ keystr) + self._capstrokes += [key] + #TODO Treat other stuff, such as arrows + if key == gtk.keysyms.BackSpace: + self._captext = self._captext[:-1] + else: + self._captext = self._captext + keystr + + logger.debug("~~~Current state: " + str(self._capstrokes) + ":" + str(self._captext)) + if not self.strokes is None and self.strokes in self._capstrokes: + self.do_callback() + if not self.text is None and self.text in self._captext: + self.do_callback() + +__event__ = { + 'name' : 'GtkWidgetTypeFilter', + 'display_name' : 'Widget Filter', + 'icon' : '', + 'class' : GtkWidgetTypeFilter, + 'mandatory_props' : ['next_state', 'object_id'] +} diff --git a/addons/oncewrapper.py b/addons/oncewrapper.py new file mode 100644 index 0000000..97f4752 --- /dev/null +++ b/addons/oncewrapper.py @@ -0,0 +1,59 @@ +# 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 * + +class OnceWrapper(Action): + """ + 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 + """ + + action = TAddonProperty() + + def __init__(self, action): + Action.__init__(self) + self._called = False + self._need_undo = False + self.action = action + + 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 + + +__action__ = { + 'name' : 'OnceWrapper', + 'display_name' : 'Execute an action only once', + 'icon' : 'once_wrapper', + 'class' : OnceWrapper, + 'mandatory_props' : ['action'] +} diff --git a/addons/timerevent.py b/addons/timerevent.py new file mode 100644 index 0000000..5bad416 --- /dev/null +++ b/addons/timerevent.py @@ -0,0 +1,74 @@ +# 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.filters import * +from sugar.tutorius.properties import * +import gobject +import logging + +logger = logging.getLogger('filters') + +class TimerEvent(EventFilter): + timeout_s = TIntProperty("1000") + """ + TimerEvent is a special EventFilter that uses gobject + timeouts to trigger a state change after a specified amount + of time. It must be used inside a gobject main loop to work. + """ + def __init__(self,next_state,timeout_s): + """Constructor. + + @param next_state default EventFilter param, passed on to EventFilter + @param timeout_s timeout in seconds + """ + super(TimerEvent,self).__init__(next_state) + self.timeout_s = timeout_s + self._handler_id = None + + def install_handlers(self, callback, **kwargs): + """install_handlers creates the timer and starts it""" + super(TimerEvent,self).install_handlers(callback, **kwargs) + #Create the timer + self._handler_id = gobject.timeout_add_seconds(self.timeout_s, self._timeout_cb) + + def remove_handlers(self): + """remove handler removes the timer""" + super(TimerEvent,self).remove_handlers() + if self._handler_id: + try: + #XXX What happens if this was already triggered? + #remove the timer + gobject.source_remove(self._handler_id) + except: + pass + + def _timeout_cb(self): + """ + _timeout_cb triggers the eventfilter callback. + + It is necessary because gobject timers only stop if the callback they + trigger returns False + """ + self.do_callback() + return False #Stops timeout + +__event__ = { + "name" : "TimerEvent", + "display_name" : "Timed transition", + "icon" : "clock", + "class" : TimerEvent, + "mandatory_props" : ["next_state", "timeout_s"] +} diff --git a/addons/triggereventfilter.py b/addons/triggereventfilter.py new file mode 100644 index 0000000..06c0995 --- /dev/null +++ b/addons/triggereventfilter.py @@ -0,0 +1,46 @@ +# 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.filters import * +from sugar.tutorius.properties import * + +class TriggerEventFilter(EventFilter): + """ + This event filter can be triggered by simply calling its do_callback function. + + Used to fake events and see the effect on the FSM. + """ + def __init__(self, next_state): + EventFilter.__init__(self, next_state) + self.toggle_on_callback = False + + def install_handlers(self, callback, **kwargs): + """ + Forsakes the incoming callback function and just set the inner one. + """ + self._callback = self._inner_cb + + def _inner_cb(self, event_filter): + self.toggle_on_callback = not self.toggle_on_callback + +__event__ = { + 'name' : 'TriggerEventFilter', + 'display_name' : 'Triggerable event filter (test only)', + 'icon' : '', + 'class' : TriggerEventFilter, + 'mandatory_props' : ['next_state'], + 'test' : True +} diff --git a/addons/typetextaction.py b/addons/typetextaction.py new file mode 100644 index 0000000..fee66e5 --- /dev/null +++ b/addons/typetextaction.py @@ -0,0 +1,57 @@ +# 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 * +from sugar.tutorius import gtkutils + +class TypeTextAction(Action): + """ + Simulate a user typing text in a widget + Work on any widget that implements a insert_text method + + @param widget The treehish representation of the widget + @param text the text that is typed + """ + widget = TStringProperty("") + text = TStringProperty("") + + def __init__(self, widget, text): + Action.__init__(self) + + self.widget = widget + self.text = text + + def do(self, **kwargs): + """ + Type the text + """ + widget = gtkutils.find_widget(ObjectStore().activity, self.widget) + if hasattr(widget, "insert_text"): + widget.insert_text(self.text, -1) + + def undo(self): + """ + no undo + """ + pass + +__action__ = { + 'name' : 'TypeTextAction', + 'display_name' : 'Type text', + 'icon' : 'format-justify-center', + 'class' : TypeTextAction, + 'mandatory_props' : ['widgetUAM', 'text'] +} diff --git a/addons/widgetidentifyaction.py b/addons/widgetidentifyaction.py new file mode 100644 index 0000000..3c66211 --- /dev/null +++ b/addons/widgetidentifyaction.py @@ -0,0 +1,47 @@ +# 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 * + +from sugar.tutorius.editor import WidgetIdentifier + +class WidgetIdentifyAction(Action): + def __init__(self): + Action.__init__(self) + self.activity = None + self._dialog = None + + def do(self): + os = ObjectStore() + if os.activity: + self.activity = os.activity + + self._dialog = WidgetIdentifier(self.activity) + self._dialog.show() + + + def undo(self): + if self._dialog: + self._dialog.destroy() + +__action__ = { + "name" : 'WidgetIdentifyAction', + "display_name" : 'Widget Identifier', + "icon" : 'viewmag1', + "class" : WidgetIdentifyAction, + "mandatory_props" : [], + 'test' : True +} -- cgit v0.9.1