コード例 #1
0
 /// <summary>
 /// Constructor that permanently attaches to the given timeline control by subscribing to its
 /// events.</summary>
 /// <param name="owner">The timeline control that we are permanently attached to</param>
 public D2dSelectionManipulator(D2dTimelineControl owner)
 {
     Owner = owner;
     Owner.MouseDownPicked += Owner_MouseDownPicked;
     Owner.KeyDown += Owner_KeyDown;
     Owner.MouseUp += Owner_MouseUp;
 }
コード例 #2
0
        /// <summary>
        /// Counts the number of references to this document by all TimelineDocuments</summary>
        /// <param name="document">Document</param>
        /// <returns>Number references to document</returns>
        private int NumReferences(ITimelineDocument document)
        {
            int count = 0;

            foreach (IDocument topDoc in m_documentRegistry.Documents)
            {
                ITimelineDocument topTimelineDoc = topDoc as ITimelineDocument;
                if (topTimelineDoc != null)
                {
                    if (document == topTimelineDoc)
                    {
                        count++;
                    }

                    foreach (TimelinePath path in D2dTimelineControl.GetHierarchy(topTimelineDoc.Timeline))
                    {
                        IHierarchicalTimeline target = ((ITimelineReference)path.Last).Target;
                        if (document == target.As <ITimelineDocument>())
                        {
                            count++;
                        }
                    }
                }
            }
            return(count);
        }
コード例 #3
0
        // private because this may be moved to TimelineControl
        private bool Overlaps(TimelinePath path, float beginTime, float endTime)
        {
            IEvent e = (IEvent)path.Last;

            float start, length;

            using (Matrix localToWorld = D2dTimelineControl.CalculateLocalToWorld(path))
            {
                start  = GdiUtil.Transform(localToWorld, e.Start);
                length = GdiUtil.TransformVector(localToWorld, e.Length);
            }

            // If the length is zero, then count an exact match with beginTime or endTime as
            //  being an overlap.
            if (length == 0)
            {
                return(!(
                           start > endTime ||
                           start + length < beginTime));
            }

            // Otherwise, don't count an exact match.
            return(!(
                       start >= endTime ||
                       start + length <= beginTime));
        }
コード例 #4
0
 /// <summary>
 /// Constructor that permanently attaches to the given TimelineControl by subscribing to its
 /// events</summary>
 /// <param name="owner">The TimelineControl whose events we permanently listen to</param>
 public D2dSplitManipulator(D2dTimelineControl owner)
 {
     m_owner = owner;
     m_owner.MouseDownPicked += owner_MouseDownPicked;
     m_owner.MouseMovePicked += owner_MouseMovePicked;
     m_owner.KeyDown += owner_KeyDown;
 }
コード例 #5
0
ファイル: D2dSplitManipulator.cs プロジェクト: zparr/ATF
 /// <summary>
 /// Constructor that permanently attaches to the given TimelineControl by subscribing to its
 /// events</summary>
 /// <param name="owner">The TimelineControl whose events we permanently listen to</param>
 public D2dSplitManipulator(D2dTimelineControl owner)
 {
     m_owner = owner;
     m_owner.MouseDownPicked += owner_MouseDownPicked;
     m_owner.MouseMovePicked += owner_MouseMovePicked;
     m_owner.KeyDown         += owner_KeyDown;
 }
コード例 #6
0
 /// <summary>
 /// Constructor that permanently attaches to the given timeline control by subscribing to its
 /// events.</summary>
 /// <param name="owner">The timeline control that we are permanently attached to</param>
 public D2dSelectionManipulator(D2dTimelineControl owner)
 {
     Owner = owner;
     Owner.MouseDownPicked += Owner_MouseDownPicked;
     Owner.KeyDown         += Owner_KeyDown;
     Owner.MouseUp         += Owner_MouseUp;
 }
コード例 #7
0
        /// <summary>
        /// Notifies the client that its Control has been activated. Activation occurs when
        /// the Control gets focus, or a parent "host" Control gets focus.</summary>
        /// <param name="control">Client Control that was activated</param>
        /// <remarks>This method is only called by IControlHostService if the Control was previously
        /// registered for this IControlHostClient.</remarks>
        public void Activate(Control control)
        {
            D2dTimelineControl timelineControl  = (D2dTimelineControl)control;
            TimelineDocument   timelineDocument = (TimelineDocument)timelineControl.TimelineDocument;

            m_contextRegistry.ActiveContext   = timelineDocument;
            m_documentRegistry.ActiveDocument = timelineDocument;
        }
