Example #1
0
 def drag_start(self, item, target, event):
     if not self._view.element.selected:
         self._view.timeline.selection.setToObj(self._view.element, SELECT)
     tx = self._view.props.parent.get_transform()
     # store y offset for later priority calculation
     self._y_offset = tx[5]
     # zero y component of mousdown coordiante
     self._mousedown = Point(self._mousedown[0], 0)
Example #2
0
 def from_event(self, event):
     return Point(*self.convert_from_pixels(event.x, event.y))
Example #3
0
 def pos(self, item):
     bounds = item.get_bounds()
     return Point(bounds.x1, bounds.y1)
Example #4
0
 def to_item_space(self, item, point):
     return Point(*self._canvas.convert_to_item_space(item, *point))
Example #5
0
 def from_item_event(self, item, event):
     return Point(*self._canvas.convert_from_item_space(
         item, *self.from_event(event)))
Example #6
0
 def from_event(self, event):
     """returns the coordinates of an event"""
     return Point(*self._canvas.convert_from_pixels(event.x, event.y))
Example #7
0
class Controller(object):
    """A controller which implements drag-and-drop bahavior on connected view
    objects. Subclasses may override the drag_start, drag_end, pos, and
    set_pos methods"""

    # note we SHOULD be using the gtk function for this, but it doesn't appear
    # to be exposed in pygtk
    __DRAG_THRESHOLD__ = Point(0, 0)

    _view = receiver()

    _dragging = None
    _canvas = None
    _cursor = None
    _ptr_within = False
    _last_click = None
    _initial = None
    _mousedown = None
    _last_event = None
    _pending_drag_start = None
    _pending_drag_end = False
    _shift_down = False
    _control_down = False
    _handle_enter_leave = True
    _handle_mouse_up_down = True
    _handle_motion_notify = True

    def __init__(self, view=None):
        object.__init__(self)
        self._view = view

## convenience functions

    def from_event(self, event):
        """returns the coordinates of an event"""
        return Point(*self._canvas.convert_from_pixels(event.x, event.y))

    def from_item_event(self, item, event):
        return Point(*self._canvas.convert_from_item_space(
            item, *self.from_event(event)))

    def to_item_space(self, item, point):
        return Point(*self._canvas.convert_to_item_space(item, *point))

    def pos(self, item):
        bounds = item.get_bounds()
        return Point(bounds.x1, bounds.y1)

## signal handlers

    @handler(_view, "enter_notify_event")
    def enter_notify_event(self, item, target, event):
        self._event_common(item, target, event)
        self._canvas.grab_focus(item)
        if self._cursor and item is target:
            event.window.set_cursor(self._cursor)
        if not self._dragging:
            self.enter(item, target)
        self._ptr_within = True
        return self._handle_enter_leave or self._dragging

    @handler(_view, "leave_notify_event")
    def leave_notify_event(self, item, target, event):
        self._event_common(item, target, event)
        self._canvas.keyboard_ungrab(item, event.time)
        self._ptr_within = False
        if not self._dragging:
            self.leave(item, target)
            event.window.set_cursor(ARROW)
        return self._handle_enter_leave or self._dragging

    @handler(_view, "button_press_event")
    def button_press_event(self, item, target, event):
        self._event_common(item, target, event)
        if not self._canvas:
            self._canvas = item.get_canvas()
        self._mousedown = self.pos(item) - self.transform(
            self.from_item_event(item, event))
        self._dragging = target
        self._initial = self.pos(target)
        self._pending_drag_start = (item, target, event)
        return self._handle_mouse_up_down

    @handler(_view, "motion_notify_event")
    def motion_notify_event(self, item, target, event):
        self._event_common(item, target, event)
        if self._dragging:
            if self._pending_drag_start is not None:
                pending_drag_start, self._pending_drag_start = \
                        self._pending_drag_start, None
                self._pending_drag_end = True
                self._drag_start(*pending_drag_start)

            self.set_pos(
                self._dragging,
                self.transform(self._mousedown +
                               self.from_item_event(item, event)))
            return self._handle_motion_notify
        else:
            self.hover(item, target, event)
        return False

    @handler(_view, "button_release_event")
    def button_release_event(self, item, target, event):
        self._event_common(item, target, event)
        self._drag_end(item, self._dragging, event)
        self._dragging = None
        return self._handle_mouse_up_down

    @handler(_view, "key_press_event")
    def key_press_event(self, item, target, event):
        self._event_common(item, target, event)
        kv = event.keyval
        if kv in (gtk.keysyms.Shift_L, gtk.keysyms.Shift_R):
            self._shift_down = True
        elif kv in (gtk.keysyms.Control_L, gtk.keysyms.Control_R):
            self._control_down = True
        return self.key_press(kv)

    @handler(_view, "key_release_event")
    def key_release_event(self, item, target, event):
        self._event_common(item, target, event)
        kv = event.keyval
        if kv in (gtk.keysyms.Shift_L, gtk.keysyms.Shift_R):
            self._shift_down = False
        elif kv in (gtk.keysyms.Control_L, gtk.keysyms.Control_R):
            self._control_down = False
        return self.key_release(kv)

## internal callbacks

    def _event_common(self, item, target, event):
        if not self._canvas:
            self._canvas = item.get_canvas()
        self._last_event = event
        s = event.get_state()
        self._shift_down = s & gtk.gdk.SHIFT_MASK
        self._control_down = s & gtk.gdk.CONTROL_MASK

    def _drag_start(self, item, target, event):
        self.drag_start(item, target, event)

    def _drag_end(self, item, target, event):
        self._pending_drag_start = None
        pending_drag_end, self._pending_drag_end = self._pending_drag_end, False
        if pending_drag_end:
            self.drag_end(item, target, event)

        if self._ptr_within and self._drag_threshold():
            point = self.from_item_event(item, event)
            if self._last_click and (event.time - self._last_click < 400):
                self.double_click(point)
            else:
                self.click(point)
            self._last_click = event.time
            event.window.set_cursor(self._cursor)
        else:
            event.window.set_cursor(ARROW)

    def _drag_threshold(self):
        last = self.pos(self._dragging)
        difference = abs(self._initial - last)
        if abs(self._initial - last) > self.__DRAG_THRESHOLD__:
            return False
        return True

## protected interface for subclasses

    def click(self, pos):
        pass

    def double_click(self, pos):
        pass

    def drag_start(self, item, target, event):
        pass

    def drag_end(self, item, target, event):
        pass

    def set_pos(self, obj, pos):
        obj.props.x, obj.props.y = pos

    def transform(self, pos):
        return pos

    def enter(self, item, target):
        pass

    def leave(self, item, target):
        pass

    def key_press(self, keyval):
        pass

    def key_release(self, keyval):
        pass

    def hover(self, item, target, event):
        pass
Example #8
0
 def from_event(self, event):
     x, y = event.x, event.y
     x += self.app.gui.timeline.hadj.get_value()
     return Point(*self.convert_from_pixels(x, y))