Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/sugar/tutorius/actions.py
diff options
context:
space:
mode:
authorSimon Poirier <simpoir@gmail.com>2009-05-18 20:27:41 (GMT)
committer Simon Poirier <simpoir@gmail.com>2009-06-01 04:50:00 (GMT)
commitf347ec202fe5b4404fa380694d7fe3d3d070ae7b (patch)
tree89f10094b90489fc43b8ec209b16d94ff2405147 /src/sugar/tutorius/actions.py
parent6fa568daae3291c7a876cd903f04079a12945dcb (diff)
fixed major missing parts in bundler
integrated bundler to creator tutorial loading still is unusable (fiters don't seem to load)
Diffstat (limited to 'src/sugar/tutorius/actions.py')
-rw-r--r--src/sugar/tutorius/actions.py151
1 files changed, 147 insertions, 4 deletions
diff --git a/src/sugar/tutorius/actions.py b/src/sugar/tutorius/actions.py
index ff7f427..570bff8 100644
--- a/src/sugar/tutorius/actions.py
+++ b/src/sugar/tutorius/actions.py
@@ -24,6 +24,112 @@ import overlayer
from sugar.tutorius.editor import WidgetIdentifier
from sugar.tutorius.services import ObjectStore
from sugar.tutorius.properties import *
+import gtk.gdk
+
+class DragWrapper(object):
+ """Wrapper to allow gtk widgets to be dragged around"""
+ def __init__(self, widget, position, draggable=False):
+ """
+ Creates a wrapper to allow gtk widgets to be mouse dragged, if the
+ parent container supports the move() method, like a gtk.Layout.
+ @param widget the widget to enhance with drag capability
+ @param position the widget's position. Will translate the widget if needed
+ @param draggable wether to enable the drag functionality now
+ """
+ self._widget = widget
+ self._eventbox = None
+ self._drag_on = False # whether dragging is enabled
+ self._rel_pos = (0,0) # mouse pos relative to widget
+ self._handles = [] # event handlers
+ self._dragging = False # whether a drag is in progress
+ self.position = position # position of the widget
+
+ self.draggable = draggable
+
+ def _pressed_cb(self, widget, evt):
+ """Callback for start of drag event"""
+ self._eventbox.grab_add()
+ self._dragging = True
+ self._rel_pos = evt.get_coords()
+
+ def _moved_cb(self, widget, evt):
+ """Callback for mouse drag events"""
+ if not self._dragging:
+ return
+
+ # Focus on a widget before dragging another would
+ # create addititonal move event, making the widget jump unexpectedly.
+ # Solution found was to process those focus events before dragging.
+ if gtk.events_pending():
+ return
+
+ xrel, yrel = self._rel_pos
+ xparent, yparent = evt.get_coords()
+ xparent, yparent = widget.translate_coordinates(widget.parent,
+ xparent, yparent)
+ self.position = (xparent-xrel, yparent-yrel)
+ self._widget.parent.move(self._eventbox, *self.position)
+ self._widget.parent.move(self._widget, *self.position)
+ self._widget.parent.queue_draw()
+
+ def _released_cb(self, *args):
+ """Callback for end of drag (mouse release)."""
+ self._eventbox.grab_remove()
+ self._dragging = False
+
+ def _drag_end(self, *args):
+ """Callback for end of drag (stolen focus)."""
+ self._dragging = False
+
+ def set_draggable(self, value):
+ """Setter for the draggable property"""
+ if bool(value) ^ bool(self._drag_on):
+ if value:
+ self._eventbox = gtk.EventBox()
+ self._eventbox.show()
+ self._eventbox.set_visible_window(False)
+ size = self._widget.size_request()
+ self._eventbox.set_size_request(*size)
+ self._widget.parent.put(self._eventbox, *self.position)
+ self._handles.append(self._eventbox.connect(
+ "button-press-event", self._pressed_cb))
+ self._handles.append(self._eventbox.connect(
+ "button-release-event", self._released_cb))
+ self._handles.append(self._eventbox.connect(
+ "motion-notify-event", self._moved_cb))
+ self._handles.append(self._eventbox.connect(
+ "grab-broken-event", self._drag_end))
+ else:
+ while len(self._handles):
+ handle = self._handles.pop()
+ self._eventbox.disconnect(handle)
+ self._eventbox.parent.remove(self._eventbox)
+ self._eventbox.destroy()
+ self._eventbox = None
+ self._drag_on = value
+
+ def get_draggable(self):
+ """Getter for the draggable property"""
+ return self._drag_on
+
+ draggable = property(fset=set_draggable, fget=get_draggable, \
+ doc="Property to enable the draggable behaviour of the widget")
+
+ def set_widget(self, widget):
+ """Setter for the widget property"""
+ if self._dragging or self._drag_on:
+ raise Exception("Can't change widget while dragging is enabled.")
+
+ assert hasattr(widget, "parent"), "wrapped widget should have a parent"
+ parent = widget.parent
+ assert hasattr(parent, "move"), "container of widget need move method"
+ self._widget = widget
+
+ def get_widget(self):
+ """Getter for the widget property"""
+ return self._widget
+
+ widget = property(fset=set_widget, fget=get_widget)
class Action(object):
"""Base class for Actions"""
@@ -56,6 +162,13 @@ class Action(object):
self.properties[i] = getattr(self,i)
return self.properties.keys()
+ def enter_editmode(self, **kwargs):
+ """
+ Enters edit mode. The action should display itself in some way,
+ without affecting the currently running application.
+ """
+ raise NotImplementedError("Not implemented")
+
class OnceWrapper(object):
"""
Wraps a class to perform an action once only
@@ -142,6 +255,7 @@ class BubbleMessage(Action):
self.overlay = None
self._bubble = None
self._speaker = None
+ self.__drag = None
def do(self):
"""
@@ -154,12 +268,14 @@ class BubbleMessage(Action):
# handled either by rendering over them, or by finding different way to
# draw the overlay.
+ if not self.overlay:
+ self.overlay = ObjectStore().activity._overlayer
if not self._bubble:
- x, y = self._position
+ x, y = self.position.value
# 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 = overlayer.TextBubble(text=self.message.value,
+ tailpos=self.tail_pos.value)
self._bubble.show()
self.overlay.put(self._bubble, x, y)
self.overlay.queue_draw()
@@ -171,7 +287,34 @@ class BubbleMessage(Action):
if self._bubble:
self._bubble.destroy()
self._bubble = None
-
+
+ def enter_editmode(self, *args):
+ """
+ Enters edit mode. The action should display itself in some way,
+ without affecting the currently running application.
+ """
+ if not self.overlay:
+ self.overlay = ObjectStore().activity._overlayer
+ assert not self.__drag, "bubble action set to editmode twice"
+ x, y = self.position.value
+ self._bubble = overlayer.TextBubble(text=self.message.value,
+ tailpos=self.tail_pos.value)
+ self.overlay.put(self._bubble, x, y)
+ self._bubble.show()
+
+ self.__drag = DragWrapper(self._bubble, self.position.value, True)
+
+ def exit_editmode(self, *args):
+ x,y = self.__drag.position
+ self.position.set([int(x), int(y)])
+ if self.__drag:
+ self.__drag.draggable = False
+ self.__drag = None
+ if self._bubble:
+ self.overlay.remove(self._bubble)
+ self._bubble = None
+ self.overlay = None
+
class WidgetIdentifyAction(Action):
def __init__(self):
self.activity = None