コード例 #8
0
 /// <summary>
 /// Constructor that permanently attaches to the given timeline control by subscribing to its
 /// events</summary>
 /// <param name="owner">The timeline control whose events we permanently listen to</param>
 public D2dScaleManipulator(D2dTimelineControl owner)
 {
     Owner = owner;
     Owner.MouseDownPicked += owner_MouseDownPicked;
     Owner.MouseMovePicked += owner_MouseMovePicked;
     Owner.Picking         += owner_Picking;
     Owner.MouseUp         += owner_MouseUp;
     Owner.DrawingD2d      += owner_DrawingD2d;
 }
コード例 #9
0
ファイル: D2dSnapManipulator.cs プロジェクト: GeertVL/ATF
 /// <summary>
 /// Constructor that permanently attaches to the given TimelineControl by subscribing to its
 /// events</summary>
 /// <param name="owner">The TimelineControl whose events we permanently listen to</param>
 public D2dSnapManipulator(D2dTimelineControl owner)
 {
     m_owner = owner;
     m_owner.GetSnapOffset = GetSnapOffset;
     m_owner.DrawingD2d += owner_DrawingD2d;
     m_owner.MouseUp += owner_MouseUp;
     m_owner.MouseDown += owner_MouseDown;
     m_owner.KeyDown += owner_KeyDown;
 }
コード例 #10
0
ファイル: D2dSnapManipulator.cs プロジェクト: zparr/ATF
 /// <summary>
 /// Constructor that permanently attaches to the given TimelineControl by subscribing to its
 /// events</summary>
 /// <param name="owner">The TimelineControl whose events we permanently listen to</param>
 public D2dSnapManipulator(D2dTimelineControl owner)
 {
     m_owner = owner;
     m_owner.GetSnapOffset = new D2dTimelineControl.SnapOffsetFinder(GetSnapOffset);
     m_owner.DrawingD2d   += owner_DrawingD2d;
     m_owner.MouseUp      += owner_MouseUp;
     m_owner.MouseDown    += owner_MouseDown;
     m_owner.KeyDown      += owner_KeyDown;
 }
コード例 #11
0
ファイル: D2dScrubberManipulator.cs プロジェクト: zparr/ATF
 /// <summary>
 /// Constructor that permanently attaches to the given timeline control by subscribing to its
 /// events</summary>
 /// <param name="owner">The timeline control whose events we permanently listen to</param>
 public D2dScrubberManipulator(D2dTimelineControl owner)
 {
     Owner = owner;
     Owner.MouseDownPicked      += owner_MouseDownPicked;
     Owner.MouseMovePicked      += owner_MouseMovePicked;
     Owner.Picking              += owner_Picking;
     Owner.MouseMove            += MouseMoveHandler;
     Owner.MouseUp              += owner_MouseUp;
     Owner.DrawingD2d           += owner_DrawingD2d;
     Owner.BoundingRectUpdating += owner_BoundingRectUpdating;
 }
コード例 #12
0
 /// <summary>
 /// Constructor that permanently attaches to the given timeline control by subscribing to its
 /// events</summary>
 /// <param name="owner">The timeline control whose events we permanently listen to</param>
 public D2dScrubberManipulator(D2dTimelineControl owner)
 {
     Owner = owner;
     Owner.MouseDownPicked += owner_MouseDownPicked;
     Owner.MouseMovePicked += owner_MouseMovePicked;
     Owner.Picking += owner_Picking;
     Owner.MouseMove += MouseMoveHandler;
     Owner.MouseUp += owner_MouseUp;
     Owner.DrawingD2d += owner_DrawingD2d;
     Owner.BoundingRectUpdating += owner_BoundingRectUpdating;
 }
