diff options
Diffstat (limited to 'sugar-toolkit/src/sugar/tutorius')
25 files changed, 0 insertions, 2657 deletions
diff --git a/sugar-toolkit/src/sugar/tutorius/Makefile.am b/sugar-toolkit/src/sugar/tutorius/Makefile.am deleted file mode 100644 index 6fd32c7..0000000 --- a/sugar-toolkit/src/sugar/tutorius/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -sugardir = $(pythondir)/sugar/tutorius -sugar_PYTHON = \ - __init__.py \ - core.py \ - dialog.py \ - actions.py \ - gtkutils.py \ - filters.py \ - services.py \ - overlayer.py diff --git a/sugar-toolkit/src/sugar/tutorius/Makefile.in b/sugar-toolkit/src/sugar/tutorius/Makefile.in deleted file mode 100644 index b6f8607..0000000 --- a/sugar-toolkit/src/sugar/tutorius/Makefile.in +++ /dev/null @@ -1,437 +0,0 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src/sugar/tutorius -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gnome-compiler-flags.m4 \ - $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/python.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" -sugarPYTHON_INSTALL = $(INSTALL_DATA) -py_compile = $(top_srcdir)/py-compile -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -EXT_CFLAGS = @EXT_CFLAGS@ -EXT_LIBS = @EXT_LIBS@ -FGREP = @FGREP@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ -INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ -INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ -INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@ -INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ -INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ -INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ -INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ -INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ -INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ -INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ -INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ -INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ -INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ -INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ -PYGTK_CODEGEN = @PYGTK_CODEGEN@ -PYGTK_DEFSDIR = @PYGTK_DEFSDIR@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -WARN_CFLAGS = @WARN_CFLAGS@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -sugardir = $(pythondir)/sugar/tutorius -sugar_PYTHON = \ - __init__.py \ - core.py \ - dialog.py \ - actions.py \ - gtkutils.py \ - filters.py \ - services.py \ - overlayer.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/sugar/tutorius/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/sugar/tutorius/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-sugarPYTHON: $(sugar_PYTHON) - @$(NORMAL_INSTALL) - test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - f=$(am__strip_dir) \ - dlist="$$dlist $$f"; \ - echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ - $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ - else :; fi; \ - done; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ - else \ - PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-sugarPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - f=$(am__strip_dir) \ - rm -f "$(DESTDIR)$(sugardir)/$$f"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-sugarPYTHON - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-sugarPYTHON - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic clean-libtool \ - distclean distclean-generic distclean-libtool distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - install-sugarPYTHON installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - uninstall uninstall-am uninstall-sugarPYTHON - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/sugar-toolkit/src/sugar/tutorius/__init__.py b/sugar-toolkit/src/sugar/tutorius/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/sugar-toolkit/src/sugar/tutorius/__init__.py +++ /dev/null diff --git a/sugar-toolkit/src/sugar/tutorius/actions.py b/sugar-toolkit/src/sugar/tutorius/actions.py deleted file mode 100644 index da8219e..0000000 --- a/sugar-toolkit/src/sugar/tutorius/actions.py +++ /dev/null @@ -1,152 +0,0 @@ -# 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 - diff --git a/sugar-toolkit/src/sugar/tutorius/calc.py b/sugar-toolkit/src/sugar/tutorius/calc.py deleted file mode 100644 index 56ceba6..0000000 --- a/sugar-toolkit/src/sugar/tutorius/calc.py +++ /dev/null @@ -1,130 +0,0 @@ -import logging - -import sys, os -import pygtk -pygtk.require20() -import gtk - -import overlayer - - -#import rpdb2 -#rpdb2.start_embedded_debugger("foo", True, True) - -class TootOriole(): - def hello(self, widget, data=None): - logging.info('Hello World') - - def buttonclicked(self, button, data=None): - evt = button.child.get_text() - if evt not in ("+", "-", "*", "/", "=", "."): - if self.newNum: - self.reg1 = 0 - self.newNum = False - if not self.decimal: - self.reg1 = self.reg1*10+int(evt) - else: - self.reg1 += self.decimal*int(evt) - self.decimal /= 10 - else: - if (evt == "."): - self.decimal = 0.1 - return - - if evt == "=": - evt = None - - self.reg2 = { - "+": lambda a, b: a+b, - "-": lambda a, b: a-b, - "*": lambda a, b: a*b, - "/": lambda a, b: a/b, - None: lambda a, b: b - }[self.lastOp](self.reg2, self.reg1) - self.reg1 = self.reg2 - self.newNum = True - self.decimal = 0 - self.lastOp = evt - self.label.set_label(str(self.reg1)) - - def __init__(self): - self.reg1 = 0 - self.reg2 = 0 - self.lastOp = None - self.decimal = 0 - self.newNum = False - - print "running activity init" - self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.window.connect("delete_event", self.delete_event) - self.window.connect("destroy", self.destroy) - print "activity running" - - # Creates the Toolbox. It contains the Activity Toolbar, which is the - # bar that appears on every Sugar window and contains essential - # functionalities, such as the 'Collaborate' and 'Close' buttons. - #toolbox = activity.ActivityToolbox(self) - #self.set_toolbox(toolbox) - #toolbox.show() - - self.vbox = gtk.VBox(homogeneous=False, spacing=20) - - #textbox - self.label = gtk.Label("0") - self.label.show() - self.vbox.pack_start(self.label, False, True, 10) - - table = gtk.Table(rows=4, columns=4, homogeneous=True) - table.show() - self.vbox.pack_start(child=table, expand=True, fill=True, \ - padding=10) - buttonlist = [0, "+", "-", "x", 7, 8, 9, "/", 4, 5, 6, "=", \ - 1, 2, 3, "."] - - for i in range(4): - for j in range(4): - button = gtk.Button("") - button.child.set_markup("<big><b>%s</b></big>" \ - % str(buttonlist.pop(0))) - table.attach(button, j, j+1, i, i+1, gtk.EXPAND|gtk.FILL, - gtk.EXPAND|gtk.FILL, 15, 15) - button.connect("clicked", self.buttonclicked, None) - button.show() - - # Set the button to be our canvas. The canvas is the main section of - # every Sugar Window. It fills all the area below the toolbox. - - - # The final step is to display this newly created widget. - self.vbox.show() - self.window.add(self.vbox) - - self.window.show() - - # proto overlap - # ==================================================================== - # =================================== clip here ====================== - # Create overlay base where all overlayed widgets will reside - overlayBase = overlayer.Overlayer() - overlayBase.inject(self.vbox) - bubble = overlayer.TextBubble(text="Hello,\nI'm a comma.Use me to\nrepresent decimal numbers.", speaker=button) - overlayBase.put(bubble, 40, 50) - # we do not eject the overlay, but it could be done when overlay is not - # needed anymore - # =================================== end clip ======================= - # ==================================================================== - - - def delete_event(self, widget, event, data=None): - print "quitting..." - return False - - def destroy(self, widget, data=None): - gtk.main_quit() - - - - -if __name__ == "__main__": - t = TootOriole() - gtk.main() diff --git a/sugar-toolkit/src/sugar/tutorius/core.py b/sugar-toolkit/src/sugar/tutorius/core.py deleted file mode 100644 index f817ba9..0000000 --- a/sugar-toolkit/src/sugar/tutorius/core.py +++ /dev/null @@ -1,334 +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 -""" -Core - -This module contains the core classes for tutorius - -""" - -import gtk -import logging - -from sugar.tutorius.dialog import TutoriusDialog -from sugar.tutorius.gtkutils import find_widget - -logger = logging.getLogger("tutorius") - -class Tutorial (object): - """ - Tutorial Class, used to run through the FSM. - """ - - def __init__(self, name, fsm): - """ - Creates an unattached tutorial. - """ - object.__init__(self) - self.name = name - - self.state_machine = fsm - self.state_machine.set_tutorial(self) - - self.state = None - - self.handlers = [] - self.activity = None - #Rest of initialisation happens when attached - - def attach(self, activity): - """ - Attach to a running activity - - @param activity the activity to attach to - """ - #For now, absolutely detach if a previous one! - if self.activity: - self.detach() - self.activity = activity - self.state_machine.set_state("INIT") - - def detach(self): - """ - Detach from the current activity - """ - - # Uninstall the whole FSM - self.state_machine.teardown() - - #FIXME There should be some amount of resetting done here... - self.activity = None - - - def set_state(self, name): - """ - Switch to a new state - """ - logger.debug("====NEW STATE: %s====" % name) - - self.state_machine.set_state(name) - - - # Currently unused -- equivalent function is in each state - def _eventfilter_state_done(self, eventfilter): - """ - Callback handler for eventfilter to notify - when we must go to the next state. - """ - #XXX Tests should be run here normally - - #Swith to the next state pointed by the eventfilter - self.set_state(eventfilter.get_next_state()) - -class State: - """ - This is a step in a tutorial. The state represents a collection of actions - to undertake when entering the state, and a series of event filters - with associated actions that point to a possible next state. - """ - - def __init__(self, name, action_list=[], event_filter_list=[], tutorial=None): - """ - Initializes the content of the state, like loading the actions - that are required and building the correct tests. - - @param action_list The list of actions to execute when entering this - state - @param event_filter_list A list of tuples of the form - (event_filter, next_state_name), that explains the outgoing links for - this state - @param tutorial The higher level container of the state - """ - self._actions = action_list - - # Unused for now - #self.tests = [] - - self._event_filters = event_filter_list - - self.tutorial = tutorial - - def set_tutorial(self, tutorial): - """ - Associates this state with a tutorial. A tutorial must be set prior - to executing anything in the state. The reason for this is that the - states need to have access to the activity (via the tutorial) in order - to properly register their callbacks on the activities' widgets. - - @param tutorial The tutorial that this state runs under. - """ - if self.tutorial == None : - self.tutorial = tutorial - else: - raise RuntimeWarning(\ - "The state %s was already associated with a tutorial." % self.name) - - def setup(self): - """ - Install the state itself, by first registering the event filters - and then triggering the actions. - """ - for eventfilter in self._event_filters: - eventfilter.install_handlers(self._event_filter_state_done_cb, - activity=self.tutorial.activity) - - for action in self._actions: - action.do() - - def teardown(self): - """ - Uninstall all the event filters that were active in this state. - Also undo every action that was installed for this state. This means - removing dialogs that were displayed, removing highlights, etc... - """ - # Remove the handlers for the all of the state's event filters - for event_filter in self._event_filters: - event_filter.remove_handlers() - - # Undo all the actions related to this state - for action in self._actions: - action.undo() - - def _event_filter_state_done_cb(self, event_filter): - """ - Callback for event filters. This function needs to inform the - tutorial that the state is over and tell it what is the next state. - - @param event_filter The event filter that was called - """ - # Run the tests here, if need be - - # Warn the higher level that we wish to change state - self.tutorial.set_state(event_filter.get_next_state()) - - # Unused for now -## 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. - - For now, we will consider that there can only be states - inserted in the FSM, and that there are no nested FSM inside. - """ - - def __init__(self, name, tutorial=None, state_dict={}, start_state_name="INIT", action_list=[]): - """ - 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). - - @param name A short descriptive name for this FSM - @param tutorial The tutorial that will execute this FSM. If None is - attached on creation, then one must absolutely be attached before - executing the FSM with set_tutorial(). - @param state_dict A dictionary containing the state names as keys and - the state themselves as entries. - @param start_state_name The name of the starting state, if different - from "INIT" - @param action_list The actions to undertake when initializing the FSM - """ - State.__init__(self, name) - - self.name = name - self.tutorial = tutorial - - # Dictionnary of states contained in the FSM - self._states = state_dict - - # Remember the initial state - we might want to reset - # or rewind the FSM at a later moment - self.start_state = state_dict[start_state_name] - self.current_state = self.start_state - - # Register the actions for the FSM - They will be processed at the - # FSM level, meaning that when the FSM will start, it will first - # execute those actions. When the FSM closes, it will tear down the - # inner actions of the state, then close its own actions - self.actions = action_list - - # Flag to mention that the FSM was initialized - self._fsm_setup_done = False - # Flag that must be raised when the FSM is to be teared down - self._fsm_teardown_done = False - # Flag used to declare that the FSM has reached an end state - self._fsm_has_finished = False - - def set_tutorial(self, tutorial): - """ - This associates the FSM to the given tutorial. It MUST be associated - either in the constructor or with this function prior to executing the - FSM. - - @param tutorial The tutorial that will execute this FSM. - """ - # If there was no tutorial associated - if self.tutorial == None: - # Associate it with this FSM and all the underlying states - self.tutorial = tutorial - for state in self._states.itervalues(): - state.set_tutorial(tutorial) - else: - raise RuntimeWarning(\ - "The FSM %s is already associated with a tutorial."%self.name\ - ) - - def setup(self): - """ - This function initializes the FSM the first time it is called. - Then, every time it is called, it initializes the current state. - """ - # Are we associated with a tutorial? - if self.tutorial == None: - raise UnboundLocalError("No tutorial was associated with FSM %s" % self.name) - - # If we never initialized the FSM itself, then we need to run all the - # actions associated with the FSM. - if self._fsm_setup_done == False: - # Flag the FSM level setup as done - self._fsm_setup_done = True - # Execute all the FSM level actions - for action in self.actions: - action.do() - - # Then, we need to run the setup of the current state - self.current_state.setup() - - def set_state(self, new_state_name): - """ - This functions changes the current state of the finite state machine. - - @param new_state The identifier of the state we need to go to - """ - # TODO : Since we assume no nested FSMs, we don't set state on the - # inner States / FSMs -## # Pass in the name to the internal state - it might be a FSM and -## # this name will apply to it -## self.current_state.set_state(new_state_name) - - # Make sure the given state is owned by the FSM - if not self._states.has_key(new_state_name): - # If we did not recognize the name, then we do not possess any - # state by that name - we must ignore this state change request as - # it will be done elsewhere in the hierarchy (or it's just bogus). - return - - new_state = self._states[new_state_name] - - # Undo the actions of the old state - self.teardown() - - # Insert the new state - self.current_state = new_state - - # Call the initial actions in the new state - self.setup() - - - def teardown(self): - """ - Revert any changes done by setup() - """ - # Teardown the current state - self.current_state.teardown() - - # If we just finished the whole FSM, we need to also call the teardown - # on the FSM level actions - if self._fsm_has_finished == True: - # Flag the FSM teardown as not needed anymore - self._fsm_teardown_done = True - # Undo all the FSM level actions here - for action in self.actions: - action.undo() - - #Unused for now -## def verify(self): -## """Verify if the current state passes its tests""" -## return self.current_state.verify() diff --git a/sugar-toolkit/src/sugar/tutorius/dialog.py b/sugar-toolkit/src/sugar/tutorius/dialog.py deleted file mode 100644 index be51a0e..0000000 --- a/sugar-toolkit/src/sugar/tutorius/dialog.py +++ /dev/null @@ -1,59 +0,0 @@ -# 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 -""" -The Dialog module provides means of interacting with the user -through the use of Dialogs. -""" -import gtk - -class TutoriusDialog(gtk.Dialog): - """ - TutoriusDialog is a simple wrapper around gtk.Dialog. - - It allows creating and showing a dialog and connecting the response and - button click events to callbacks. - """ - def __init__(self, label="Hint", button_clicked_cb=None, response_cb=None): - """ - Constructor. - - @param label text to be shown on the dialog - @param button_clicked_cb callback for the button click - @param response_cb callback for the dialog response - """ - gtk.Dialog.__init__(self) - - self._button = gtk.Button(label) - - self.add_action_widget(self._button, 1) - - if not button_clicked_cb == None: - self._button.connect("clicked", button_clicked_cb) - - self._button.show() - - if not response_cb == None: - self.connect("response", response_cb) - - self.set_decorated(False) - - def set_button_clicked_cb(self, funct): - """Setter for the button_clicked callback""" - self._button.connect("clicked", funct) - - def close_self(self, arg=None): - """Close the dialog""" - self.destroy() diff --git a/sugar-toolkit/src/sugar/tutorius/dialog.pyc b/sugar-toolkit/src/sugar/tutorius/dialog.pyc Binary files differdeleted file mode 100644 index e7e02b9..0000000 --- a/sugar-toolkit/src/sugar/tutorius/dialog.pyc +++ /dev/null diff --git a/sugar-toolkit/src/sugar/tutorius/dragbox.py b/sugar-toolkit/src/sugar/tutorius/dragbox.py deleted file mode 100644 index d84e4ee..0000000 --- a/sugar-toolkit/src/sugar/tutorius/dragbox.py +++ /dev/null @@ -1,120 +0,0 @@ -# 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 the DragBox class, representing a gtk.Layout like container -which supports a "children dragging mode". -""" - -import gtk - -class DragBox(gtk.EventBox): - """ - A DragBox represents a gtk container whose child object can be arbitrarily - placed, like for a gtk.Layout. However DragBox implements a child "dragging" - mode which allows the user to freely move immediate children of the DragBox. - - This can be toggled by the dragMode property (default to False) - - Default behavior is to keep children at minimal size, as returned by - a call to gtk.Widget.get_size(). - - """ - def __init__(self): - gtk.EventBox.__init__(self) - - self.set_above_child(False) - self.connect("motion-notify-event", self._on_mouse_evt) - self.connect("button-press-event", self._on_mouse_evt) - self.connect("button-release-event", self._on_mouse_evt) - - self._drag_mode = False - self._dragging = None # the object being dragged, or None - self._last_mouse_pos = None # last known mouse position (win. relative) - - self._layout = gtk.Layout() - self.add(self._layout) - - def attach(self, widget, xPos=0, yPos=0, size=None, resizable=False): - """ - Adds the child to the EventBox hierarchy. - widget is expected to be a displayable gtk.Widget and will respond - to the dragMode by being dragable. - """ - # TODO handle child and set size - self._layout.put(child_widget=widget, x=xPos, y=yPos) - - def show(self): - gtk.EventBox.show(self) - self._layout.show() - - def hide(self): - gtk.EventBox.hide(self) - self._layout.hide() - - def _on_mouse_evt(self, widget, event, data=None): - """ - Callback registered on mouse events. - _on_mouse_evt does the actual child selection and moving - """ - if not self._drag_mode: - return - - x, y = event.get_coords() - - if self._dragging is not None and event.type is gtk.gdk.MOTION_NOTIFY: - child = self._dragging.get_allocation() - self._layout.move(self._dragging, - int(child.x+x-self._last_mouse_pos[0]), - int(child.y+y-self._last_mouse_pos[1])) - self._last_mouse_pos = event.get_coords() - # FIXME scale layout or constraint dragging to DragBox - - elif self._dragging is None and event.type is gtk.gdk.BUTTON_PRESS: - # iterate in revese as last drawn child is over the others - for child in reversed(self._layout.get_children()): - rect = child.get_allocation() - if x >= rect.x and x < rect.x+rect.width \ - and y >= rect.y and y < rect.y+rect.height: - self._dragging = child - # Common interface paradigm is that selecting an item - # goes to top of stack it so we do just that. - self._layout.remove(child) - self._layout.put(child, rect.x, rect.y) - break - self._last_mouse_pos = event.get_coords() - # TODO add conditional restack child - - elif self._dragging is not None \ - and event.type is gtk.gdk.BUTTON_RELEASE: - self._dragging = None - - def _set_drag_mode(self, value): - if (not self._drag_mode) and value: - self.set_above_child(True) - elif self._drag_mode and (not value): - self.set_above_child(False) - - self._drag_mode = value - - def _get_drag_mode(self): - return self._drag_mode - - dragMode = property(fset=_set_drag_mode, fget=_get_drag_mode, - doc="Defines whether widgets in DragBox can be mouse dragged.") - - # TODO set child properties (list_child_properties) - - diff --git a/sugar-toolkit/src/sugar/tutorius/dragbox.pyc b/sugar-toolkit/src/sugar/tutorius/dragbox.pyc Binary files differdeleted file mode 100644 index 568f3e3..0000000 --- a/sugar-toolkit/src/sugar/tutorius/dragbox.pyc +++ /dev/null diff --git a/sugar-toolkit/src/sugar/tutorius/filters.py b/sugar-toolkit/src/sugar/tutorius/filters.py deleted file mode 100644 index 4c04cf6..0000000 --- a/sugar-toolkit/src/sugar/tutorius/filters.py +++ /dev/null @@ -1,162 +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 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 - - diff --git a/sugar-toolkit/src/sugar/tutorius/gtkutils.py b/sugar-toolkit/src/sugar/tutorius/gtkutils.py deleted file mode 100644 index 073a7f3..0000000 --- a/sugar-toolkit/src/sugar/tutorius/gtkutils.py +++ /dev/null @@ -1,169 +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 -""" -Utility classes and functions that are gtk related -""" - -def find_widget(base, target_fqdn): - """Find a widget by digging into a parent widget's children tree - @param base the parent widget - @param target_fqdn fqdn-style target object name - - @return widget found - - The object should normally be the activity widget, as it is the root - widget for activities. The target_fqdn is a dot separated list of - indexes used in widget.get_children and should start with a 0 which is - the base widget itself, - - Example Usage: - find_widget(activity,"0.0.0.1.0.0.2") - """ - path = target_fqdn.split(".") - #We select the first object and pop the first zero - obj = base - path.pop(0) - - while len(path) > 0: - try: - obj = obj.get_children()[int(path.pop(0))] - except: - break - - return obj - -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 register_signals_numbered(target, handler, prefix="0", max_depth=None): - """ - Recursive function to register event handlers on an target - 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 target that triggered the event. - - This function registers all of the events listed in - EVENTS - - Example arg tuple added: - ("focus", "1.1.2") - Side effects: - -Handlers connected on the various targets - - @param target the target to recurse on - @param handler the handler function to connect - @param prefix name prepended to the target name to form a chain - @param max_depth maximum recursion depth, None for infinity - - @returns list of (object, handler_id) - """ - ret = [] - #Gtk Containers have a get_children() function - if hasattr(target, "get_children") and \ - hasattr(target.get_children, "__call__"): - children = target.get_children() - for i in range(len(children)): - child = children[i] - if max_depth is None or max_depth > 0: - #Recurse with a prefix on all children - pre = ".".join( \ - [p for p in (prefix, str(i)) if not p is None] - ) - if max_depth is None: - dep = None - else: - dep = max_depth - 1 - ret+=register_signals_numbered(child, handler, pre, dep) - #register events on the target if a widget XXX necessary to check this? - if isinstance(target, gtk.Widget): - for sig in Tutorial.EVENTS: - try: - ret.append( \ - (target, target.connect(sig, handler, (sig, prefix) ))\ - ) - except TypeError: - pass - - return ret - -def register_signals(self, target, handler, prefix=None, max_depth=None): - """ - Recursive function to register event handlers on an target - 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 target 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 targets - -Handler ID's stored in self.handlers - - @param target the target to recurse on - @param handler the handler function to connect - @param prefix name prepended to the target name to form a chain - @param max_depth maximum recursion depth, None for infinity - """ - ret = [] - #Gtk Containers have a get_children() function - if hasattr(target, "get_children") and \ - hasattr(target.get_children, "__call__"): - for child in target.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, target.get_name()) \ - if not (p is None or p in Tutorial.IGNORED_WIDGETS)] \ - ) - ret += register_signals(child, handler, pre, max_depth-1) - name = ".".join( \ - [p for p in (prefix, target.get_name()) \ - if not (p is None or p in Tutorial.IGNORED_WIDGETS)] \ - ) - #register events on the target if a widget XXX necessary to check this? - if isinstance(target, gtk.Widget): - for sig in Tutorial.EVENTS: - try: - ret.append( \ - (target, target.connect(sig, handler, (sig, name) )) \ - ) - except TypeError: - pass - - return ret - diff --git a/sugar-toolkit/src/sugar/tutorius/overlayer.py b/sugar-toolkit/src/sugar/tutorius/overlayer.py deleted file mode 100644 index c08ed4c..0000000 --- a/sugar-toolkit/src/sugar/tutorius/overlayer.py +++ /dev/null @@ -1,328 +0,0 @@ -""" -This guy manages drawing of overlayed widgets. The class responsible for drawing -management (Overlayer) and overlayable widgets are defined here. -""" -# 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 gobject -import gtk -import cairo -import pangocairo - -# This is the CanvasDrawable protocol. Any widget wishing to be drawn on the -# overlay must implement it. See TextBubble for a sample implementation. -#class CanvasDrawable(object): -# """Defines the CanvasDrawable protocol""" -# no_expose = None -# def draw_with_context(self, context): -# """ -# Draws the cairo widget with the passed cairo context. -# This will be called if the widget is child of an overlayer. -# """ -# pass - -class Overlayer(gtk.Layout): - """ - This guy manages drawing of overlayed widgets. Those can be standard GTK - widgets or special "cairoDrawable" widgets which support the defined - interface (see the put method). - - @param overlayed widget to be overlayed. Will be resized to full size. - """ - def __init__(self, overlayed=None): - gtk.Layout.__init__(self) - - self._overlayed = overlayed - if overlayed: - self.put(overlayed, 0, 0) - - self.__realizer = self.connect("expose-event", self.__init_realized) - self.connect("size-allocate", self.__size_allocate) - self.show() - - self.__render_handle = None - - def put(self, child, x, y): - """ - Adds a child widget to be overlayed. This can be, overlay widgets or - normal GTK widgets (though normal widgets will alwas appear under - cairo widgets due to the rendering chain). - - @param child the child to add - @param x the horizontal coordinate for positionning - @param y the vertical coordinate for positionning - """ - 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) - - - def __init_realized(self, widget, event): - """ - Initializer to set once widget is realized. - Since an expose event is signaled only to realized widgets, we set this - callback for the first expose run. It should also be called after - beign reparented to ensure the window used for drawing is set up. - """ - assert hasattr(self.window, "set_composited"), \ - "compositing not supported or widget not realized." - self.disconnect(self.__realizer) - del self.__realizer - - self.parent.set_app_paintable(True) - - # the parent is composited, so we can access gtk's rendered buffer - # and overlay over. If we don't composite, we won't be able to read - # pixels and background will be black. - self.window.set_composited(True) - self.__render_handle = self.parent.connect_after("expose-event", \ - self.__expose_overlay) - - def __expose_overlay(self, widget, event): - """expose event handler to draw the thing.""" - #get our child (in this case, the event box) - child = widget.get_child() - - #create a cairo context to draw to the window - ctx = widget.window.cairo_create() - - #the source data is the (composited) event box - ctx.set_source_pixmap(child.window, - child.allocation.x, - child.allocation.y) - - #draw no more than our expose event intersects our child - region = gtk.gdk.region_rectangle(child.allocation) - rect = gtk.gdk.region_rectangle(event.area) - region.intersect(rect) - ctx.region (region) - ctx.clip() - - ctx.set_operator(cairo.OPERATOR_OVER) - # has to be blended and a 1.0 alpha would not make it blend - ctx.paint_with_alpha(0.99) - - #draw overlay - for drawn_child in self.get_children(): - if hasattr(drawn_child, "draw_with_context"): - drawn_child.draw_with_context(ctx) - - - def __size_allocate(self, widget, allocation): - """ - Set size allocation (actual gtk widget size) and propagate it to - overlayed child - """ - self.allocation = allocation - # One may wonder why using size_request instead of size_allocate; - # Since widget is laid out in a Layout box, the Layout will honor the - # requested size. Using size_allocate could make a nasty nested loop in - # some cases. - self._overlayed.set_size_request(allocation.width, allocation.height) - - -class TextBubble(gtk.Widget): - """ - A CanvasDrawableWidget drawing a round textbox and a tail pointing - to a specified widget. - """ - def __init__(self, text, speaker=None, tailpos=None): - """ - Creates a new cairo rendered text bubble. - - @param text the text to render in the bubble - @param speaker the widget to compute the tail position from - @param tailpos (optional) position relative to the bubble to use as - the tail position, if no speaker - """ - gtk.Widget.__init__(self) - - # FIXME: ensure previous call does not interfere with widget stacking, - # as using a gtk.Layout and stacking widgets may reveal a screwed up - # order with the cairo widget on top. - self.__label = None - self.__text_dimentions = None - - self.label = text - self.speaker = speaker - self.tailpos = tailpos - self.line_width = 5 - - self.__exposer = self.connect("expose-event", self.__on_expose) - - def draw_with_context(self, context): - """ - Draw using the passed cairo context instead of creating a new cairo - context. This eases blending between multiple cairo-rendered - widgets. - """ - context.translate(self.allocation.x, self.allocation.y) - width = self.allocation.width - height = self.allocation.height - xradius = width/2 - yradius = height/2 - width -= self.line_width - height -= self.line_width - - # bubble border - context.move_to(self.line_width, yradius) - context.curve_to(self.line_width, self.line_width, - self.line_width, self.line_width, xradius, self.line_width) - context.curve_to(width, self.line_width, - width, self.line_width, width, yradius) - context.curve_to(width, height, width, height, xradius, height) - context.curve_to(self.line_width, height, - self.line_width, height, self.line_width, yradius) - context.set_line_width(self.line_width) - context.set_source_rgb(0.0, 0.0, 0.0) - context.stroke() - - # TODO fetch speaker coordinates - - # draw bubble tail - if self.tailpos: - context.move_to(xradius-40, yradius) - context.line_to(self.tailpos[0], self.tailpos[1]) - context.line_to(xradius+40, yradius) - context.set_line_width(self.line_width) - context.set_source_rgb(0.0, 0.0, 0.0) - context.stroke_preserve() - context.set_source_rgb(1.0, 1.0, 0.0) - context.fill() - - # bubble painting. Redrawing the inside after the tail will combine - # both shapes. - # TODO: we could probably generate the shape at initialization to - # lighten computations. - context.move_to(self.line_width, yradius) - context.curve_to(self.line_width, self.line_width, - self.line_width, self.line_width, xradius, self.line_width) - context.curve_to(width, self.line_width, - width, self.line_width, width, yradius) - context.curve_to(width, height, width, height, xradius, height) - context.curve_to(self.line_width, height, - self.line_width, height, self.line_width, yradius) - context.set_source_rgb(1.0, 1.0, 0.0) - context.fill() - - # text - # FIXME create text layout when setting text or in realize method - context.set_source_rgb(0.0, 0.0, 0.0) - pangoctx = pangocairo.CairoContext(context) - text_layout = pangoctx.create_layout() - text_layout.set_text(self.__label) - pangoctx.move_to( - int((self.allocation.width-self.__text_dimentions[0])/2), - int((self.allocation.height-self.__text_dimentions[1])/2)) - pangoctx.show_layout(text_layout) - - # work done. Be kind to next cairo widgets and reset matrix. - context.identity_matrix() - - def do_realize(self): - """ Setup gdk window creation. """ - self.set_flags(gtk.REALIZED | gtk.NO_WINDOW) - # TODO: cleanup window creation code as lot here probably isn't - # necessary. - # See http://www.learningpython.com/2006/07/25/writing-a-custom-widget-using-pygtk/ - # as the following was taken there. - self.window = self.get_parent_window() - if not isinstance(self.parent, Overlayer): - self.unset_flags(gtk.NO_WINDOW) - self.window = gtk.gdk.Window( - self.get_parent_window(), - width=self.allocation.width, - height=self.allocation.height, - window_type=gtk.gdk.WINDOW_CHILD, - wclass=gtk.gdk.INPUT_OUTPUT, - event_mask=self.get_events()|gtk.gdk.EXPOSURE_MASK) - - # Associate the gdk.Window with ourselves, Gtk+ needs a reference - # between the widget and the gdk window - self.window.set_user_data(self) - - # Attach the style to the gdk.Window, a style contains colors and - # GC contextes used for drawing - self.style.attach(self.window) - - # The default color of the background should be what - # the style (theme engine) tells us. - self.style.set_background(self.window, gtk.STATE_NORMAL) - self.window.move_resize(*self.allocation) - - def __on_expose(self, widget, event): - """Redraw event callback.""" - ctx = self.window.cairo_create() - - self.draw_with_context(ctx) - - return True - - def _set_label(self, value): - """Sets the label and flags the widget to be redrawn.""" - self.__label = value - # FIXME hack to calculate size. necessary because may not have been - # realized. We create a fake surface to use builtin math. This should - # probably be done at realization and/or on text setter. - surf = cairo.SVGSurface("/dev/null", 0, 0) - ctx = cairo.Context(surf) - pangoctx = pangocairo.CairoContext(ctx) - text_layout = pangoctx.create_layout() - text_layout.set_text(value) - self.__text_dimentions = text_layout.get_pixel_size() - del text_layout, pangoctx, ctx, surf - - def do_size_request(self, requisition): - """Fill requisition with size occupied by the widget.""" - width, height = self.__text_dimentions - - # FIXME bogus values follows. will need to replace them with - # padding relative to font size and line border size - requisition.width = int(width+30) - requisition.height = int(height+40) - - def do_size_allocate(self, allocation): - """Save zone allocated to the widget.""" - self.allocation = allocation - - def _get_label(self): - """Getter method for the label property""" - return self.__label - - def _set_no_expose(self, value): - """setter for no_expose property""" - if self.__exposer and value: - self.disconnect(self.__exposer) - self.__exposer = None - elif (not self.__exposer) and (not value): - self.__exposer = self.connect("expose-event", self.__on_expose) - - def _get_no_expose(self): - """getter for no_expose property""" - return not self.__exposer - - no_expose = property(fset=_set_no_expose, fget=_get_no_expose, - doc="Whether the widget should handle exposition events or not.") - - label = property(fget=_get_label, fset=_set_label, - doc="Text label which is to be painted on the top of the widget") - -gobject.type_register(TextBubble) - - -# vim:set ts=4 sts=4 sw=4 et: diff --git a/sugar-toolkit/src/sugar/tutorius/overlayer.pyc b/sugar-toolkit/src/sugar/tutorius/overlayer.pyc Binary files differdeleted file mode 100644 index 627ba9d..0000000 --- a/sugar-toolkit/src/sugar/tutorius/overlayer.pyc +++ /dev/null diff --git a/sugar-toolkit/src/sugar/tutorius/services.py b/sugar-toolkit/src/sugar/tutorius/services.py deleted file mode 100644 index 467eca0..0000000 --- a/sugar-toolkit/src/sugar/tutorius/services.py +++ /dev/null @@ -1,68 +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 -""" -Services - -This module supplies services to be used by States, FSMs, Actions and Filters. - -Services provided are: --Access to the running activity --Access to the running tutorial -""" - - -class ObjectStore(object): - #Begin Singleton code - instance=None - def __new__(cls): - if not ObjectStore.instance: - ObjectStore.instance = ObjectStore.__ObjectStore() - - return ObjectStore.instance - - #End Singleton code - class __ObjectStore(object): - """ - The Object Store is a singleton class that allows access to - the current runnign activity and tutorial. - """ - def __init__(self): - self._activity = None - self._tutorial = None - #self._fsm_path = [] - - def set_activity(self, activity): - """Setter for activity""" - self._activity = activity - - def get_activity(self): - """Getter for activity""" - return self._activity - - activity = property(fset=set_activity,fget=get_activity,doc="activity") - - def set_tutorial(self, tutorial): - """Setter for tutorial""" - self._tutorial = tutorial - - def get_tutorial(self): - """Getter for tutorial""" - return self._tutorial - - tutorial = property(fset=set_tutorial,fget=get_tutorial,doc="tutorial") - - __doc__ = __ObjectStore.__doc__ diff --git a/sugar-toolkit/src/sugar/tutorius/tests/.coverage b/sugar-toolkit/src/sugar/tutorius/tests/.coverage deleted file mode 100644 index eb89cb2..0000000 --- a/sugar-toolkit/src/sugar/tutorius/tests/.coverage +++ /dev/null @@ -1 +0,0 @@ -{0
\ No newline at end of file diff --git a/sugar-toolkit/src/sugar/tutorius/tests/coretests.py b/sugar-toolkit/src/sugar/tutorius/tests/coretests.py deleted file mode 100644 index ed5a7c0..0000000 --- a/sugar-toolkit/src/sugar/tutorius/tests/coretests.py +++ /dev/null @@ -1,197 +0,0 @@ -# Copyright (C) 2009, Tutorius.org -# Copyright (C) 2009, Michael Janelle-Montcalm <michael.jmontcalm@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 -""" -Core Tests - -This module contains all the tests that pertain to the usage of the Tutorius -Core. This means that the Event Filters, the Finite State Machine and all the -related elements and interfaces are tested here. - -""" - -import unittest - -import logging -from sugar.tutorius.actions import Action, OnceWrapper -from sugar.tutorius.core import * -from sugar.tutorius.filters import * - -# Helper classes to help testing -class SimpleTutorial(Tutorial): - """ - Fake tutorial - """ - def __init__(self, start_name="INIT"): - #Tutorial.__init__(self, "Simple Tutorial", None) - self.current_state_name = start_name - self.activity = "TODO : This should be an activity" - - def set_state(self, name): - self.current_state_name = name - -class TrueWhileActiveAction(Action): - """ - This action's active member is set to True after a do and to False after - an undo. - - Used to verify that a State correctly triggers the do and undo actions. - """ - def __init__(self): - self.active = False - - def do(self): - self.active = True - - def undo(self): - self.active = False - - -class CountAction(Action): - """ - This action counts how many times it's do and undo methods get called - """ - def __init__(self): - self.do_count = 0 - self.undo_count = 0 - - def do(self): - self.do_count += 1 - - def undo(self): - self.undo_count += 1 - -class TriggerEventFilter(EventFilter): - """ - This event filter can be triggered by simply calling its execute 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 - -class OnceWrapperTests(unittest.TestCase): - def test_onceaction_toggle(self): - """ - Validate that the OnceWrapper wrapper works properly using the - CountAction - """ - act = CountAction() - wrap = OnceWrapper(act) - - assert act.do_count == 0, "do() should not have been called in __init__()" - assert act.undo_count == 0, "undo() should not have been called in __init__()" - - wrap.undo() - - assert act.undo_count == 0, "undo() should not be called if do() has not been called" - - wrap.do() - assert act.do_count == 1, "do() should have been called once" - - wrap.do() - assert act.do_count == 1, "do() should have been called only once" - - wrap.undo() - assert act.undo_count == 1, "undo() should have been called once" - - wrap.undo() - assert act.undo_count == 1, "undo() should have been called only once" - - -# State testing class -class StateTest(unittest.TestCase): - """ - This class has to test the State interface as well as the expected - functionality. - """ - - def test_action_toggle(self): - """ - Validate that the actions are properly done on setup and undone on - teardown. - - Pretty awesome. - """ - act = TrueWhileActiveAction() - - state = State("action_test", action_list=[act]) - - assert act.active == False, "Action is not initialized properly" - - state.setup() - - assert act.active == True, "Action was not triggered properly" - - state.teardown() - - assert act.active == False, "Action was not undone properly" - - def test_event_filter(self): - """ - Tests the fact that the event filters are correctly installed on setup - and uninstalled on teardown. - """ - event_filter = TriggerEventFilter("second_state") - - state = State("event_test", event_filter_list=[event_filter]) - state.set_tutorial(SimpleTutorial()) - - assert event_filter.toggle_on_callback == False, "Wrong init of event_filter" - assert event_filter._callback == None, "Event filter has a registered callback before installing handlers" - - state.setup() - - assert event_filter._callback != None, "Event filter did not register callback!" - - # 'Trigger' the event - This is more like a EventFilter test. - event_filter.do_callback() - - assert event_filter.toggle_on_callback == True, "Event filter did not execute callback" - - state.teardown() - - assert event_filter._callback == None, "Event filter did not remove callback properly" - - def test_warning_set_tutorial_twice(self): - """ - Calls set_tutorial twice and expects a warning on the second. - """ - state = State("start_state") - tut = SimpleTutorial("First") - tut2 = SimpleTutorial("Second") - - state.set_tutorial(tut) - - try: - state.set_tutorial(tut2) - assert False, "No RuntimeWarning was raised on second set_tutorial" - except : - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/sugar-toolkit/src/sugar/tutorius/tests/coretests.pyc b/sugar-toolkit/src/sugar/tutorius/tests/coretests.pyc Binary files differdeleted file mode 100644 index 5adf79e..0000000 --- a/sugar-toolkit/src/sugar/tutorius/tests/coretests.pyc +++ /dev/null diff --git a/sugar-toolkit/src/sugar/tutorius/tests/overlaytests.py b/sugar-toolkit/src/sugar/tutorius/tests/overlaytests.py deleted file mode 100644 index b5fd209..0000000 --- a/sugar-toolkit/src/sugar/tutorius/tests/overlaytests.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (C) 2009, Tutorius.org -# Copyright (C) 2009, Simon Poirier <simpoir@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 -""" -GUI Tests - -This module contains all the tests that pertain to the usage of the Tutorius -overlay mechanism used to display objects on top of the application. -""" - -import unittest - -import logging -import gtk, gobject -from sugar.tutorius.actions import Action, BubbleMessage -import sugar.tutorius.overlayer as overlayer - -class CanvasDrawable(object): - def __init__(self): - self._no_expose = False - self.exposition_count = 0 - def _set_no_expose(self, value): - self._no_expose = value - def draw_with_context(self, context): - self.exposition_count += 1 - no_expose = property(fset=_set_no_expose) - - -class OverlayerTest(unittest.TestCase): - def test_cairodrawable_iface(self): - """ - Quickly validates that all our cairo widgets have a minimal interface - implemented. - """ - drawables = [overlayer.TextBubble] - for widget in drawables: - for attr in filter(lambda s:s[0]!='_', dir(CanvasDrawable)): - assert hasattr(widget, attr), \ - "%s not implementing CanvasDrawable iface"%widget.__name__ - - - def test_drawn(self): - """ - Ensures a cairo widget draw method is called at least once in - a real gui app. - """ - win = gtk.Window(type=gtk.WINDOW_TOPLEVEL) - - btn = gtk.Button() - btn.show() - overlay = overlayer.Overlayer(btn) - win.add(overlay) - # let's also try to draw substitute button label - lbl = overlayer.TextBubble("test!") - assert lbl.label == 'test!', \ - "label property mismatch" - btn.show() - lbl.show() - btn.add(lbl) - - lbl.no_expose = True - assert lbl.no_expose, "wrong no_expose evaluation" - lbl.no_expose = False - assert not lbl.no_expose, "wrong no_expose evaluation" - - - widget = overlayer.TextBubble("testing msg!", tailpos=(10,-20)) - widget.exposition_count = 0 - # override draw method - def counter(ctx, self=widget): - self.exposition_count += 1 - self.real_exposer(ctx) - widget.real_exposer = widget.draw_with_context - widget.draw_with_context = counter - # centering allows to test the blending with the label - overlay.put(widget, 50, 50) - widget.show() - assert widget.no_expose, \ - "Overlay should overide exposition handling of widget" - assert not lbl.no_expose, \ - "Non-overlayed cairo should expose as usual" - - # force widget realization - # the child is flagged to be redrawn, the overlay should redraw too. - win.set_default_size(100, 100) - win.show() - - while gtk.events_pending(): - gtk.main_iteration(block=False) - # visual validation: there should be 2 visible bubbles, one as label, - # one as overlay - import time - time.sleep(1) - # as x11 events are asynchronous, wait a bit before assuming it went - # wrong. - while gtk.events_pending(): - gtk.main_iteration(block=False) - assert widget.exposition_count>0, "overlay widget should expose" - - -if __name__ == "__main__": - unittest.main() diff --git a/sugar-toolkit/src/sugar/tutorius/tests/overlaytests.pyc b/sugar-toolkit/src/sugar/tutorius/tests/overlaytests.pyc Binary files differdeleted file mode 100644 index 8d7d533..0000000 --- a/sugar-toolkit/src/sugar/tutorius/tests/overlaytests.pyc +++ /dev/null diff --git a/sugar-toolkit/src/sugar/tutorius/tests/run-tests.py b/sugar-toolkit/src/sugar/tutorius/tests/run-tests.py deleted file mode 100755 index 74efd64..0000000 --- a/sugar-toolkit/src/sugar/tutorius/tests/run-tests.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/python -# This is a dumb script to run tests on the sugar-jhbuild installed files -# The path added is the default path for the jhbuild build - -import os, sys -sys.path.insert(0, - os.path.abspath("../../../../../../install/lib/python2.5/site-packages/") -) -import unittest -from coretests import * - -unittest.main() diff --git a/sugar-toolkit/src/sugar/tutorius/testwin.py b/sugar-toolkit/src/sugar/tutorius/testwin.py deleted file mode 100644 index ef92b7f..0000000 --- a/sugar-toolkit/src/sugar/tutorius/testwin.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python -# 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 gtk -import dragbox -import textbubble - -box = None - -def _destroy(widget, data=None): - gtk.main_quit() - -def _delete_event(widget, event, data=None): - print "quitting" - return False - -def blublu(widget, data=""): - print data - -def _drag_toggle(widget, data=None): - global box - box.dragMode = not box.dragMode - - -def addBtn(widget, data, bubble=0, btns=[0]): - if bubble == 1: - bt = textbubble.TextBubble("Bubble(%d)"%btns[0]) - else: - bt = gtk.Button("Bubble(%d)"%btns[0]) - ##bt.set_size_request(60,40) - bt.show() - data.attach(bt) - btns[0] += 1 - -def main(): - global box - win = gtk.Window(type=gtk.WINDOW_TOPLEVEL) - win.connect("delete_event", _delete_event) - win.connect("destroy", _destroy) - - win.set_default_size(800,600) - - vbox = gtk.VBox() - vbox.show() - win.add(vbox) - - check = gtk.CheckButton(label="dragMode") - check.connect("toggled", _drag_toggle) - check.show() - vbox.pack_start(check, expand=False) - - btnadd = gtk.Button("Add Bubble") - btnadd.show() - vbox.pack_start(btnadd, expand=False) - btnadd2 = gtk.Button("Add Button") - btnadd2.show() - vbox.pack_start(btnadd2, expand=False) - -## bubble = textbubble.TextBubble("Bubbles!") -## bubble.show() -## bubble.set_size_request(40,40) -## vbox.pack_start(bubble, expand=False) - - box = dragbox.DragBox() - box.set_border_width(10) - box.show() - vbox.pack_start(box, expand=True, fill=True) - - btnadd.connect("clicked", addBtn, box, 1) - btnadd2.connect("clicked", addBtn, box) - - win.show() - gtk.main() - - -if __name__ == "__main__": - main() - diff --git a/sugar-toolkit/src/sugar/tutorius/textbubble.py b/sugar-toolkit/src/sugar/tutorius/textbubble.py deleted file mode 100644 index e09b298..0000000 --- a/sugar-toolkit/src/sugar/tutorius/textbubble.py +++ /dev/null @@ -1,109 +0,0 @@ -# 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 represents TextBubble widget. Also, it aims to be a short example -of drawing with Cairo. -""" - -import gtk -from math import pi as M_PI -import cairo - -# FIXME set as subclass of gtk.Widget, not EventBox -class TextBubble(gtk.EventBox): - def __init__(self, label): - gtk.EventBox.__init__(self) - - ##self.set_app_paintable(True) # else may be blank - # FIXME ensure previous call does not interfere with widget stacking - self.label = label - self.lineWidth = 5 - - self.connect("expose-event", self._on_expose) - - def __draw_with_cairo__(self, context): - """ - - """ - pass - - def _on_expose(self, widget, event): - """Redraw event callback.""" - # TODO - ctx = self.window.cairo_create() - - # set drawing region. Useless since this widget has its own window. - ##region = gtk.gdk.region_rectangle(self.allocation) - ##region.intersect(gtk.gdk.region_rectangle(event.area)) - ##ctx.region(region) - ##ctx.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) - ##ctx.clip() - - ##import pdb; pdb.set_trace() - ##ctx.set_operator(cairo.OPERATOR_CLEAR) - ##ctx.paint() - ##ctx.set_operator(cairo.OPERATOR_OVER) - - width = self.allocation.width - height = self.allocation.height - xradius = width/2 - yradius = height/2 - width -= self.lineWidth - height -= self.lineWidth - ctx.move_to(self.lineWidth, yradius) - ctx.curve_to(self.lineWidth, self.lineWidth, - self.lineWidth, self.lineWidth, xradius, self.lineWidth) - ctx.curve_to(width, self.lineWidth, - width, self.lineWidth, width, yradius) - ctx.curve_to(width, height, width, height, xradius, height) - ctx.curve_to(self.lineWidth, height, - self.lineWidth, height, self.lineWidth, yradius) - ctx.set_source_rgb(1.0, 1.0, 1.0) - ctx.fill_preserve() - ctx.set_line_width(self.lineWidth) - ctx.set_source_rgb(0.0, 0.0, 0.0) - ctx.stroke() - - _, _, textWidth, textHeight, _, _ = ctx.text_extents(self._label) - ctx.move_to(int((self.allocation.width-textWidth)/2), - int((self.allocation.height+textHeight)/2)) - ctx.text_path(self._label) - ctx.fill() - - return True - - - def _set_label(self, value): - """Sets the label and flags the widget to be redrawn.""" - self._label = value - # FIXME hack to calculate size. necessary because may not have been - # realized - surf = cairo.SVGSurface("/dev/null", 0, 0) - ctx = cairo.Context(surf) - _, _, width, height, _, _ = ctx.text_extents(self._label) - del ctx, surf - - # FIXME bogus values follows - self.set_size_request(int(width+20), int(height+40)) - # TODO test changing a realized label - - def _get_label(self): - """Getter method for the label property""" - return self._label - - label = property(fget=_get_label, fset=_set_label,\ - doc="Text label which is to be painted on the top of the widget") - diff --git a/sugar-toolkit/src/sugar/tutorius/textbubble.pyc b/sugar-toolkit/src/sugar/tutorius/textbubble.pyc Binary files differdeleted file mode 100644 index c16cb0f..0000000 --- a/sugar-toolkit/src/sugar/tutorius/textbubble.pyc +++ /dev/null diff --git a/sugar-toolkit/src/sugar/tutorius/tutorial.py b/sugar-toolkit/src/sugar/tutorius/tutorial.py deleted file mode 100644 index 5236127..0000000 --- a/sugar-toolkit/src/sugar/tutorius/tutorial.py +++ /dev/null @@ -1,162 +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 - - |