diff options
Diffstat (limited to 'src/sugar/tutorius/tutorial.py')
-rw-r--r-- | src/sugar/tutorius/tutorial.py | 279 |
1 files changed, 0 insertions, 279 deletions
diff --git a/src/sugar/tutorius/tutorial.py b/src/sugar/tutorius/tutorial.py deleted file mode 100644 index 8c457ae..0000000 --- a/src/sugar/tutorius/tutorial.py +++ /dev/null @@ -1,279 +0,0 @@ -# Copyright (C) 2009, Tutorius.org -# Copyright (C) 2009, Vincent Vinet <vince.vinet@gmail.com> -# -# 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 gtk -import logging - -from sugar.tutorius.dialog import TutoriusDialog - - -logger = logging.getLogger("tutorius") - -class Event: - def __init__(self, object_name, event_name ): - self.object_name = object_name - self.event_name = event_name - - def test(self, sig, name): - if self.object_name == name and self.event_name == sig: - return True - return False - - -class Tutorial (object): - EVENTS = [ - "focus", - "button-press-event", - "enter-notify-event", - "leave-notify-event", - "key-press-event", - "text-selected", - "clicked", - ] - - IGNORED_WIDGETS = [ - "GtkVBox", - "GtkHBox", - "GtkAlignment", - "GtkNotebook", - "GtkButton", - "GtkToolItem", - "GtkToolbar", - ] - - def __init__(self, name, fsm): - object.__init__(self) - self.name = name - self.state_machine = fsm - - self.handlers = [] - self.activity = None - #self.setState("INIT") - #self.state="INIT" - #self.register_signals(self.activity, self.handleEvent, max_depth=10) - - def attach(self, activity): - #For now, absolutely detach if a previous one! - if self.activity: - self.detach() - self.activity = activity - self.state="INIT" - self.register_signals(self.activity,self.handleEvent, max_depth=10) - - def detach(self): - self.disconnectHandlers() - self.activity = None - - def handleEvent(self, *args): - sig, objname = args[-1] - logger.debug("EVENT %s ON %s" % (sig, objname) ) - for transition, next in self.state_machine[self.state]["Events"]: - if transition.test(sig,objname): - logger.debug("====NEW STATE: %s====" % next) - self.state = next - dlg = TutoriusDialog(self.state_machine[self.state]["Message"]) - dlg.setButtonClickedCallback(dlg.closeSelf) - dlg.run() - -# @staticmethod -# def logEvent(obj, *args): -# logger.debug("%s" % str(args[-1])) - - def disconnectHandlers(self): - for t, id in self.handlers: - t.disconnect_handler(id) - -# def setState(self,name): -# self.disconnectHandlers() -# self.state = name -# newstate = ABIWORD_MEF.get(name,()) -# for event, n in newstate: -# target = self.activity -# try: -# for obj in event.object_name.split("."): -# target = getattr(target,obj) -# id = target.connect(self.handler,(event.object_name, event.event_name)) -# self.handlers.append(target, id) -# id = target.connect(Tutorial.logEvent,"EVENT %s ON %s" % (event.object_name, event.event_name)) -# self.handlers.append(target, id) -# except Exception, e: -# logger.debug(str(e)) - - def register_signals(self,object,handler,prefix=None,max_depth=None): - """ - Recursive function to register event handlers on an object - and it's children. The event handler is called with an extra - argument which is a two-tuple containing the signal name and - the FQDN-style name of the object that triggered the event. - - This function registers all of the events listed in - Tutorial.EVENTS and omits widgets with a name matching - Tutorial.IGNORED_WIDGETS from the name hierarchy. - - Example arg tuple added: - ("focus", "Activity.Toolbox.Bold") - Side effects: - -Handlers connected on the various objects - -Handler ID's stored in self.handlers - - @param object the object to recurse on - @param handler the handler function to connect - @param prefix name prepended to the object name to form a chain - @param max_depth maximum recursion depth, None for infinity - """ - #Gtk Containers have a get_children() function - if hasattr(object,"get_children") and \ - hasattr(object.get_children,"__call__"): - for child in object.get_children(): - if max_depth is None or max_depth > 0: - #Recurse with a prefix on all children - pre = ".".join( \ - [p for p in (prefix, object.get_name()) \ - if not (p is None or p in Tutorial.IGNORED_WIDGETS)] \ - ) - self.register_signals(child,handler,pre,max_depth-1) - name = ".".join( \ - [p for p in (prefix, object.get_name()) \ - if not (p is None or p in Tutorial.IGNORED_WIDGETS)] \ - ) - #register events on the object if a widget XXX necessary to check this? - if isinstance(object,gtk.Widget): - for sig in Tutorial.EVENTS: - try: - self.handlers.append( (object,object.connect(sig,handler,(sig, name) )) ) - except TypeError: - continue - - -############################################################################### -# -# Object oriented model for the FSM -# - -class Action: - """Represents an action to take when entering a state. An action might be - show a dialog to the user, or to play a sound. - - The do() executes the interaction, while the undo() must clean up - everything. """ - def __init__(self): - self.name = "Default Action" - - def do(self): - logging.debug("Doing default action") - - def undo(self): - logging.debug("Undoing default action") - -class DialogAction(Action): - """This is a pop-up dialog that displays a short text to the user.""" - def __init__(self, label, posX, posY): - self.name = "Dialog Action" - self.label = label - self.pos = [posX, posY] - - def do(self): - self.dialog = TutoriusDialog(label) - self.dialog.move(self.pos[0], self,pos[1]) - - def undo(self): - self.dialog.destroy() - -class State: - """This is a step in a tutorial. The state represents a collection of - actions to undertake when entering the state, and a description of an - event filter with associated actions to go to the next state.""" - - def __init__(self): - """Initializes the content of the state, as in loading the actions - that are required and building the correct tests.""" - self.actions = [] - self.tests = [] - - - def setup(self): - """Install the state itself. This is the best time to pop-up a dialog - that has to remain for the duration of the state.""" - for act in self.actions: - act.do() - - - def teardown(self): - """Undo every action that was installed for this state. This means - removing dialogs that were displayed, removing highlights, etc...""" - for act in self.actions: - act.undo() - - - def verify(self): - """Run the internal tests to see if one of them passes. If it does, - then do the associated processing to go in the next state.""" - for test in self.tests: - if test.verify() == True: - actions = test.get_actions() - for act in actions: - act.do() - # Now that we execute the actions related to a test, we might - # want to undo them right after --- should we use a callback or - # a timer? - -class FiniteStateMachine(State): - """This is a collection of states, with a start state and an end callback. - It is used to simplify the development of the various tutorials by - encapsulating a collection of states that represent a given learning - process.""" - def __init__(self, start_state, setup_actions): - """The constructor for a FSM. Pass in the start state and the setup - actions that need to be taken when the FSM itself start (which may be - different from what is done in the first state of the machine).""" - self.start_state = start_state - self.actions = setup_actions - - self.tests = [] - - self.current_state = self.start_state - - def setup(self): - for act in self.actions: - act.do() - - def teardown(self): - for act in self.actions: - act.undo - - def verify(self): - return self.current_state.verify() - - -class Executor: - """This is a class that executes a tutorial graph, meaning that it handles - the creation and deletion of states, as well as handling the transitions - between the various states.""" - - def __init__(self): - self.current_state = None - - - def start(self, fsm): - if self.current_state == None: - self.current_state = fsm - - self.current_state.install_handlers() - self.current_state.setup() - -
\ No newline at end of file |