コード例 #13
0
        /// <summary>
        /// Requests permission to close the client's Control</summary>
        /// <param name="control">Client Control to be closed</param>
        /// <returns>True if the Control can close, or false to cancel</returns>
        /// <remarks>
        /// 1. This method is only called by IControlHostService if the Control was previously
        /// registered for this IControlHostClient.
        /// 2. If true is returned, the IControlHostService calls its own
        /// UnregisterControl. The IControlHostClient has to call RegisterControl again
        /// if it wants to re-register this Control.</remarks>
        public bool Close(Control control)
        {
            D2dTimelineControl timelineControl  = (D2dTimelineControl)control;
            TimelineDocument   timelineDocument = (TimelineDocument)timelineControl.TimelineDocument;

            if (timelineDocument != null)
            {
                return(m_documentService.Close(timelineDocument));
            }

            return(true);
        }
コード例 #14
0
        private void owner_MouseMovePicked(object sender, HitEventArgs e)
        {
            string toolTipText = null;

            if (m_active)
            {
                e.Handled = true;

                if (e.HitRecord.Type == HitType.Interval &&
                    e.MouseEvent.Button == MouseButtons.None &&
                    !m_owner.IsUsingMouse &&
                    m_owner.IsEditable(e.HitRecord.HitPath))
                {
                    SetCursor();
                    TimelinePath hitPath   = e.HitRecord.HitPath;
                    IInterval    hitObject = (IInterval)e.HitRecord.HitTimelineObject;
                    float        worldX    = GdiUtil.InverseTransform(m_owner.Transform, e.MouseEvent.Location.X);

                    //Make sure the snap-to indicator line is drawn.
                    float delta = m_owner.GetSnapOffset(new[] { worldX }, s_snapOptions);

                    worldX += delta;
                    worldX  = m_owner.ConstrainFrameOffset(worldX);

                    using (Matrix localToWorld = D2dTimelineControl.CalculateLocalToWorld(hitPath))
                    {
                        if (worldX <= GdiUtil.Transform(localToWorld, hitObject.Start) ||
                            worldX >= GdiUtil.Transform(localToWorld, hitObject.Start + hitObject.Length))
                        {
                            // Clear the results since a split is impossible.
                            m_owner.GetSnapOffset(new float[] {}, s_snapOptions);
                        }
                        else
                        {
                            toolTipText = worldX.ToString();
                        }
                    }
                }
            }

            if (toolTipText != null)
            {
                m_toolTip.Show(toolTipText, m_owner, e.MouseEvent.Location);
            }
            else
            {
                m_toolTip.Hide(m_owner);
            }
        }
コード例 #15
0
 /// <summary>
 /// Constructor that permanently attaches to the given TimelineControl by subscribing to its
 /// events</summary>
 /// <param name="owner">The timeline control that we are permanently attached to</param>
 public D2dMoveManipulator(D2dTimelineControl owner)
 {
     m_owner = owner;
     m_owner.MouseDownPicked += owner_MouseDownPicked;
     m_owner.MouseMovePicked += owner_MouseMovePicked;
     m_owner.MouseMove       += owner_MouseMove;
     m_owner.MouseDown       += owner_MouseDown;
     m_owner.MouseUp         += owner_MouseUp;
     m_owner.DrawingD2d      += owner_DrawingD2d;
     m_owner.KeyDown         += owner_KeyDown;
     m_owner.DragOver        += owner_DragOver;
     m_owner.DragEnter       += owner_DragEnter;
     m_owner.DragLeave       += owner_DragLeave;
     m_owner.DragDrop        += owner_DragDrop;
 }
コード例 #16
0
 /// <summary>
 /// Constructor that permanently attaches to the given TimelineControl by subscribing to its
 /// events</summary>
 /// <param name="owner">The timeline control that we are permanently attached to</param>
 public D2dMoveManipulator(D2dTimelineControl owner)
 {
     m_owner = owner;
     m_owner.MouseDownPicked += owner_MouseDownPicked;
     m_owner.MouseMovePicked += owner_MouseMovePicked;
     m_owner.MouseMove += owner_MouseMove;
     m_owner.MouseDown += owner_MouseDown;
     m_owner.MouseUp += owner_MouseUp;
     m_owner.DrawingD2d += owner_DrawingD2d;
     m_owner.KeyDown += owner_KeyDown;
     m_owner.DragOver += owner_DragOver;
     m_owner.DragEnter += owner_DragEnter;
     m_owner.DragLeave += owner_DragLeave;
     m_owner.DragDrop += owner_DragDrop;
 }
