- calls insertSourceAfter() when an user drops item to timeline
- calls removeSource() when user deletes item from timeline
- calls moveSource() when user moves a source to a new position
- responds to the "source_added" signal by creating a new source widget and adding it to the timeline
- responds to the "source_removed" signal by removing its widget from the timeline
- responds to the "condensed_list_changed" signal by updating items to their new position
When the user clicks on an item in the timeline, the source will be moved to the top layer of the canvas (so that it shows above other objects as it is moved. The user can then drag it freely in the x direction within the bounds of the canvas, but it will be completely constrained in the y direction.
If the object is moved beyond a certain threshold to the right or left, the position of the nearest object to the one being moved will be swapped (i.e. the order of the objects will change, but the object being dragged will still be under the control of the mouse). The operation finishes when the user releases the mouse.
Two ways to do this:
- When the threshold value is reached, simply call moveSource() to exchange the positions of both sources. The advantage of this approach is that the UI updates automatically when the composition emits the "condensed-list-changed" signal. One possibly negative side-effect is that the object the user is dragging will suddenly "jump" in to position. Another potential side-effect is that the "condensed-list-changed" signal might be delayed for some reason, leaving the timeline in a sorry state even after the user releases the mouse.
- When the threshold value is reached, only swap the sources visually. Save the proposed changes until after the user releases the mouse. Then call moveSource() to move the source. This avoids the "jumping" side effect, but introduces a different problem. The visual timeline and back end will be temporarily inconsistent. If the "consensed-list-changed" signal is delayed, then the user's changes are incorrectly displayed. We can get around this by automatically restoring the list to its original state after the user releases the mouse. This could also be confusing: the user sees their clips move into a new position, then move back to their original position after releasing the mouse, then move back to the new position after the signal arrives.
My goal for my first commit is to come up with a drop-in replacement for the existing timeline. But, in the interest of being forward thinking, there's a design constraint here I almost forgot to consider: Transition widgets. Handling child widgets of different sizes and aspect ratios will not be so hard, but transitions are only supposed to go between two sources. How can I easily enforce this constraint? Maybe by fiddling with the threshold values, but remember that transitions are optional. I could use a mandatory space between sources, but to be honest I really hate that idea. I'll sleep on it for now. One thing at a time.