Esempio n. 1
0
        // Gets the track and group that contains 'target'. Also handles if 'target' is a track or group.
        private static void GetTrackAndGroup(ITimelineObject target, out ITrack targetTrack, out IGroup targetGroup)
        {
            IInterval interval = target as IInterval;

            if (interval != null)
            {
                targetTrack = interval.Track;
            }
            else
            {
                IKey key = target as IKey;
                if (key != null)
                {
                    targetTrack = key.Track;
                }
                else
                {
                    targetTrack = target as ITrack;
                }
            }

            if (targetTrack != null)
            {
                targetGroup = targetTrack.Group;
            }
            else
            {
                targetGroup = target as IGroup;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Inserts items via drag-and-drop</summary>
        /// <param name="e">DragEventArgs containing drag and drop event data</param>
        public void Insert(DragEventArgs e)
        {
            IEnumerable <ITimelineObject> itemCopies;

            if (m_timelineControl.DragDropObjects != null)
            {
                itemCopies = m_timelineControl.DragDropObjects;
                m_timelineControl.DragDropObjects = null;
            }
            else
            {
                itemCopies = ConvertDrop(e);
            }

            Point           clientPoint   = m_timelineControl.PointToClient(new Point(e.X, e.Y));
            PointF          mouseLocation = clientPoint;
            ITimelineObject dropTarget    = Pick(mouseLocation);

            List <TimelinePath> newSelection = new List <TimelinePath>();

            foreach (ITimelineObject droppedItem in itemCopies)
            {
                Insert(droppedItem, dropTarget);
                newSelection.Add(new TimelinePath(droppedItem));
            }
            Selection.SetRange(newSelection.AsIEnumerable <object>());
        }
Esempio n. 3
0
        private void DomNode_AttributeChanging(object sender, AttributeEventArgs e)
        {
            ITimelineObject item = e.DomNode.As <ITimelineObject>();

            if (item != null)
            {
                if (!IsEditable(item, e.AttributeInfo))
                {
                    if (ActiveDocument.Cast <ITransactionContext>().InTransaction)
                    {
                        throw new InvalidTransactionException("timeline object can't be edited");
                    }
                    else
                    {
                        return;
                    }
                }

                // Check if a URI on a timeline reference has changed, so we can unload
                //  old document and load new document.
                if (e.AttributeInfo.Equivalent(Schema.timelineRefType.refAttribute))
                {
                    UnloadSubDocument((Uri)e.OldValue);
                    LoadSubDocument((Uri)e.NewValue);
                }
            }
        }
Esempio n. 4
0
        private bool IsEditable(ITimelineObject item)
        {
            var path = new TimelinePath(item);
            TimelineDocument document = (TimelineDocument)TimelineEditor.TimelineDocumentRegistry.ActiveDocument;

            if (document != null)
            {
                return(document.TimelineControl.IsEditable(path));
            }
            return(false);
        }
Esempio n. 5
0
        /// <summary>
        /// Checks whether the given timeline object's attribute is editable for the current
        /// context and document</summary>
        /// <param name="item">Timeline object that changed</param>
        /// <param name="attribute">Attribute on the timeline object that changed</param>
        /// <returns>True iff this timeline object attribute is editable for the current
        /// ActiveControl, ActiveContext, and ActiveDocument properties</returns>
        public virtual bool IsEditable(ITimelineObject item, AttributeInfo attribute)
        {
            if (attribute == Schema.groupType.expandedAttribute)
            {
                return(true);
            }

            TimelinePath path = new TimelinePath(item);

            return(ActiveControl.IsEditable(path));
        }
Esempio n. 6
0
 /// <summary>
 /// Constructor</summary>
 /// <param name="obj">Ghosted object</param>
 /// <param name="target">Target to snap ghosted object to</param>
 /// <param name="start">Start of ghosted object</param>
 /// <param name="length">Length of ghosted object</param>
 /// <param name="bounds">Bounds of ghosted object</param>
 /// <param name="valid">Whether ghosted object is valid</param>
 public GhostInfo(
     ITimelineObject obj,
     ITimelineObject target,
     float start,
     float length,
     RectangleF bounds,
     bool valid)
 {
     Object = obj;
     Target = target;
     Start = start;
     Length = length;
     Bounds = bounds;
     Valid = valid;
 }
Esempio n. 7
0
        /// <summary>
        /// Adds new object using a transaction so the history context can be verified.
        /// Called by automated scripts during testing.</summary>
        /// <typeparam name="T">Type of object added</typeparam>
        /// <param name="objectToInsert">Object to add</param>
        /// <param name="objectToInsertTo">Parent object to add to</param>
        /// <returns>Object added as type T</returns>
        public T Insert <T>(DomNode objectToInsert, DomNode objectToInsertTo) where T : class
        {
            ITimelineObject source      = objectToInsert.As <ITimelineObject>();
            ITimelineObject destination = objectToInsertTo.As <ITimelineObject>();

            ITransactionContext transactionContext = this.As <ITransactionContext>();

            transactionContext.DoTransaction(
                delegate
            {
                Insert(source, destination);
            }, "Scripted Insert Object");

            return(objectToInsert.As <T>());
        }
Esempio n. 8
0
 /// <summary>
 /// Constructor</summary>
 /// <param name="obj">Ghosted object</param>
 /// <param name="target">Target to snap ghosted object to</param>
 /// <param name="start">Start of ghosted object</param>
 /// <param name="length">Length of ghosted object</param>
 /// <param name="bounds">Bounds of ghosted object</param>
 /// <param name="valid">Whether ghosted object is valid</param>
 public GhostInfo(
     ITimelineObject obj,
     ITimelineObject target,
     float start,
     float length,
     RectangleF bounds,
     bool valid)
 {
     Object = obj;
     Target = target;
     Start  = start;
     Length = length;
     Bounds = bounds;
     Valid  = valid;
 }
Esempio n. 9
0
        // Determines which tracks to place the targets timeline objects in. Creates new tracks if necessary.
        //  Returns a dictionary mapping target timeline objects to the tracks they should be placed in.
        private static Dictionary <ITimelineObject, ITrack> CreateTrackMappings(
            ITimeline timeline,
            IList <Tuple <ITimelineObject, ITimelineObject> > sourceTargetPairs,
            ITrack centerTrack, Dictionary <ITimelineObject, ITrack> sourceObjToTrack)
        {
            // Gather together all the source tracks. Use the dictionary instead of
            //  the source objects in 'sourceTargetPairs' because the source objects may
            //  no longer be parented to a track. (Because of Cut and Paste.)
            List <ITrack> sourceTracks = new List <ITrack>(sourceObjToTrack.Values);

            // Sort the source tracks from top-to-bottom
            SortTracks(timeline, sourceTracks);

            // Get or create the target tracks
            List <ITrack> targetTracks = GetOrCreateOrderedTracks(timeline, sourceTracks.Count, centerTrack);

            // Prepare a mapping from source track to target track
            var sourceTrackToTargetTrack = new Dictionary <ITrack, ITrack>();

            for (int i = 0; i < targetTracks.Count; i++)
            {
                sourceTrackToTargetTrack[sourceTracks[i]] = targetTracks[i];
            }

            // Prepare the mapping from target ITimelineObject to target ITrack
            Dictionary <ITimelineObject, ITrack> targetObjToTrack = new Dictionary <ITimelineObject, ITrack>();

            for (int i = 0; i < sourceTargetPairs.Count; i++)
            {
                ITimelineObject source = sourceTargetPairs[i].Item1;
                ITimelineObject target = sourceTargetPairs[i].Item2;
                ITrack          sourceTrack;
                sourceObjToTrack.TryGetValue(source, out sourceTrack);
                if (sourceTrack != null)
                {
                    ITrack targetTrack = sourceTrackToTargetTrack[sourceTrack];
                    targetObjToTrack[target] = targetTrack;
                }
            }
            return(targetObjToTrack);
        }
Esempio n. 10
0
        // Gets the bounding box in client window coordinates
        private RectangleF GetDragDropBounds(ITimelineObject dragDrop)
        {
            var bounds = new RectangleF();

            var interval = dragDrop as IInterval;

            if (interval != null)
            {
                bounds = m_owner.Renderer.GetBounds(interval, 0, m_owner.Transform, m_owner.ClientRectangle);
            }

            var key = dragDrop as IKey;

            if (key != null)
            {
                bounds = m_owner.Renderer.GetBounds(key, 0, m_owner.Transform, m_owner.ClientRectangle);
            }

            bounds = GdiUtil.Transform(m_owner.Transform, bounds);

            return(bounds);
        }
Esempio n. 11
0
        private void _MoveSelection(bool tryToCopy, bool createTracksAndGroups)
        {
            ITimeline timeline = m_owner.TimelineDocument.Timeline;
            Dictionary <ITrack, ITrack>           newTrackMap = new Dictionary <ITrack, ITrack>();
            List <Sce.Atf.Pair <ITrack, IEvent> > toAdd       = new List <Sce.Atf.Pair <ITrack, IEvent> >();

            for (int i = 0; i < m_ghosts.Length; i++)
            {
                GhostInfo ghost = m_ghosts[i];

                ITimelineObject ghostCopy = null;
                if (tryToCopy)
                {
                    ICloneable cloneable = ghost.Object as ICloneable;
                    if (cloneable != null)
                    {
                        ghostCopy = cloneable.Clone() as ITimelineObject;
                    }
                }

                ITimelineReference reference = ghost.Object as ITimelineReference;
                if (reference != null)
                {
                    if (ghostCopy != null)
                    {
                        reference = (ITimelineReference)ghostCopy;
                    }
                    reference.Start = ghost.Start;
                    if (ghostCopy != null && timeline is IHierarchicalTimelineList)
                    {
                        ((IHierarchicalTimelineList)timeline).References.Add(reference);
                    }
                    continue;
                }

                IInterval interval = ghost.Object as IInterval;
                if (interval != null)
                {
                    if (ghostCopy != null)
                    {
                        interval = (IInterval)ghostCopy;
                    }
                    interval.Start  = ghost.Start;
                    interval.Length = ghost.Length;
                    ITrack target = (ITrack)ghost.Target;
                    if (target != interval.Track && createTracksAndGroups)
                    {
                        if (target == null)
                        {
                            target = CreateTargetTrack(interval.Track, newTrackMap);
                        }
                        if (ghostCopy == null)
                        {
                            interval.Track.Intervals.Remove(interval);
                        }
                        toAdd.Add(new Sce.Atf.Pair <ITrack, IEvent>(target, interval));
                    }
                    continue;
                }

                IKey key = ghost.Object as IKey;
                if (key != null)
                {
                    if (ghostCopy != null)
                    {
                        key = (IKey)ghostCopy;
                    }
                    key.Start = ghost.Start;
                    ITrack target = (ITrack)ghost.Target;
                    if (target != key.Track && createTracksAndGroups)
                    {
                        if (target == null)
                        {
                            target = CreateTargetTrack(key.Track, newTrackMap);
                        }
                        if (ghostCopy == null)
                        {
                            key.Track.Keys.Remove(key);
                        }
                        toAdd.Add(new Sce.Atf.Pair <ITrack, IEvent>(target, key));
                    }
                    continue;
                }

                IMarker marker = ghost.Object as IMarker;
                if (marker != null)
                {
                    if (ghost.Valid &&
                        marker.Start != ghost.Start)
                    {
                        if (ghostCopy != null)
                        {
                            IMarker markerCopy = (IMarker)ghostCopy;
                            markerCopy.Start = ghost.Start;
                            marker.Timeline.Markers.Add(markerCopy);
                        }
                        else
                        {
                            marker.Start = ghost.Start;
                        }
                    }
                    continue;
                }

                ITrack track = ghost.Object as ITrack;
                if (track != null)
                {
                    var targetTrack = ghost.Target as ITrack;
                    if (targetTrack != null &&
                        targetTrack != track)
                    {
                        if (ghostCopy != null)
                        {
                            track = (ITrack)ghostCopy;
                        }
                        int index = targetTrack.Group.Tracks.IndexOf(targetTrack);
                        if (ghostCopy == null)
                        {
                            track.Group.Tracks.Remove(track);
                        }
                        targetTrack.Group.Tracks.Insert(index, track);
                    }
                    else
                    {
                        var targetGroup = ghost.Target as IGroup;
                        if (targetGroup != null)
                        {
                            // the track was dragged to an empty group. http://tracker.ship.scea.com/jira/browse/WWSATF-1371
                            if (ghostCopy != null)
                            {
                                track = (ITrack)ghostCopy;
                            }
                            else
                            {
                                track.Group.Tracks.Remove(track);
                            }
                            targetGroup.Tracks.Insert(0, track);
                        }
                    }
                    continue;
                }

                IGroup group = ghost.Object as IGroup;
                if (group != null)
                {
                    IGroup target = (IGroup)ghost.Target;
                    if (target != null &&
                        target != group)
                    {
                        if (ghostCopy != null)
                        {
                            group = (IGroup)ghostCopy;
                        }
                        int index = m_owner.TimelineDocument.Timeline.Groups.IndexOf(target);
                        if (ghostCopy == null)
                        {
                            m_owner.TimelineDocument.Timeline.Groups.Remove(group);
                        }
                        m_owner.TimelineDocument.Timeline.Groups.Insert(index, group);
                    }
                    continue;
                }
            }

            // So that when multiple intervals from multiple tracks are relocated to a different
            //  set of tracks, we need to remove them all and then add them all. If the remove and
            //  adds are done in pairs, one by one, then the events can step on each other. artf32260
            foreach (Sce.Atf.Pair <ITrack, IEvent> trackEventPair in toAdd)
            {
                if (trackEventPair.Second is IInterval)
                {
                    trackEventPair.First.Intervals.Add((IInterval)trackEventPair.Second);
                }
                else
                {
                    trackEventPair.First.Keys.Add((IKey)trackEventPair.Second);
                }
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Checks whether the given timeline object's attribute is editable for the current
        /// context and document</summary>
        /// <param name="item">Timeline object that changed</param>
        /// <param name="attribute">Attribute on the timeline object that changed</param>
        /// <returns>True iff this timeline object attribute is editable for the current
        /// ActiveControl, ActiveContext, and ActiveDocument properties</returns>
        public virtual bool IsEditable(ITimelineObject item, AttributeInfo attribute)
        {
            if (attribute == Schema.groupType.expandedAttribute)
                return true;

            TimelinePath path = new TimelinePath(item);
            return ActiveControl.IsEditable(path);
        }
Esempio n. 13
0
        private bool DoCommand(object commandTag, bool doing)
        {
            TimelineContext context = m_contextRegistry.GetActiveContext <TimelineContext>();

            if (context == null)
            {
                return(false);
            }

            TimelineDocument document = context.As <TimelineDocument>();

            if (document == null)
            {
                return(false);
            }

            if (commandTag is Command)
            {
                if ((Command)commandTag == Command.ToggleSplitMode)
                {
                    if (doing && document.SplitManipulator != null)
                    {
                        document.SplitManipulator.Active = !document.SplitManipulator.Active;
                    }
                    return(true);
                }

                ITimelineObject target = m_contextRegistry.GetCommandTarget <ITimelineObject>();
                if (target == null)
                {
                    return(false);
                }

                IInterval activeInterval = target as IInterval;
                ITrack    activeTrack    =
                    (activeInterval != null) ? activeInterval.Track : target.As <ITrack>();
                IGroup activeGroup =
                    (activeTrack != null) ? activeTrack.Group : target.As <IGroup>();
                ITimeline activeTimeline =
                    (activeGroup != null) ? activeGroup.Timeline : target.As <ITimeline>();
                ITransactionContext transactionContext = context.TimelineControl.TransactionContext;

                switch ((Command)commandTag)
                {
                case Command.RemoveGroup:
                    if (activeGroup == null)
                    {
                        return(false);
                    }

                    if (doing)
                    {
                        transactionContext.DoTransaction(delegate
                        {
                            activeGroup.Timeline.Groups.Remove(activeGroup);
                        },
                                                         "Remove Group");
                    }
                    return(true);

                case Command.RemoveTrack:
                    if (activeTrack == null)
                    {
                        return(false);
                    }

                    if (doing)
                    {
                        transactionContext.DoTransaction(delegate
                        {
                            activeTrack.Group.Tracks.Remove(activeTrack);
                        },
                                                         "Remove Track");
                    }
                    return(true);

                case Command.RemoveEmptyGroupsAndTracks:
                    if (activeTimeline == null)
                    {
                        return(false);
                    }

                    if (doing)
                    {
                        transactionContext.DoTransaction(delegate
                        {
                            IList <IGroup> groups = activeTimeline.Groups;
                            for (int i = 0; i < groups.Count;)
                            {
                                IList <ITrack> tracks = groups[i].Tracks;
                                for (int j = 0; j < tracks.Count;)
                                {
                                    if (tracks[j].Intervals.Count == 0 && tracks[j].Keys.Count == 0)
                                    {
                                        tracks.RemoveAt(j);
                                    }
                                    else
                                    {
                                        j++;
                                    }
                                }

                                if (tracks.Count == 0)
                                {
                                    groups.RemoveAt(i);
                                }
                                else
                                {
                                    i++;
                                }
                            }
                        },
                                                         "Remove Empty Groups and Tracks");
                    }
                    return(true);
                }
            }
            else if (commandTag is StandardCommand)
            {
                switch ((StandardCommand)commandTag)
                {
                case StandardCommand.ViewZoomExtents:
                    if (doing)
                    {
                        document.TimelineControl.Frame();
                    }
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 14
0
        // Gets the bounding box in client window coordinates
        private RectangleF GetDragDropBounds(ITimelineObject dragDrop)
        {
            var bounds = new RectangleF();

            var interval = dragDrop as IInterval;
            if (interval != null)
                bounds = m_owner.Renderer.GetBounds(interval, 0, m_owner.Transform, m_owner.ClientRectangle);

            var key = dragDrop as IKey;
            if (key != null)
                bounds = m_owner.Renderer.GetBounds(key, 0, m_owner.Transform, m_owner.ClientRectangle);

            bounds = GdiUtil.Transform(m_owner.Transform, bounds);

            return bounds;
        }
Esempio n. 15
0
        private void Insert(ITimelineObject droppedItem, ITimelineObject dropTarget)
        {
            if (m_timelineDocument == null)
            {
                return;
            }

            // TimelineControl maintains target group and track
            ITimeline targetTimeline = m_timelineDocument.Timeline;
            IGroup    targetGroup    = m_timelineControl.TargetGroup != null ? (IGroup)m_timelineControl.TargetGroup.Last : null;
            ITrack    targetTrack    = m_timelineControl.TargetTrack != null ? (ITrack)m_timelineControl.TargetTrack.Last : null;

            // in case of drag and drop, use drop target instead
            if (dropTarget != null)
            {
                GetTrackAndGroup(dropTarget, out targetTrack, out targetGroup);
            }

            // Work up from insertion point to get target key/interval, track, group, timeline
            ITimelineReference reference = droppedItem.As <ITimelineReference>();

            if (reference != null)
            {
                ((Timeline)targetTimeline).AddReference(reference);
                return;
            }

            IGroup group = droppedItem.As <IGroup>();

            if (group != null)
            {
                // if this is a new group, add a default track
                if (group.Tracks.Count == 0)
                {
                    ITrack emptyTrack = group.CreateTrack();
                    if (emptyTrack != null)
                    {
                        group.Tracks.Add(emptyTrack);
                    }
                }

                targetTimeline.Groups.Add(group);
                return;
            }

            IMarker marker = droppedItem.As <IMarker>();

            if (marker != null)
            {
                targetTimeline.Markers.Add(marker);
                return;
            }

            // Must be track or interval; get the target group, or create one.
            ITrack track = droppedItem.As <ITrack>();
            IEvent ev    = droppedItem.As <IEvent>();

            if (track != null ||
                ev != null)
            {
                IList <IGroup> groups = targetTimeline.Groups;
                if (targetGroup == null)
                {
                    targetGroup = targetTimeline.CreateGroup();
                    groups.Add(targetGroup);
                }

                if (track != null)
                {
                    targetGroup.Tracks.Add(track);
                }
                else //if (ev != null)
                {
                    // interval or key; get the target track or create one
                    if (targetTrack == null)
                    {
                        targetTrack = targetGroup.CreateTrack();
                        targetGroup.Tracks.Add(targetTrack);
                    }

                    IInterval interval = droppedItem.As <IInterval>();
                    if (interval != null)
                    {
                        targetTrack.Intervals.Add(interval);
                    }
                    else
                    {
                        IKey key = droppedItem.As <IKey>();
                        if (key != null)
                        {
                            targetTrack.Keys.Add(key);
                        }
                    }
                }
            }
        }
Esempio n. 16
0
 /// <summary>
 /// Gets or sets the bounding rectangle, in screen space, of a timeline object that is
 /// in the main timeline document and so has no parent ITimelineReference objects in
 /// its path. A TimelinePath is created around this timeline object when setting.</summary>
 /// <param name="obj">Timeline object</param>
 public RectangleF this[ITimelineObject obj]
 {
     get { return(m_paths[new TimelinePath(obj)]); }
     set { m_paths[new TimelinePath(obj)] = value; }
 }
Esempio n. 17
0
        // gets move information, for drawing ghosts and for performing actual move operation
        private GhostInfo[] GetMoveGhostInfo(Matrix worldToView, TimelineLayout layout)
        {
            // get start and y offsets in timeline space
            PointF dragOffset = m_owner.GetDragOffset();

            // Get snapping points along the timeline (in world coordinates).
            List <float> movingPoints = new List <float>(2);
            TimelinePath snapperPath;

            if (m_mouseMoveHitRecord != null)
            {
                snapperPath = m_mouseMoveHitRecord.HitPath;//use the last clicked event (interval, key or marker)
            }
            else
            {
                snapperPath = m_owner.Selection.LastSelected as TimelinePath;//moving a group or track, for example
            }
            IEvent snapperEvent = snapperPath != null ? snapperPath.Last as IEvent : null;

            if (snapperEvent != null)
            {
                Matrix localToWorld = TimelineControl.CalculateLocalToWorld(snapperPath);
                float  worldStart   = GdiUtil.Transform(localToWorld, snapperEvent.Start + dragOffset.X);
                movingPoints.Add(worldStart);
                if (snapperEvent.Length > 0.0f)
                {
                    movingPoints.Add(GdiUtil.Transform(localToWorld, snapperEvent.Start + dragOffset.X + snapperEvent.Length));
                }
            }

            // Get the offset from one of the world snap points to the closest non-selected object.
            float snapOffset;

            try
            {
                s_snapOptions.FilterContext = snapperEvent;
                s_snapOptions.Filter        = new TimelineControl.SnapFilter(MoveSnapFilter);
                snapOffset = m_owner.GetSnapOffset(movingPoints, s_snapOptions);
            }
            finally
            {
                s_snapOptions.FilterContext = null;
                s_snapOptions.Filter        = null;
            }

            // adjust dragOffset to "snap-to" nearest event
            dragOffset.X += snapOffset;

            // get offsets in client space
            float xOffset = dragOffset.X * worldToView.Elements[0];
            float yOffset = dragOffset.Y * worldToView.Elements[3];

            TimelinePath[] targets = GetMoveTargets(layout);

            GhostInfo[] ghosts = new GhostInfo[targets.Length];
            int         i      = -1;

            foreach (TimelinePath path in m_owner.Selection.Selection)
            {
                i++;

                ITimelineObject timelineObject = path.Last;
                RectangleF      bounds         = layout[path];

                TimelinePath    targetPath = targets[i];
                ITimelineObject target     = targetPath != null ? targetPath.Last : null;

                float start  = 0;
                float length = 0;
                bool  valid  = true;

                IInterval          interval  = timelineObject as IInterval;
                IKey               key       = timelineObject as IKey;
                IMarker            marker    = timelineObject as IMarker;
                ITrack             track     = timelineObject as ITrack;
                IGroup             group     = timelineObject as IGroup;
                ITimelineReference reference = timelineObject as ITimelineReference;

                if (interval != null)
                {
                    ITrack targetTrack = target as ITrack;
                    start  = interval.Start + dragOffset.X;
                    length = interval.Length;
                    valid  =
                        targetTrack != null &&
                        m_owner.Constraints.IsStartValid(interval, ref start) &&
                        m_owner.Constraints.IsLengthValid(interval, ref length);

                    if (valid)
                    {
                        yOffset = layout[target].Y - layout[interval.Track].Y;
                        TimelinePath testPath = new TimelinePath(targetPath);
                        foreach (IInterval other in targetTrack.Intervals)
                        {
                            // skip selected intervals, since they are moving too
                            testPath.Last = other;
                            if (m_owner.Selection.SelectionContains(testPath))
                            {
                                continue;
                            }

                            if (!m_owner.Constraints.IsIntervalValid(interval, ref start, ref length, other))
                            {
                                valid = false;
                                break;
                            }
                        }
                    }
                }
                else if (reference != null)
                {
                    // don't allow for vertical repositioning yet
                    start = reference.Start + dragOffset.X;
                    valid = true;
                }
                else if (key != null)
                {
                    start = key.Start + dragOffset.X;
                    ITrack targetTrack = target as ITrack;
                    valid =
                        targetTrack != null &&
                        m_owner.Constraints.IsStartValid(key, ref start);

                    if (valid)
                    {
                        yOffset = layout[targetTrack].Y - layout[key.Track].Y;
                    }
                }
                else if (marker != null)
                {
                    start   = marker.Start + dragOffset.X;
                    yOffset = 0;
                    valid   = m_owner.Constraints.IsStartValid(marker, ref start);
                }
                else if (track != null)
                {
                    xOffset = 0;
                    if (target == null)
                    {
                        target =
                            (m_owner.DragDelta.Y < 0) ? GetLastTrack() : GetFirstTrack();
                    }
                }
                else if (group != null)
                {
                    xOffset = 0;
                    if (target == null)
                    {
                        IList <IGroup> groups = m_owner.TimelineDocument.Timeline.Groups;
                        target = (m_owner.DragDelta.Y < 0) ? groups[0] : groups[groups.Count - 1];
                    }
                }

                bounds.Offset(xOffset, yOffset);

                ghosts[i] = new GhostInfo(timelineObject, target, start, length, bounds, valid);
            }
            return(ghosts);
        }
Esempio n. 18
0
        /// <summary>
        /// Inserts the data object into the context.
        /// Generic insert via IInstancingContext. Called from, for example, the standard paste command.</summary>
        /// <param name="insertingObject">Data to insert; e.g., System.Windows.Forms.IDataObject</param>
        public void Insert(object insertingObject)
        {
            IDataObject dataObject = (IDataObject)insertingObject;

            // use current document control to center the elements
            object[] items = dataObject.GetData(typeof(object[])) as object[];
            if (items == null)
            {
                return;
            }
            IEnumerable <DomNode> sourceDomNodes = PathsToDomNodes(items);

            DomNode[] nodeCopies  = DomNode.Copy(sourceDomNodes);
            var       itemSources = new List <ITimelineObject>(sourceDomNodes.AsIEnumerable <ITimelineObject>());
            var       itemCopies  = new List <ITimelineObject>(nodeCopies.AsIEnumerable <ITimelineObject>());

            TimelineDocument   document        = DomNode.Cast <TimelineDocument>();
            D2dTimelineControl timelineControl = document.TimelineControl;

            Rectangle clientRect  = m_timelineControl.VisibleClientRectangle;
            Point     clientPoint = new Point(
                clientRect.Left + clientRect.Width / 2,
                clientRect.Top + clientRect.Height / 2);

            CenterEvents(itemCopies.AsIEnumerable <IEvent>(), clientPoint, timelineControl.Transform);

            var sourceTargetPairs = new List <Tuple <ITimelineObject, ITimelineObject> >(itemSources.Count);

            for (int i = 0; i < itemSources.Count; i++)
            {
                sourceTargetPairs.Add(new Tuple <ITimelineObject, ITimelineObject>(itemSources[i], itemCopies[i]));
            }

            // Prepare the mapping of source objects to their tracks. These may be known already (from
            //  a previous Copy operation), but we can't be sure, so let's augment m_copyObjToTrack if
            //  possible.
            if (m_copyObjToTrack == null)
            {
                m_copyObjToTrack = new Dictionary <ITimelineObject, ITrack>();
            }
            foreach (var source in itemSources)
            {
                IGroup group;
                ITrack track;
                GetTrackAndGroup(source, out track, out group);
                if (track != null)
                {
                    m_copyObjToTrack[source] = track;
                }
            }

            // Guess where the user wants to paste. Priority:
            // 1. The timeline control's target (currently selected) track.
            ITrack targetTrack = timelineControl.TargetTrack != null ? (ITrack)m_timelineControl.TargetTrack.Last : null;

            // But only if it's visible.
            if (targetTrack != null)
            {
                if (!IsTrackVisible(targetTrack))
                {
                    targetTrack = null;
                }
            }
            // 2. The track in the center of the view.
            if (targetTrack == null)
            {
                ITimelineObject centerObject = Pick(clientPoint);
                IGroup          centerGroup;
                GetTrackAndGroup(centerObject, out targetTrack, out centerGroup);
            }
            // 3. The first visible track
            if (targetTrack == null)
            {
                foreach (IGroup group in Timeline.Groups)
                {
                    foreach (ITrack track in group.Tracks)
                    {
                        if (IsTrackVisible(track))
                        {
                            targetTrack = track;
                            break;
                        }
                    }
                    if (targetTrack != null)
                    {
                        break;
                    }
                }
            }

            Dictionary <ITimelineObject, ITrack> copiesToTracks = CreateTrackMappings(
                m_timelineDocument.Timeline, sourceTargetPairs, targetTrack, m_copyObjToTrack);

            foreach (ITimelineObject item in itemCopies)
            {
                // Not all items will have a track. The item could be a group, for example.
                ITrack dropTarget;
                copiesToTracks.TryGetValue(item, out dropTarget);
                Insert(item, dropTarget);
            }

            List <TimelinePath> newSelection = new List <TimelinePath>();

            foreach (ITimelineObject copy in itemCopies)
            {
                // Would need a way to get the path of ITimelineReference objects....
                if (TimelineControl.GetOwningTimeline(copy) != Timeline)
                {
                    throw new NotImplementedException("We haven't implemented the ability to insert timeline objects into a sub-document");
                }
                newSelection.Add(new TimelinePath(copy));
            }

            Selection.SetRange(newSelection.AsIEnumerable <object>());
        }
Esempio n. 19
0
        /// <summary>
        /// Moves the objects represented by the current ghosts to be at the position of
        /// the ghosts</summary>
        protected virtual void MoveSelection()
        {
            // To avoid setting the dirty bit in custom applications.
            // http://sf.ship.scea.com/sf/go/artf22506
            PointF dragOffset = m_owner.GetDragOffset();

            if ((dragOffset.X == 0.0f) && (dragOffset.Y == 0.0f))
            {
                return;
            }

            // If we're dragging up, then don't create new tracks
            if (dragOffset.Y < 0)
            {
                foreach (GhostInfo ghost in m_ghosts)
                {
                    if (!ghost.Valid)
                    {
                        return;
                    }
                }
            }

            // If Control key is being held down, then we're in copy mode.
            bool tryToCopy = (Control.ModifierKeys == Keys.Control);

            m_owner.TransactionContext.DoTransaction(delegate
            {
                ITimeline timeline = m_owner.TimelineDocument.Timeline;
                Dictionary <ITrack, ITrack> newTrackMap     = new Dictionary <ITrack, ITrack>();
                List <Sce.Atf.Pair <ITrack, IEvent> > toAdd = new List <Sce.Atf.Pair <ITrack, IEvent> >();

                for (int i = 0; i < m_ghosts.Length; i++)
                {
                    GhostInfo ghost = m_ghosts[i];

                    ITimelineObject ghostCopy = null;
                    if (tryToCopy)
                    {
                        ICloneable cloneable = ghost.Object as ICloneable;
                        if (cloneable != null)
                        {
                            ghostCopy = cloneable.Clone() as ITimelineObject;
                        }
                    }

                    ITimelineReference reference = ghost.Object as ITimelineReference;
                    if (reference != null)
                    {
                        if (ghostCopy != null)
                        {
                            reference = (ITimelineReference)ghostCopy;
                        }
                        reference.Start = ghost.Start;
                        if (ghostCopy != null && timeline is IHierarchicalTimelineList)
                        {
                            ((IHierarchicalTimelineList)timeline).References.Add(reference);
                        }
                        continue;
                    }

                    IInterval interval = ghost.Object as IInterval;
                    if (interval != null)
                    {
                        if (ghostCopy != null)
                        {
                            interval = (IInterval)ghostCopy;
                        }
                        interval.Start  = ghost.Start;
                        interval.Length = ghost.Length;
                        ITrack target   = (ITrack)ghost.Target;
                        if (target != interval.Track)
                        {
                            if (target == null)
                            {
                                target = CreateTargetTrack(interval.Track, newTrackMap);
                            }
                            if (ghostCopy == null)
                            {
                                interval.Track.Intervals.Remove(interval);
                            }
                            toAdd.Add(new Sce.Atf.Pair <ITrack, IEvent>(target, interval));
                        }
                        continue;
                    }

                    IKey key = ghost.Object as IKey;
                    if (key != null)
                    {
                        if (ghostCopy != null)
                        {
                            key = (IKey)ghostCopy;
                        }
                        key.Start     = ghost.Start;
                        ITrack target = (ITrack)ghost.Target;
                        if (target != key.Track)
                        {
                            if (target == null)
                            {
                                target = CreateTargetTrack(key.Track, newTrackMap);
                            }
                            if (ghostCopy == null)
                            {
                                key.Track.Keys.Remove(key);
                            }
                            toAdd.Add(new Sce.Atf.Pair <ITrack, IEvent>(target, key));
                        }
                        continue;
                    }

                    IMarker marker = ghost.Object as IMarker;
                    if (marker != null)
                    {
                        if (ghost.Valid &&
                            marker.Start != ghost.Start)
                        {
                            if (ghostCopy != null)
                            {
                                IMarker markerCopy = (IMarker)ghostCopy;
                                markerCopy.Start   = ghost.Start;
                                marker.Timeline.Markers.Add(markerCopy);
                            }
                            else
                            {
                                marker.Start = ghost.Start;
                            }
                        }
                        continue;
                    }

                    ITrack track = ghost.Object as ITrack;
                    if (track != null)
                    {
                        ITrack target = (ITrack)ghost.Target;
                        if (target != null &&
                            target != track)
                        {
                            if (ghostCopy != null)
                            {
                                track = (ITrack)ghostCopy;
                            }
                            int index = target.Group.Tracks.IndexOf(target);
                            if (ghostCopy == null)
                            {
                                track.Group.Tracks.Remove(track);
                            }
                            target.Group.Tracks.Insert(index, track);
                        }
                        continue;
                    }

                    IGroup group = ghost.Object as IGroup;
                    if (group != null)
                    {
                        IGroup target = (IGroup)ghost.Target;
                        if (target != null &&
                            target != group)
                        {
                            if (ghostCopy != null)
                            {
                                group = (IGroup)ghostCopy;
                            }
                            int index = m_owner.TimelineDocument.Timeline.Groups.IndexOf(target);
                            if (ghostCopy == null)
                            {
                                m_owner.TimelineDocument.Timeline.Groups.Remove(group);
                            }
                            m_owner.TimelineDocument.Timeline.Groups.Insert(index, group);
                        }
                        continue;
                    }
                }

                // So that when multiple intervals from multiple tracks are relocated to a different
                //  set of tracks, we need to remove them all and then add them all. If the remove and
                //  adds are done in pairs, one by one, then the events can step on each other. artf32260
                foreach (Sce.Atf.Pair <ITrack, IEvent> trackEventPair in toAdd)
                {
                    if (trackEventPair.Second is IInterval)
                    {
                        trackEventPair.First.Intervals.Add((IInterval)trackEventPair.Second);
                    }
                    else
                    {
                        trackEventPair.First.Keys.Add((IKey)trackEventPair.Second);
                    }
                }
            },
                                                     "Move Events".Localize("Move Manipulator's undo / redo description for moving timeline events"));
        }