コード例 #17
0
        private void owner_DrawingD2d(object sender, EventArgs e)
        {
            // Test if anything is visible.
            m_visibleManipulator =
                D2dTimelineControl.CalculateRange(Owner.EditableSelection, out m_worldMin, out m_worldMax);
            if (!m_visibleManipulator)
            {
                return;
            }

            D2dGraphics g           = Owner.D2dGraphics;
            Matrix      worldToView = Owner.Transform;

            // Make the TimelineRenderer draw the ghosts, if necessary. Must happen before
            //  the manipulator is drawn so that snap-to info is created.
            if (IsScaling)
            {
                TimelineLayout layout = Owner.GetLayout();

                GhostInfo[] ghosts = m_resizer.CreateGhostInfo(
                    layout,
                    Owner.GetDragOffset().X,
                    worldToView);

                Owner.Renderer.DrawGhosts(
                    ghosts,
                    DraggedSide,
                    worldToView,
                    Owner.ClientRectangle);
            }

            // Tighten clipping region. Has to occur after DrawGhosts because the TimelineRenderer
            //  assumes that it has to shrink the current Graphics.Clip region by the header width.
            try
            {
                g.PushAxisAlignedClip(Owner.VisibleClientRectangle);

                // Draw the manipulator, giving client code a customization point.
                DrawManipulator(g, out m_leftHandle, out m_rightHandle);
            }
            finally
            {
                g.PopAxisAlignedClip();
            }
        }
コード例 #18
0
        private void owner_MouseDownPicked(object sender, HitEventArgs e)
        {
            TimelinePath hitPath     = e.HitRecord.HitPath;
            IInterval    hitInterval = e.HitRecord.HitTimelineObject as IInterval;

            if (m_active &&
                e.MouseEvent.Button == MouseButtons.Left &&
                !m_owner.IsUsingMouse &&
                m_owner.IsEditable(hitPath))
            {
                if (hitInterval != null &&
                    e.HitRecord.Type == HitType.Interval)
                {
                    PointF mouseLocation = e.MouseEvent.Location;
                    float  worldX        =
                        Sce.Atf.GdiUtil.InverseTransform(m_owner.Transform, mouseLocation.X);

                    worldX += m_owner.GetSnapOffset(new[] { worldX }, s_snapOptions);

                    float fraction;
                    using (Matrix localToWorld = D2dTimelineControl.CalculateLocalToWorld(hitPath))
                    {
                        fraction =
                            (worldX - GdiUtil.Transform(localToWorld, hitInterval.Start)) /
                            GdiUtil.TransformVector(localToWorld, hitInterval.Length);
                    }

                    if (m_owner.Selection.SelectionContains(hitInterval))
                    {
                        SplitSelectedIntervals(fraction);
                    }
                    else
                    {
                        SplitUnselectedInterval(hitInterval, fraction);
                    }
                }
                Active    = false;
                e.Handled = true; //don't let subsequent listeners get this event
            }
        }
コード例 #19
0
            /// <summary>
            /// Constructor for a single scaling or resizing operation</summary>
            /// <param name="side">Side of the interval or manipulator is being dragged</param>
            /// <param name="mode">Scaling mode</param>
            /// <param name="boundary">World coordinate starting position for the drag operation</param>
            /// <param name="owner">The timeline control that this manipulator is attached to</param>
            internal Resizer(Side side, ScaleMode mode, float boundary, D2dTimelineControl owner)
            {
                m_intervalSide     = side;
                Mode               = mode;
                m_originalBoundary = boundary;
                m_owner            = owner;
                if (Mode == ScaleMode.InPlace)
                {
                    m_selection = new HashSet <TimelinePath>(GetEditableEvents <IInterval>());
                }
                else
                {
                    m_selection = new HashSet <TimelinePath>(GetEditableEvents <IEvent>());
                }
                if (m_selection.Count == 0)
                {
                    throw new InvalidTransactionException("only IEvents can be resized");
                }

                m_initialMin = float.MaxValue;
                m_initialMax = float.MinValue;

                if (Mode == ScaleMode.TimePeriod)
                {
                    foreach (TimelinePath path in m_selection)
                    {
                        IEvent curr = (IEvent)path.Last;
                        if (curr.Start < m_initialMin)
                        {
                            m_initialMin = curr.Start;
                        }
                        if (m_initialMax < curr.Start + curr.Length)
                        {
                            m_initialMax = curr.Start + curr.Length;
                        }
                    }
                }

                DragOffsetWithSnap = m_owner.GetDragOffset().X;
            }
