Index: pitivi/ui/tracklayer.py =================================================================== --- pitivi/ui/tracklayer.py (revision 1108) +++ pitivi/ui/tracklayer.py (working copy) @@ -55,7 +55,19 @@ border = 5 effectgutter = 5 layergutter = 5 + handlesize = 10 # how big an offest in pixels should be reserved + # for punch in and punch out handles + # TODO: get this value somehow from the gtk+ theme + # _modifyState states + # it should be noted that extending the punch out time beyond the clip + # should repeat the clip from the start (used for looped animations or + # stills) + (MODIFY_NONE, # no modification happening + MODIFY_MOVE, # moving source in timeline + MODIFY_IN, # modifying the punch in time for the clip + MODIFY_OUT) = range(4) # modifying the punch out time for the clip + def __init__(self, layerInfo, hadj): gst.log("new TrackLayer for composition %r" % layerInfo.composition) gtk.Layout.__init__(self) @@ -84,10 +96,12 @@ self.connect('button-release-event', self._buttonReleaseEventCb) self._mouseDownPosition = [None, None] - self._movingSource = None + self._modifyingSource = None self._origSourcePosition = None self._requestedPosition = None - self._currentlyMoving = False + self._requestedDuration = None + self._currentlyModifying = False + self._modificationState = self.MODIFY_NONE self._popupMenu = gtk.Menu() deleteitem = gtk.MenuItem(_("Remove")) @@ -108,8 +122,8 @@ def _deleteMenuItemCb(self, unused_menuitem): # remove currently selected source gst.log("removing source") - self.layerInfo.composition.removeSource(self._movingSource) - self._movingSource = None + self.layerInfo.composition.removeSource(self._modifyingSource) + self._modifyingSource = None def _cutMenuItemCb(self, unused_menuitem): gst.log("cut at position %s" % gst.TIME_ARGS(self.position)) @@ -240,10 +254,11 @@ x, y, x, y, width, height) return gtk.Layout.do_expose_event(self, event) - def _moveTimeoutCb(self): - self._currentlyMoving = False - if self._requestedPosition and self._movingSource: - self._movingSource.setStartDurationTime(start = self._requestedPosition) + def _modifyTimeoutCb(self): + self._currentlyModifying = False + if self._requestedPosition and self._modifyingSource: + self._modifyingSource.setStartDurationTime(start = self._requestedPosition, + duration = self._requestedDuration) def do_motion_notify_event(self, event): gst.debug("motion x:%d y:%d" % (event.x , event.y)) @@ -251,17 +266,38 @@ diffx = event.x - self._mouseDownPosition[0] diffy = event.y - self._mouseDownPosition[1] gst.debug("we moved by x:%d, y:%d" % (diffx, diffy)) - if self._movingSource: - newstart = self._origSourcePosition + self.pixelToNs(diffx) + + if self._modifyingSource: + newstart = self._origSourcePosition + print self._modificationState + if (self._modificationState == self.MODIFY_MOVE or + self._modificationState == self.MODIFY_IN): + newstart += self.pixelToNs(diffx) + + newduration = self._origSourceDuration + if self._modificationState == self.MODIFY_IN: + newduration -= self.pixelToNs(diffx) + elif self._modificationState == self.MODIFY_OUT: + newduration += self.pixelToNs(diffx) + # FIXME : implement blocking !! if newstart < 0: newstart = 0 + + if newduration < 1: + newduration = 1 + gst.debug("we should move the source to %s" % gst.TIME_ARGS(newstart)) - if not self._currentlyMoving: - self._currentlyMoving = True - gobject.timeout_add(80, self._moveTimeoutCb) - self._movingSource.setStartDurationTime(start = newstart) + + + if not self._currentlyModifying: + self._currentlyModifying = True + gobject.timeout_add(80, self._modifyTimeoutCb) + print newstart, newduration + self._modifyingSource.setStartDurationTime(start = newstart, + duration = newduration) self._requestedPosition = newstart + self._requestedDuration = newduration ## Drawing methods @@ -360,23 +396,37 @@ gst.log("Mouse down at %d / %d" % (event.x, event.y)) source = self._findSourceAtPosition(event.x) if source: - gst.log("we are moving %s" % source) - self._movingSource = source + gst.log("we are modifying %s" % source) + widget = self.sources[source] + minv = widget.getPixelPosition() + maxv = minv + widget.getPixelWidth() + if event.x < minv + self.handlesize: + self._modificationState = self.MODIFY_IN + elif event.x > maxv - self.handlesize: + self._modificationState = self.MODIFY_OUT + else: + self._modificationState = self.MODIFY_MOVE + + self._modifyingSource = source self._origSourcePosition = source.start + self._origSourceDuration = source.duration elif event.button == 3: source = self._findSourceAtPosition(event.x) if source: - gst.log("we are moving %s" % source) - self._movingSource = source + gst.log("we are modifying %s" % source) + self._modifyingSource = source self._origSourcePosition = source.start + self._origSourceDuration = source.duration self._popupMenu.popup(None,None,None, event.button, event.time) def _buttonReleaseEventCb(self, unused_layout, unused_event): gst.log("Mouse up !") # reset values self._mouseDownPosition = [None,None] - self._movingSource = None + self._modifyingSource = None self._origSourcePosition = None + self._origSourceDuration = None + self._modificationState = self.MODIFY_NONE def _findSourceAtPosition(self, position): """