From 7019bbb21cf345a25afe87c148e5651aef3dd5c2 Mon Sep 17 00:00:00 2001 From: Vincent Vinet Date: Sat, 28 Feb 2009 01:54:39 +0000 Subject: -Replace the current event classes to use EVentFilters and callbacks onto the Tutorial claa -Wow this is an awesome commit, seriously! --- (limited to 'src/sugar/tutorius/filters.py') diff --git a/src/sugar/tutorius/filters.py b/src/sugar/tutorius/filters.py new file mode 100644 index 0000000..4c04cf6 --- /dev/null +++ b/src/sugar/tutorius/filters.py @@ -0,0 +1,162 @@ +# Copyright (C) 2009, Tutorius.org +# Copyright (C) 2009, Vincent Vinet +# +# 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 gobject + + +from sugar.tutorius.gtkutils import find_widget +class EventFilter(object): + """ + Base class for an event filter + """ + def __init__(self, next_state): + """ + Constructor. + @param next_state name of the next state + """ + self._next_state = next_state + self._callback = None + + def get_next_state(self): + """ + Getter for the next state + """ + return self._next_state + + def install_handlers(self, callback, **kwargs): + """ + install_handlers is called for eventfilters to setup all + necessary event handlers to be able to catch the desired + event. + + @param callback the callback function that will be called + with the event filter as an argument when the event is catched + and validated. + @param **kwargs unused by this handler for now, allows subclasses + to receive information about the context when installing + + Subclasses must call this super method to setup the callback if they + feel like cooperating + """ + self._callback = callback + + def remove_handlers(self): + """ + remove_handlers is called when a state is done so that all + event filters can cleanup any handlers they have installed + + This function will also clear the callback function so that any + leftover handler that is triggered will not be able to change the + application state. + + subclasses must call this super method to cleanup the callback if they + collaborate and use this classe's do_callback() + """ + self._callback = None + + def do_callback(self, *args, **kwargs): + """ + Default callback function that calls the event filter callback + with the event filter as only argument. + """ + if self._callback: + self._callback(self) + +class TimerEvent(EventFilter): + """ + 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 = 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, 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 + +class GtkWidgetEventFilter(EventFilter): + """ + Basic Event filter for Gtk widget events + """ + def __init__(self, next_state, object_id, event_name): + """Constructor + @param next_state default EventFilter param, passed on to EventFilter + @param object_id object fqdn-style identifier + @param event_name event to attach to + """ + super(GtkWidgetEventFilter,self).__init__(next_state) + self._callback = None + self._object_id = object_id + self._event_name = event_name + self._widget = None + self._handler_id = None + + def install_handlers(self, callback, **kwargs): + """install handlers + @param callback default EventFilter callback arg + @param activity keyword argument activity must be present to install + the event handler into the activity's widget hierarchy + """ + super(GtkWidgetEventFilter, self).install_handlers(callback, **kwargs) + if not "activity" in kwargs: + raise TypeError("activity argument is Mandatory") + + #find the widget and connect to its event + self._widget = find_widget(kwargs["activity"], self._object_id) + self._handler_id = self._widget.connect( \ + self._event_name, self.do_callback ) + + def remove_handlers(self): + """remove handlers""" + super(GtkWidgetEventFilter, 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 + + -- cgit v0.9.1