コード例 #20
0
ファイル: D2dSnapManipulator.cs プロジェクト: zparr/ATF
        /// <summary>
        /// Gets the offset from one of the world snap points to the closest non-selected object's edge</summary>
        /// <param name="movingPoints">The x-coordinates to snap "from", in world coordinates</param>
        /// <param name="options">The options to control the behavior. If null, the defaults are used.</param>
        /// <returns>The value to be added, to GetDragOffset().X, for example. Is in world coordinates.</returns>
        private float GetSnapOffset(IEnumerable <float> movingPoints, D2dTimelineControl.SnapOptions options)
        {
            //we want to recalculate m_snapInfo and reflect changes to the snap-to lines
            m_snapInfo.Clear();
            m_owner.Invalidate();

            if (options == null)
            {
                options = new D2dTimelineControl.SnapOptions();
            }

            // Check for user-forced snapping and no-snapping.
            if (options.CheckModifierKeys)
            {
                Keys modKeys = Control.ModifierKeys;
                if (s_deactivatorKeys != Keys.None &&
                    (modKeys & s_deactivatorKeys) == s_deactivatorKeys)
                {
                    return(0.0f);
                }
                if (s_activatorKeys != Keys.None &&
                    (modKeys & s_activatorKeys) != s_activatorKeys)
                {
                    return(0.0f);
                }
            }

            // Prepare helper object on each moving point.
            foreach (float snapping in movingPoints)
            {
                m_snapInfo.Add(new SnapOffsetInfo(snapping));
            }
            if (m_snapInfo.Count == 0)
            {
                return(0.0f);
            }

            // Find the closest IEvent.
            float worldSnapTolerance = GdiUtil.InverseTransformVector(m_owner.Transform, s_snapTolerance);

            List <TimelinePath> events = new List <TimelinePath>(
                D2dTimelineControl.GetObjects <IEvent>(m_owner.Timeline));

            // Allow for snapping to a scrubber manipulator.
            if (m_scrubber != null && options.IncludeScrubber)
            {
                events.Add(new TimelinePath(m_scrubber));
            }

            foreach (TimelinePath path in events)
            {
                if (options.IncludeSelected ||
                    !m_owner.Selection.SelectionContains(path))
                {
                    IEvent snapToEvent = (IEvent)path.Last;

                    if (options.Filter == null ||
                        options.Filter(snapToEvent, options))
                    {
                        Matrix localToWorld = D2dTimelineControl.CalculateLocalToWorld(path);
                        float  start, length;
                        GetEventDimensions(snapToEvent, localToWorld, out start, out length);

                        foreach (SnapOffsetInfo info in m_snapInfo)
                        {
                            info.Update(start, snapToEvent, worldSnapTolerance);
                            if (length > 0)
                            {
                                info.Update(start + length, snapToEvent, worldSnapTolerance);
                            }
                        }
                    }
                }
            }

            // Keep only the shortest distance snap-to points. Could be multiple in case of tie.
            SnapOffsetInfo.RemoveInvalid(m_snapInfo);
            if (m_snapInfo.Count == 0)
            {
                return(0.0f);
            }

            SnapOffsetInfo topInfo = m_snapInfo[0];

            return(topInfo.Offset);
        }
