Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tutorius/creator.py
diff options
context:
space:
mode:
Diffstat (limited to 'tutorius/creator.py')
-rw-r--r--tutorius/creator.py198
1 files changed, 111 insertions, 87 deletions
diff --git a/tutorius/creator.py b/tutorius/creator.py
index fd9f1e8..e8182b0 100644
--- a/tutorius/creator.py
+++ b/tutorius/creator.py
@@ -27,27 +27,68 @@ from gettext import gettext as T
import uuid
import os
-from sugar.graphics import icon
+from sugar.graphics import icon, style
+import jarabe.frame
from . import overlayer, gtkutils, vault, addon
from .services import ObjectStore
from .tutorial import Tutorial
from . import viewer
from .propwidgets import TextInputDialog
+from . import TProbe
-class Creator(object):
+from dbus import SessionBus
+from dbus.service import method, Object, BusName
+
+BUS_PATH = "/org/tutorius/Creator"
+BUS_NAME = "org.tutorius.Creator"
+
+def default_creator():
+ """
+ The Creator class is a singleton. There can never be more than one creator
+ at a time. This method returns a new instance only if none
+ already exists. Else, the existing instance is returned.
+ """
+ Creator._instance = Creator._instance or Creator()
+ return Creator._instance
+
+def get_creator_proxy():
+ """
+ Returns a Creator dbus proxy for inter-process events.
+ """
+ bus = dbus.SessionBus()
+ proxy = bus.get_object(BUS_NAME, BUS_PATH)
+ return proxy
+
+class Creator(Object):
"""
- Class acting as a bridge between the creator, serialization and core
- classes. This contains most of the UI part of the editor.
+ Class acting as a controller for the tutorial edition.
"""
- def __init__(self, activity, tutorial=None):
+
+ _instance = None
+
+ def __init__(self):
+ bus_name = BusName(BUS_NAME, bus=SessionBus())
+ Object.__init__(self, bus_name, BUS_PATH)
+
+ self.tuto = None
+ self.is_authoring = False
+ Creator._instance = self
+ self._probe_mgr = TProbe.ProbeManager.default_instance
+
+ def start_authoring(self, tutorial=None):
"""
- Instanciate a tutorial creator for the activity.
+ Start authoring a tutorial.
- @param activity to bind the creator to
- @param tutorial an existing tutorial to edit, or None to create one
+ @type tutorial: str or None
+ @param tutorial: the unique identifier to an existing tutorial to
+ modify, or None to create a new one.
"""
- self._activity = activity
+ if self.is_authoring:
+ raise Exception("Already authoring")
+
+ self.is_authoring = True
+
if not tutorial:
self._tutorial = Tutorial('Untitled')
self._state = self._tutorial.add_state()
@@ -68,21 +109,15 @@ class Creator(object):
self._action_panel = None
self._current_filter = None
- self._intro_mask = None
- self._intro_handle = None
- allocation = self._activity.get_allocation()
- self._width = allocation.width
- self._height = allocation.height
self._selected_widget = None
self._eventmenu = None
self.tuto = None
self._guid = None
self.metadata = None
- self._hlmask = overlayer.Rectangle(None, (1.0, 0.0, 0.0, 0.5))
- self._activity._overlayer.put(self._hlmask, 0, 0)
+ frame = jarabe.frame.get_view()
- self._propedit = ToolBox(self._activity)
+ self._propedit = ToolBox(None)
self._propedit.tree.signal_autoconnect({
'on_quit_clicked': self._cleanup_cb,
'on_save_clicked': self.save,
@@ -90,18 +125,39 @@ class Creator(object):
'on_event_activate': self._add_event_cb,
})
self._propedit.window.move(
- gtk.gdk.screen_width()-self._propedit.window.get_allocation().width,
- 100)
-
+ gtk.gdk.screen_width()-self._propedit.window.get_allocation().width\
+ -style.GRID_CELL_SIZE,
+ style.GRID_CELL_SIZE)
+ self._propedit.window.connect('enter-notify-event',
+ frame._enter_notify_cb)
+ self._propedit.window.connect('leave-notify-event',
+ frame._leave_notify_cb)
self._overview = viewer.Viewer(self._tutorial, self)
- self._overview.win.set_transient_for(self._activity)
+ self._overview.win.set_transient_for(frame._bottom_panel)
+ self._overview.win.connect('enter-notify-event',
+ frame._enter_notify_cb)
+ self._overview.win.connect('leave-notify-event',
+ frame._leave_notify_cb)
- self._overview.win.move(0, gtk.gdk.screen_height()- \
- self._overview.win.get_allocation().height)
+ self._overview.win.move(style.GRID_CELL_SIZE,
+ gtk.gdk.screen_height()-style.GRID_CELL_SIZE \
+ -self._overview.win.get_allocation().height)
self._transitions = dict()
+ # FIXME : remove when probemgr completed
+ #self._probe_mgr.attach('org.laptop.Calculate')
+ self._probe_mgr._current_activity = 'org.laptop.Calculate'
+
+ def _tool_enter_notify_cb(self, window, event):
+ frame = jarabe.frame.get_view()
+ frame._bottom_panel.hover = True
+
+ def _tool_leave_notify_cb(self, window, event):
+ frame = jarabe.frame.get_view()
+ frame._bottom_panel.hover = False
+
def _update_next_state(self, state, event, next_state):
self._transitions[event] = next_state
@@ -121,7 +177,8 @@ class Creator(object):
.get(action, None)
if not action_obj:
return False
- action_obj.exit_editmode()
+ #action_obj.exit_editmode()
+ self._probe_mgr.uninstall(action_obj, is_editing=True)
self._tutorial.delete_action(action)
self._overview.win.queue_draw()
return True
@@ -169,7 +226,8 @@ class Creator(object):
return
for action in self._tutorial.get_action_dict(self._state).values():
- action.exit_editmode()
+ #action.exit_editmode()
+ self._probe_mgr.uninstall(action, is_editing=True)
self._state = state_name
state_actions = self._tutorial.get_action_dict(self._state).values()
@@ -194,54 +252,20 @@ class Creator(object):
"""
# undo actions so they don't persist through step editing
for action in self._state.get_action_list():
- action.exit_editmode()
- self._hlmask.covered = None
+ self._probe_mgr.uninstall(action, is_editing=True)
+ #action.exit_editmode()
self._propedit.action = None
- self._activity.queue_draw()
-
- def _intro_cb(self, widget, evt):
- """
- Callback for capture of widget events, when in introspect mode.
- """
- if evt.type == gtk.gdk.BUTTON_PRESS:
- # widget has focus, let's hilight it
- win = gtk.gdk.display_get_default().get_window_at_pointer()
- click_wdg = win[0].get_user_data()
- if not click_wdg.is_ancestor(self._activity._overlayer):
- # as popups are not (yet) supported, it would break
- # badly if we were to play with a widget not in the
- # hierarchy.
- return
- for hole in self._intro_mask.pass_thru:
- self._intro_mask.mask(hole)
- self._intro_mask.unmask(click_wdg)
- self._selected_widget = gtkutils.raddr_lookup(click_wdg)
-
- if self._eventmenu:
- self._eventmenu.destroy()
- self._eventmenu = gtk.Menu()
- menuitem = gtk.MenuItem(label=type(click_wdg).__name__)
- menuitem.set_sensitive(False)
- self._eventmenu.append(menuitem)
- self._eventmenu.append(gtk.MenuItem())
-
- for item in gobject.signal_list_names(click_wdg):
- menuitem = gtk.MenuItem(label=item)
- menuitem.connect("activate", self._evfilt_cb, item)
- self._eventmenu.append(menuitem)
- self._eventmenu.show_all()
- self._eventmenu.popup(None, None, None, evt.button, evt.time)
- self._activity.queue_draw()
+ #self._activity.queue_draw()
def _add_action_cb(self, widget, path):
"""Callback for the action creation toolbar tool"""
action_type = self._propedit.actions_list[path][ToolBox.ICON_NAME]
action = addon.create(action_type)
- action.enter_editmode()
+ self._probe_mgr.install(action, is_editing=True)
self._tutorial.add_action(self._state, action)
# FIXME: replace following with event catching
- action._drag._eventbox.connect_after(
- "button-release-event", self._action_refresh_cb, action)
+ #action._drag._eventbox.connect_after(
+ # "button-release-event", self._action_refresh_cb, action)
self._overview.win.queue_draw()
def _add_event_cb(self, widget, path):
@@ -271,7 +295,7 @@ class Creator(object):
meta = addon.get_addon_meta(addonname)
for propname in meta['mandatory_props']:
prop = getattr(type(event), propname)
- prop.widget_class.run_dialog(self._activity, event, propname)
+ prop.widget_class.run_dialog(None, event, propname)
event_filters = self._tutorial.get_transition_dict(self._state)
@@ -296,17 +320,22 @@ class Creator(object):
self.set_insertion_point(new_state)
+ def properties_changed(self, action, properties):
+ pass
+
def _action_refresh_cb(self, widget, evt, action):
"""
Callback for refreshing properties values and notifying the
property dialog of the new values.
"""
- action.exit_editmode()
- action.enter_editmode()
- self._activity.queue_draw()
+ self._probe_mgr.uninstall(action, is_editing=True)
+ #action.exit_editmode()
+ self._probe_mgr.install(action, is_editing=True)
+ #action.enter_editmode()
+ #self._activity.queue_draw()
# TODO: replace following with event catching
- action._drag._eventbox.connect_after(
- "button-release-event", self._action_refresh_cb, action)
+ #action._drag._eventbox.connect_after(
+ # "button-release-event", self._action_refresh_cb, action)
self._propedit.action = action
self._overview.win.queue_draw()
@@ -319,11 +348,12 @@ class Creator(object):
"""
# undo actions so they don't persist through step editing
for action in self._tutorial.get_action_dict(self._state).values():
- action.exit_editmode()
+ #action.exit_editmode()
+ self._probe_mgr.uninstall(action, is_editing=True)
if kwargs.get('force', False):
dialog = gtk.MessageDialog(
- parent=self._activity,
+ parent=None,
flags=gtk.DIALOG_MODAL,
type=gtk.MESSAGE_QUESTION,
buttons=gtk.BUTTONS_YES_NO,
@@ -335,14 +365,9 @@ class Creator(object):
self.save()
# remove UI remains
- self._hlmask.covered = None
- self._activity._overlayer.remove(self._hlmask)
- self._hlmask.destroy()
- self._hlmask = None
self._propedit.destroy()
self._overview.destroy()
- self._activity.queue_draw()
- del self._activity._creator
+ self.is_authoring = False
def save(self, widget=None):
"""
@@ -369,16 +394,11 @@ class Creator(object):
vault.Vault.saveTutorial(self._tutorial, self._metadata)
-
- def launch(*args, **kwargs):
- """
- Launch and attach a creator to the currently running activity.
- """
- activity = ObjectStore().activity
- if not hasattr(activity, "_creator"):
- activity._creator = Creator(activity)
+ def launch(self, *args):
+ assert False, "REMOVE THIS CALL!!!"
launch = staticmethod(launch)
+
class ToolBox(object):
"""
Palette window for edition tools, including the actions, states and
@@ -396,10 +416,13 @@ class ToolBox(object):
'ui', 'creator.glade')
self.tree = gtk.glade.XML(glade_file)
self.window = self.tree.get_widget('mainwindow')
+ self.window.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_TOOLBAR_GREY.get_gdk_color())
self._propbox = self.tree.get_widget('propbox')
self._propedits = []
self.window.set_transient_for(parent)
+ self.window.set_keep_above(True)
self._action = None
self.actions_list = gtk.ListStore(str, gtk.gdk.Pixbuf, str, str)
@@ -494,6 +517,7 @@ class ToolBox(object):
self.__parent._creator._action_refresh_cb(None, None, self._action)
+
# The purpose of this function is to reformat text, as current IconView
# implentation does not insert carriage returns on long lines.
# To preserve layout, this call reformat text to fit in small space under an