Commit df5486ed authored by luyikei's avatar luyikei

Timeline: Always show the top and the left items

parent 8edb932f
......@@ -67,7 +67,7 @@ Rectangle {
if ( sView.flickableItem.contentX + sView.width <
x + width + initPosOfCursor + sView.sViewPadding )
Drag.hotSpot.x = 0;
else if ( sView.flickableItem.contentX + sView.sViewPadding > x + initPosOfCursor )
else if ( sView.flickableItem.contentX + sView.sViewPadding > x )
Drag.hotSpot.x = width;
}
......
......@@ -3,11 +3,12 @@ import QtQuick 2.5
Rectangle {
width: 1
color: "#c24a00"
x: ftop( cursorPosition ) + initPosOfCursor
x: ftop( cursorPosition )
visible: x < sView.flickableItem.contentX ? false : true
Component.onCompleted: {
// FIXME: Binding is lost
x = Qt.binding( function() { return ftop( cursorPosition ) + initPosOfCursor; } );
x = Qt.binding( function() { return ftop( cursorPosition ); } );
}
// Triangle
......
......@@ -6,7 +6,8 @@ Rectangle {
width: 1
height: page.height
color: "#3F6644"
x: ftop( position ) + initPosOfCursor
x: ftop( position )
visible: x < sView.flickableItem.contentX ? false : true
property int position: 0
property var markerModel
......
......@@ -2,7 +2,7 @@ import QtQuick 2.0
Rectangle {
id: ruler
height: 52
height: parent.height
width: parent.width - initPosOfCursor
color: "#333333"
......
......@@ -10,394 +10,390 @@ Item {
property string type
property ListModel clips
Row {
anchors.fill: parent
Rectangle {
id: clipArea
x: trackInfo.width
color: "#222222"
height: parent.height
width: track.width - initPosOfCursor
Rectangle {
id: trackInfo
width: initPosOfCursor
height: parent.height
color: "#444444"
Rectangle {
width: parent.width
height: 1
anchors.bottom: parent.bottom
color: "#111111"
}
Rectangle {
width: 1
height: parent.height
anchors.left: parent.left
color: "#111111"
}
Rectangle {
width: 1
height: parent.height
anchors.right: parent.right
color: "#111111"
}
Text {
text: type + " " + ( trackId + 1 )
anchors.right: parent.right
anchors.rightMargin: 10
color: "white"
font.pointSize: trackHeight / 3
}
}
Rectangle {
id: clipArea
color: "#222222"
height: parent.height
width: track.width - initPosOfCursor
Rectangle {
color: "#666666"
height: 1
width: parent.width
anchors.bottom: clipArea.bottom
Component.onCompleted: {
if ( track.type === "Video" && track.trackId == 0 )
{
color = "#111111";
}
color: "#666666"
height: 1
width: parent.width
anchors.bottom: clipArea.bottom
Component.onCompleted: {
if ( track.type === "Video" && track.trackId == 0 )
{
color = "#111111";
}
}
}
DropArea {
id: dropArea
anchors.fill: parent
keys: ["Clip", "vlmc/uuid"]
DropArea {
id: dropArea
anchors.fill: parent
keys: ["Clip", "vlmc/uuid"]
// Enum for drop mode
readonly property var dropMode: {
"New": 0,
"Move": 1,
}
readonly property int magneticMargin: 25
property string currentUuid
property var aClipInfo: null
property var vClipInfo: null
property int lastX: 0
property int deltaX: 0
function findNewPosition( newX, target, useMagneticMode ) {
var oldX = target.pixelPosition();
if ( useMagneticMode === true ) {
var leastDestance = magneticMargin;
// Check two times
for ( var k = 0; k < 2; ++k ) {
for ( var j = 0; j < markers.count; ++j ) {
var mx = ftop( markers.get( j ).position );
if ( Math.abs( newX - mx ) < leastDestance ) {
leastDestance = Math.abs( newX - mx );
newX = mx;
}
else if ( Math.abs( newX + target.width - mx ) < leastDestance ) {
leastDestance = Math.abs( newX + target.width - mx );
newX = mx - target.width;
}
// Enum for drop mode
readonly property var dropMode: {
"New": 0,
"Move": 1,
}
readonly property int magneticMargin: 25
property string currentUuid
property var aClipInfo: null
property var vClipInfo: null
property int lastX: 0
property int deltaX: 0
function findNewPosition( newX, target, useMagneticMode ) {
var oldX = target.pixelPosition();
if ( useMagneticMode === true ) {
var leastDestance = magneticMargin;
// Check two times
for ( var k = 0; k < 2; ++k ) {
for ( var j = 0; j < markers.count; ++j ) {
var mx = ftop( markers.get( j ).position );
if ( Math.abs( newX - mx ) < leastDestance ) {
leastDestance = Math.abs( newX - mx );
newX = mx;
}
else if ( Math.abs( newX + target.width - mx ) < leastDestance ) {
leastDestance = Math.abs( newX + target.width - mx );
newX = mx - target.width;
}
}
}
}
// Collision detection
var isCollided = true;
var currentTrack = trackContainer( target.type )["tracks"].get( target.newTrackId );
if ( currentTrack )
var clips = currentTrack["clips"];
else
currentTrack.append( { "clips": [] } );
for ( j = 0; j < clips.count + 2 && isCollided; ++j ) {
isCollided = false;
for ( k = 0; k < clips.count; ++k ) {
var clip = clips.get( k );
if ( clip.uuid === target.uuid )
continue;
var sw = target.width; // Width of the source clip
var cx = ftop( clip["position"] );
var cw = ftop( clip["end"] - clip["begin"] + 1);
// Set a right position
//
// HACK: If magnetic mode, consider clips bigger.
if ( useMagneticMode === true ) {
if ( cx + cw > newX && newX + sw > cx )
isCollided = true;
cw += magneticMargin * 2
cx -= magneticMargin
if ( cx + cw > newX && newX + sw > cx ) {
if ( cx > newX ) {
if ( cx - sw > 0 )
newX = cx - sw + magneticMargin;
else
newX = oldX;
} else {
newX = cx + cw - magneticMargin;
}
// Collision detection
var isCollided = true;
var currentTrack = trackContainer( target.type )["tracks"].get( target.newTrackId );
if ( currentTrack )
var clips = currentTrack["clips"];
else
currentTrack.append( { "clips": [] } );
for ( j = 0; j < clips.count + 2 && isCollided; ++j ) {
isCollided = false;
for ( k = 0; k < clips.count; ++k ) {
var clip = clips.get( k );
if ( clip.uuid === target.uuid )
continue;
var sw = target.width; // Width of the source clip
var cx = ftop( clip["position"] );
var cw = ftop( clip["end"] - clip["begin"] + 1);
// Set a right position
//
// HACK: If magnetic mode, consider clips bigger.
if ( useMagneticMode === true ) {
if ( cx + cw > newX && newX + sw > cx )
isCollided = true;
cw += magneticMargin * 2
cx -= magneticMargin
if ( cx + cw > newX && newX + sw > cx ) {
if ( cx > newX ) {
if ( cx - sw > 0 )
newX = cx - sw + magneticMargin;
else
newX = oldX;
} else {
newX = cx + cw - magneticMargin;
}
}
else {
if ( cx + cw > newX && newX + sw > cx ) {
isCollided = true;
if ( cx > newX ) {
if ( cx - sw > 0 )
newX = cx - sw;
else
newX = oldX;
} else {
newX = cx + cw;
}
}
else {
if ( cx + cw > newX && newX + sw > cx ) {
isCollided = true;
if ( cx > newX ) {
if ( cx - sw > 0 )
newX = cx - sw;
else
newX = oldX;
} else {
newX = cx + cw;
}
}
if ( isCollided )
break;
}
if ( isCollided )
break;
}
}
if ( isCollided ) {
for ( k = 0; k < clips.count; ++k ) {
clip = clips.get( k );
cx = ftop( clip["position"] );
cw = ftop( clip["end"] - clip["begin"] + 1);
newX = Math.max( newX, cx + cw );
}
if ( isCollided ) {
for ( k = 0; k < clips.count; ++k ) {
clip = clips.get( k );
cx = ftop( clip["position"] );
cw = ftop( clip["end"] - clip["begin"] + 1);
newX = Math.max( newX, cx + cw );
}
return newX;
}
return newX;
}
function scrollToTarget( target ) {
while ( target.width > sView.width )
zoomIn( 0.5 );
function scrollToTarget( target ) {
while ( target.width > sView.width )
zoomIn( 0.5 );
if ( sView.flickableItem.contentX + sView.width <
target.x + target.width + initPosOfCursor + sView.sViewPadding ) {
// Never show the background behind the timeline
var newContentX = sView.flickableItem.contentWidth - sView.width;
if ( newContentX >= 0 ) {
sView.flickableItem.contentX = newContentX;
}
}
else if ( sView.flickableItem.contentX + sView.sViewPadding > target.x + initPosOfCursor ) {
sView.flickableItem.contentX = target.x + initPosOfCursor - sView.sViewPadding;
}
}
var newContentX = sView.flickableItem.contentX;
onDropped: {
if ( drop.keys.indexOf( "vlmc/uuid" ) >= 0 ) {
aClipInfo = findClipFromTrack( "Audio", trackId, "audioUuid" );
vClipInfo = findClipFromTrack( "Video", trackId, "videoUuid" );
if ( aClipInfo ) {
var pos = aClipInfo["position"];
var audioClipUuid = workflow.addClip( currentUuid, trackId, pos, true );
removeClipFromTrack( "Audio", trackId, "audioUuid" );
}
if ( vClipInfo ) {
pos = vClipInfo["position"];
var videoClipUuid = workflow.addClip( currentUuid, trackId, pos, false );
removeClipFromTrack( "Video", trackId, "videoUuid" );
}
if ( audioClipUuid && videoClipUuid ) {
workflow.linkClips( audioClipUuid, videoClipUuid );
}
currentUuid = "";
aClipInfo = null;
vClipInfo = null;
clearSelectedClips();
adjustTracks( "Audio" );
adjustTracks( "Video" );
}
}
if ( sView.flickableItem.contentX + sView.width <
target.x + target.width + initPosOfCursor + sView.sViewPadding )
newContentX = target.x + target.width + initPosOfCursor + sView.sViewPadding - sView.width;
else if ( sView.flickableItem.contentX + sView.sViewPadding > target.x )
newContentX = target.x - sView.sViewPadding;
onExited: {
if ( currentUuid !== "" ) {
sView.flickableItem.contentX = Math.max( newContentX, 0 );
}
onDropped: {
if ( drop.keys.indexOf( "vlmc/uuid" ) >= 0 ) {
aClipInfo = findClipFromTrack( "Audio", trackId, "audioUuid" );
vClipInfo = findClipFromTrack( "Video", trackId, "videoUuid" );
if ( aClipInfo ) {
var pos = aClipInfo["position"];
var audioClipUuid = workflow.addClip( currentUuid, trackId, pos, true );
removeClipFromTrack( "Audio", trackId, "audioUuid" );
}
if ( vClipInfo ) {
pos = vClipInfo["position"];
var videoClipUuid = workflow.addClip( currentUuid, trackId, pos, false );
removeClipFromTrack( "Video", trackId, "videoUuid" );
}
if ( audioClipUuid && videoClipUuid ) {
workflow.linkClips( audioClipUuid, videoClipUuid );
}
currentUuid = "";
aClipInfo = null;
vClipInfo = null;
clearSelectedClips();
adjustTracks( "Audio" );
adjustTracks( "Video" );
}
}
onEntered: {
if ( drag.keys.indexOf( "vlmc/uuid" ) >= 0 ) {
clearSelectedClips();
if ( currentUuid === drag.getDataAsString( "vlmc/uuid" ) ) {
if ( aClipInfo )
{
aClipInfo["position"] = ptof( drag.x );
aClipInfo = addClip( "Audio", trackId, aClipInfo );
}
if ( vClipInfo )
{
vClipInfo["position"] = ptof( drag.x );
vClipInfo = addClip( "Video", trackId, vClipInfo );
}
onExited: {
if ( currentUuid !== "" ) {
removeClipFromTrack( "Audio", trackId, "audioUuid" );
removeClipFromTrack( "Video", trackId, "videoUuid" );
}
}
onEntered: {
if ( drag.keys.indexOf( "vlmc/uuid" ) >= 0 ) {
clearSelectedClips();
if ( currentUuid === drag.getDataAsString( "vlmc/uuid" ) ) {
if ( aClipInfo )
{
aClipInfo["position"] = ptof( drag.x );
aClipInfo = addClip( "Audio", trackId, aClipInfo );
}
else {
var newClipInfo = workflow.clipInfo( drag.getDataAsString( "vlmc/uuid" ) );
currentUuid = "" + newClipInfo["uuid"];
newClipInfo["position"] = ptof( drag.x );
if ( newClipInfo["audio"] ) {
newClipInfo["uuid"] = "audioUuid";
aClipInfo = addClip( "Audio", trackId, newClipInfo );
}
if ( newClipInfo["video"] ) {
newClipInfo["uuid"] = "videoUuid";
vClipInfo = addClip( "Video", trackId, newClipInfo );
}
if ( vClipInfo )
{
vClipInfo["position"] = ptof( drag.x );
vClipInfo = addClip( "Video", trackId, vClipInfo );
}
lastX = drag.x;
}
else
lastX = drag.source.x;
else {
var newClipInfo = workflow.clipInfo( drag.getDataAsString( "vlmc/uuid" ) );
currentUuid = "" + newClipInfo["uuid"];
newClipInfo["position"] = ptof( drag.x );
if ( newClipInfo["audio"] ) {
newClipInfo["uuid"] = "audioUuid";
aClipInfo = addClip( "Audio", trackId, newClipInfo );
}
if ( newClipInfo["video"] ) {
newClipInfo["uuid"] = "videoUuid";
vClipInfo = addClip( "Video", trackId, newClipInfo );
}
}
lastX = drag.x;
}
else
lastX = drag.source.x;
}
onPositionChanged: {
// If resizing, ignore
if ( drag.source.resizing === true )
return;
if ( drag.keys.indexOf( "vlmc/uuid" ) >= 0 )
var dMode = dropMode.New;
else
dMode = dropMode.Move;
if ( dMode === dropMode.Move ) {
// Put drag.source top
for ( var i = 1; i < selectedClips.length; ++i ) {
if ( selectedClips[i] === drag.source ) {
selectedClips.splice( i, 1 );
selectedClips.unshift( drag.source );
}
onPositionChanged: {
// If resizing, ignore
if ( drag.source.resizing === true )
return;
if ( drag.keys.indexOf( "vlmc/uuid" ) >= 0 )
var dMode = dropMode.New;
else
dMode = dropMode.Move;
if ( dMode === dropMode.Move ) {
// Put drag.source top
for ( var i = 1; i < selectedClips.length; ++i ) {
if ( selectedClips[i] === drag.source ) {
selectedClips.splice( i, 1 );
selectedClips.unshift( drag.source );
}
}
scrollToTarget( drag.source );
// Optimization: Delta delta X should be different
if ( deltaX === drag.source.x - lastX && drag.source.x !== 0 ) {
lastX = drag.source.x;
return;
}
else
deltaX = drag.source.x - lastX;
scrollToTarget( drag.source );
// Optimization: Delta delta X should be different
if ( deltaX === drag.source.x - lastX && drag.source.x !== 0 ) {
lastX = drag.source.x;
return;
}
else
deltaX = drag.x - lastX;
deltaX = drag.source.x - lastX;
var alreadyCalculated = []; // Uuids of clips being already set new x position.
for ( i = 0; i < selectedClips.length; ++i ) {
var target = selectedClips[i];
if ( drag.source === target ) {
var oldTrackId = target.newTrackId;
target.newTrackId = trackId;
for ( var j = 0; j < selectedClips.length; ++j ) {
if ( drag.source !== selectedClips[j] )
selectedClips[j].newTrackId = trackId - oldTrackId + selectedClips[j].trackId;
}
}
else
deltaX = drag.x - lastX;
var alreadyCalculated = []; // Uuids of clips being already set new x position.
for ( i = 0; i < selectedClips.length; ++i ) {
var target = selectedClips[i];
if ( drag.source === target ) {
var oldTrackId = target.newTrackId;
target.newTrackId = trackId;
for ( var j = 0; j < selectedClips.length; ++j ) {
if ( drag.source !== selectedClips[j] )
selectedClips[j].newTrackId = trackId - oldTrackId + selectedClips[j].trackId;
}
}
if ( alreadyCalculated.indexOf( target.uuid ) < 0 ) {
var oldX = target.pixelPosition();
var newX = Math.max( oldX + deltaX, 0 );
// Recalculate deltaX in case of drag.source being moved
if ( drag.source === target ) {
if ( oldTrackId === target.newTrackId )
deltaX = Math.round( newX - oldX );
else
// Don't move other clips if drag.source's track is changed
deltaX = 0;
}
if ( alreadyCalculated.indexOf( target.uuid ) < 0 ) {
var oldX = target.pixelPosition();
var newX = Math.max( oldX + deltaX, 0 );
newX = findNewPosition( newX, target, isMagneticMode );
// Recalculate deltaX in case of drag.source being moved
if ( drag.source === target ) {
if ( oldTrackId === target.newTrackId )
deltaX = Math.round( newX - oldX );
else
// Don't move other clips if drag.source's track is changed
deltaX = 0;
}
// Let's find newX of the linked clip
if ( target.linked === true ) {
var linkedClipItem = findClipItem( target.linkedClip );
newX = findNewPosition( newX, target, isMagneticMode );
if ( linkedClipItem ) {
var newLinkedClipX = findNewPosition( newX, linkedClipItem, isMagneticMode );
// Let's find newX of the linked clip
if ( target.linked === true ) {
var linkedClipItem = findClipItem( target.linkedClip );
// If linked clip collides
if ( Math.abs( newLinkedClipX - newX ) > 1 ) {
if ( linkedClipItem ) {
var newLinkedClipX = findNewPosition( newX, linkedClipItem, isMagneticMode );
// Recalculate target's newX
// This time, don't use magnets
newX = findNewPosition( newLinkedClipX, target, false );
newLinkedClipX = findNewPosition( newX, target, false );
// If linked clip collides
if ( Math.abs( newLinkedClipX - newX ) > 1 ) {
// And if newX collides again, we don't move
if ( Math.abs( newLinkedClipX - newX ) > 1 )
newX = oldX;
}
// Recalculate target's newX
// This time, don't use magnets
newX = findNewPosition( newLinkedClipX, target, false );
newLinkedClipX = findNewPosition( newX, target, false );
if ( length < ptof( newX + linkedClipItem.width ) ) {
length = ptof( newX + linkedClipItem.width );
}
// And if newX collides again, we don't move
if ( Math.abs( newLinkedClipX - newX ) > 1 )
newX = oldX;
}
linkedClipItem.setPixelPosition( newX );
alreadyCalculated.push( target.linkedClip );
if ( length < ptof( newX + linkedClipItem.width ) ) {
length = ptof( newX + linkedClipItem.width );
}
}
if ( length < ptof( newX + target.width ) ) {
length = ptof( newX + target.width );
linkedClipItem.setPixelPosition( newX );
alreadyCalculated.push( target.linkedClip );
}
}
target.setPixelPosition( newX );
alreadyCalculated.push( target.uuid );
if ( length < ptof( newX + target.width ) ) {
length = ptof( newX + target.width );
}
// Scroll if needed
if ( drag.source === target || dMode === dropMode.New )
scrollToTarget( target );
// Let's move to the new tracks
if ( dMode === dropMode.Move ) {
if ( target.newTrackId !== target.trackId ) {
drag.source.parent.parent.parent.z = ++maxZ;
if ( drag.source.uuid !== target.uuid ) {
target.clipInfo["selected"] = true;
addClip( target.type, target.newTrackId, target.clipInfo );
removeClipFromTrack( target.type, target.trackId, target.uuid );
--i;
}
target.setPixelPosition( newX );
alreadyCalculated.push( target.uuid );
}
// Scroll if needed
if ( drag.source === target || dMode === dropMode.New )
scrollToTarget( target );
// Let's move to the new tracks
if ( dMode === dropMode.Move ) {
if ( target.newTrackId !== target.trackId ) {
drag.source.parent.parent.z = ++maxZ;
if ( drag.source.uuid !== target.uuid ) {
target.clipInfo["selected"] = true;
addClip( target.type, target.newTrackId, target.clipInfo );
removeClipFromTrack( target.type, target.trackId, target.uuid );
--i;
}
}
}
// END of for ( var i = 0; i < selectedClips.length; ++i )
if ( dMode === dropMode.Move )
lastX = drag.source.x;
else
lastX = drag.x;
}
// END of for ( var i = 0; i < selectedClips.length; ++i )
if ( dMode === dropMode.Move )
lastX = drag.source.x;
else
lastX = drag.x;
}
}
Repeater {
id: repeater
model: clips
delegate: Clip {
height: track.height - 3
name: model.name
trackId: model.trackId
type: track.type
uuid: model.uuid