コード例 #21
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 = 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 = D2dTimelineControl.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 D2dTimelineControl.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);

            // Pretend that drag-drop objects are in the TimelineLayout object
            if (m_owner.DragDropObjects != null)
            {
                foreach (ITimelineObject dragDrop in m_owner.DragDropObjects)
                {
                    layout[dragDrop] = GetDragDropBounds(dragDrop);
                }
            }

            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;
                    valid &= m_owner.Constraints.IsStartValid(interval, ref start);
                    valid &= m_owner.Constraints.IsLengthValid(interval, ref length);

                    if (valid)
                    {
                        ITrack intervalTrack = interval.Track;
                        if (intervalTrack != null)
                        {
                            yOffset = layout[target].Y - layout[interval.Track].Y;
                        }
                        else
                        {
                            yOffset = layout[target].Y - bounds.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;
                    valid &= m_owner.Constraints.IsStartValid(key, ref start);

                    if (valid)
                    {
                        ITrack keyTrack = key.Track;
                        if (keyTrack != null)
                        {
                            yOffset = layout[targetTrack].Y - layout[key.Track].Y;
                        }
                        else
                        {
                            yOffset = layout[targetTrack].Y - bounds.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 =
                            (DragDelta.Y < 0) ? GetLastTrack() : GetFirstTrack();
                    }
                }
                else if (group != null)
                {
                    xOffset = 0;
                    if (target == null)
                    {
                        IList <IGroup> groups = m_owner.TimelineDocument.Timeline.Groups;
                        target = (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);
        }
コード例 #22
0
 private void owner_BoundingRectUpdating(object sender, D2dTimelineControl.BoundingRectEventArgs e)
 {
     e.NewClientRect = m_handleRect;
 }
コード例 #23
0
ファイル: D2dSnapManipulator.cs プロジェクト: GeertVL/ATF
        /// <summary>
        /// Gets the offset from one of the world snap points to the closest non-selected object's edge</summary>
        /// <param name="movingPoints">The x-coordinates to snap "from", in world coordinates</param>
        /// <param name="options">The options to control the behavior. If null, the defaults are used.</param>
        /// <returns>The value to be added, to GetDragOffset().X, for example. Is in world coordinates.</returns>
        private float GetSnapOffset(IEnumerable<float> movingPoints, D2dTimelineControl.SnapOptions options)
        {
            //we want to recalculate m_snapInfo and reflect changes to the snap-to lines
            m_snapInfo.Clear();
            m_owner.Invalidate();

            if (options == null)
                options = new D2dTimelineControl.SnapOptions();

            // Check for user-forced snapping and no-snapping.
            if (options.CheckModifierKeys)
            {
                Keys modKeys = Control.ModifierKeys;
                if (s_deactivatorKeys != Keys.None &&
                    (modKeys & s_deactivatorKeys) == s_deactivatorKeys)
                    return 0.0f;
                if (s_activatorKeys != Keys.None &&
                    (modKeys & s_activatorKeys) != s_activatorKeys)
                    return 0.0f;
            }

            // Prepare helper object on each moving point.
            foreach (float snapping in movingPoints)
            {
                m_snapInfo.Add(new SnapOffsetInfo(snapping));
            }
            if (m_snapInfo.Count == 0)
                return 0.0f;
            
            // Find the closest IEvent.
            float worldSnapTolerance = GdiUtil.InverseTransformVector(m_owner.Transform, s_snapTolerance);

            List<TimelinePath> events = new List<TimelinePath>(
                D2dTimelineControl.GetObjects<IEvent>(m_owner.Timeline));

            // Allow for snapping to a scrubber manipulator.
            if (m_scrubber != null && options.IncludeScrubber)
                events.Add(new TimelinePath(m_scrubber));

            foreach (TimelinePath path in events)
            {
                if (options.IncludeSelected ||
                    !m_owner.Selection.SelectionContains(path))
                {
                    IEvent snapToEvent = (IEvent)path.Last;

                    if (options.Filter == null ||
                        options.Filter(snapToEvent, options))
                    {
                        Matrix localToWorld = D2dTimelineControl.CalculateLocalToWorld(path);
                        float start, length;
                        GetEventDimensions(snapToEvent, localToWorld, out start, out length);

                        foreach (SnapOffsetInfo info in m_snapInfo)
                        {
                            info.Update(start, snapToEvent, worldSnapTolerance);
                            if (length > 0)
                                info.Update(start + length, snapToEvent, worldSnapTolerance);
                        }
                    }
                }
            }

            // Keep only the shortest distance snap-to points. Could be multiple in case of tie.
            SnapOffsetInfo.RemoveInvalid(m_snapInfo);
            if (m_snapInfo.Count == 0)
                return 0.0f;

            SnapOffsetInfo topInfo = m_snapInfo[0];
            return topInfo.Offset;
        }
コード例 #24
0
ファイル: TimelineContext.cs プロジェクト: zoombapup/ATF
        /// <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>());
        }
コード例 #25
0
        private bool MoveSnapFilter(IEvent testEvent, D2dTimelineControl.SnapOptions options)
        {
            ITimelineReference movingReference = options.FilterContext as ITimelineReference;
            if (movingReference == null)
                return true;

            IHierarchicalTimeline movingTimeline = movingReference.Target;
            if (movingTimeline == null)
                return true;

            ITimeline owningTimeline = null;
            if (testEvent is ITimelineReference)
                owningTimeline = ((ITimelineReference)testEvent).Parent;
            else if (testEvent is IInterval)
                owningTimeline = ((IInterval)testEvent).Track.Group.Timeline;
            else if (testEvent is IKey)
                owningTimeline = ((IKey)testEvent).Track.Group.Timeline;
            else if (testEvent is IMarker)
                owningTimeline = ((IMarker)testEvent).Timeline;

            // Is the reference being compared to an object that it owns? Never snap!
            if (owningTimeline == movingTimeline)
                return false;

            // Is the reference being compared against a sibling object? Snap away.
            if (owningTimeline == movingReference.Parent)
                return true;

            // to-do: support a true hierarchy. We can't support directed acyclic graphs because
            //  the Layout implementation uses a Dictionary of ITimelineObjects and the same object
            //  can't have multiple layout rectangles. We could support a tree hierarchy, though.
            //// The test object may be a grandchild of the moving reference. Look for a parent.
            //owningTimeline = owningTimeline.Parent;

            return true;
        }
コード例 #26
0
        /// <summary>
        /// Gets the range of events that intersect the rectangle that encloses 'begin' and 'end'</summary>
        /// <param name="begin">Beginning timeline path</param>
        /// <param name="end">Ending timeline path</param>
        /// <returns>Enumeration of timeline paths that intersect the rectangle.
        /// A timeline path is a sequence of objects in timelines, e.g., groups, tracks, events.</returns>
        protected virtual IEnumerable <TimelinePath> GetRangeOfEvents(TimelinePath begin, TimelinePath end)
        {
            // If the two paths are the same, then the rectangle is just a point.
            // This check fixes a bug where the 'rectangle' becomes the whole interval
            //  and then falsely selects an adjacent zero-length object due to Overlaps().
            if (begin.Equals(end))
            {
                return new TimelinePath[] { begin }
            }
            ;

            // Get the range of tracks between these two events.
            bool searchMarkers = false;

            System.Collections.IEnumerable rangeOfTracks;
            if (begin.Last is IMarker || end.Last is IMarker)
            {
                rangeOfTracks = Owner.AllTracks;

                searchMarkers = true;
            }
            else
            {
                TimelinePath beginTrack = GetOwningTrack(begin);
                TimelinePath endTrack   = GetOwningTrack(end);
                rangeOfTracks = GetRangeOfTracks(beginTrack, endTrack);
            }

            // Get the range of times to look for.
            float beginStart, beginEnd;

            D2dTimelineControl.CalculateRange(begin, out beginStart, out beginEnd);
            float endStart, endEnd;

            D2dTimelineControl.CalculateRange(end, out endStart, out endEnd);
            float beginTime = Math.Min(beginStart, endStart);
            float endTime   = Math.Max(beginEnd, endEnd);

            // Look through all the IEvents of these tracks.
            List <TimelinePath> range = new List <TimelinePath>();

            foreach (TimelinePath testPath in rangeOfTracks)
            {
                ITrack track = (ITrack)testPath.Last;
                foreach (IKey key in track.Keys)
                {
                    testPath.Last = key;
                    if (Overlaps(testPath, beginTime, endTime))
                    {
                        range.Add(new TimelinePath(testPath));
                    }
                }

                foreach (IInterval interval in track.Intervals)
                {
                    testPath.Last = interval;
                    if (Overlaps(testPath, beginTime, endTime))
                    {
                        range.Add(new TimelinePath(testPath));
                    }
                }
            }

            // Look for markers?
            if (searchMarkers)
            {
                foreach (TimelinePath testPath in Owner.AllMarkers)
                {
                    if (Overlaps(testPath, beginTime, endTime))
                    {
                        range.Add(testPath);
                    }
                }
            }

            return(range);
        }