Esempio n. 1
0
        /// <summary>
        /// Saves the document at the given URI. Persists document data.</summary>
        /// <param name="document">Document to save</param>
        /// <param name="uri">New document URI</param>
        public void Save(IDocument document, Uri uri)
        {
            TimelineDocument timelineDocument = document as TimelineDocument;

            if (timelineDocument == null)
            {
                return;
            }

            if (m_fileWatcherService != null)
            {
                m_fileWatcherService.Unregister(uri.LocalPath);
            }

            string   filePath = uri.LocalPath;
            FileMode fileMode = File.Exists(filePath) ? FileMode.Truncate : FileMode.OpenOrCreate;

            using (FileStream stream = new FileStream(filePath, fileMode))
            {
                var writer = new TimelineXmlWriter(s_schemaLoader.TypeCollection);
                writer.Write(timelineDocument.DomNode, stream, uri);
            }

            if (m_fileWatcherService != null)
            {
                m_fileWatcherService.Register(uri.LocalPath);
            }

            // mark all sub-context histories as clean);
            foreach (EditingContext context in timelineDocument.EditingContexts)
            {
                context.History.Dirty = false;
            }
        }
Esempio n. 2
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;
        }
Esempio n. 3
0
        /// <summary>
        /// Attempts to unload a sub-document if only 1 or 0 references to it exist</summary>
        /// <param name="uri">URI of sub-document</param>
        public void UnloadSubDocument(Uri uri)
        {
            TimelineDocument doc = (TimelineDocument)s_repository.GetDocument(uri);

            if (doc != null && NumReferences(doc) <= 1)
            {
                s_repository.Remove(doc);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Makes the document visible to the user</summary>
        /// <param name="document">Document to show</param>
        public void Show(IDocument document)
        {
            TimelineDocument timelineDocument = document as TimelineDocument;

            if (timelineDocument != null)
            {
                m_controlHostService.Show(timelineDocument.TimelineControl);
            }
        }
Esempio n. 5
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. 6
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);
        }
Esempio n. 7
0
 /// <summary>
 /// Attempts to load a sub-document if it is not already loaded</summary>
 /// <param name="uri">URI of sub-document</param>
 public void LoadSubDocument(Uri uri)
 {
     //The URI can be null, for example, if the property editor's Reset Current command is used.
     //  http://tracker.ship.scea.com/jira/browse/ATFINTERNALJIRA-212
     if (uri != null)
     {
         TimelineDocument doc = (TimelineDocument)s_repository.GetDocument(uri);
         if (doc == null)
         {
             LoadOrCreateDocument(uri, false);
             InvalidateTimelineControls();
         }
     }
 }
Esempio n. 8
0
        /// <summary>
        /// Opens or creates a document at the given URI.
        /// Uses LoadOrCreateDocument() to create a D2dTimelineRenderer and D2dTimelineControl.</summary>
        /// <param name="uri">Document URI</param>
        /// <returns>Document, or null if the document couldn't be opened or created</returns>
        public IDocument Open(Uri uri)
        {
            TimelineDocument document = LoadOrCreateDocument(uri, true); //true: this is a master document

            if (document != null)
            {
                m_controlHostService.RegisterControl(
                    document.TimelineControl,
                    document.Cast <TimelineContext>().ControlInfo,
                    this);

                document.TimelineControl.Frame();
            }

            return(document);
        }
Esempio n. 9
0
        /// <summary>
        /// Closes the document and removes any views of it from the UI</summary>
        /// <param name="document">Document to close</param>
        public void Close(IDocument document)
        {
            // Close the root timeline's control.
            TimelineDocument timelineDocument = document as TimelineDocument;

            if (timelineDocument == null)
            {
                return;
            }

            m_controlHostService.UnregisterControl(timelineDocument.TimelineControl);
            if (m_reloading || NumReferences(timelineDocument) == 1)
            {
                s_repository.Remove(timelineDocument);
            }
            m_contextRegistry.RemoveContext(timelineDocument);
        }
Esempio n. 10
0
        /// <summary>
        /// Updates command state for given command</summary>
        /// <param name="commandTag">Command</param>
        /// <param name="commandState">Command info to update</param>
        public void UpdateCommand(object commandTag, CommandState commandState)
        {
            TimelineDocument document = m_contextRegistry.GetActiveContext <TimelineDocument>();

            if (document == null)
            {
                return;
            }

            if (commandTag is Command)
            {
                switch ((Command)commandTag)
                {
                case Command.ToggleSplitMode:
                    commandState.Check = document.SplitManipulator != null ? document.SplitManipulator.Active : false;
                    break;
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Performs custom actions when FileChanged event occurs.
        /// Updates current document if necessary.</summary>
        /// <param name="sender">Event sender</param>
        /// <param name="e">FileSystemEventArgs containing event data</param>
        void fileWatcherService_FileChanged(object sender, FileSystemEventArgs e)
        {
            if (m_mainForm == null || m_reloading)
            {
                return;
            }

            Uri      uri           = new Uri(e.FullPath);
            FileInfo fileInfo      = new FileInfo(uri.LocalPath);
            DateTime lastWriteTime = fileInfo.LastWriteTime;
            DateTime loadedWriteTime;

            if (m_loadedWriteTimes.TryGetValue(uri, out loadedWriteTime) && loadedWriteTime >= lastWriteTime)
            {
                return; // Already loaded most recent version of the file
            }
            TimelineDocument doc = null;

            // First test if this document is a "master" document
            doc = m_documentRegistry.GetDocument(uri) as TimelineDocument;
            if (doc == null || doc.TimelineControl == null)
            {
                // It's not a master document. Check if it's already loaded. Since sub-documents are read-only,
                //  we don't need to ask the user if they want to reload. Just do it.
                doc = s_repository.GetDocument(uri) as TimelineDocument;
                if (doc != null)
                {
                    s_repository.Remove(doc);
                    WinFormsUtil.InvokeIfRequired(m_mainForm,
                                                  delegate
                    {
                        LoadOrCreateDocument(uri, false);
                        InvalidateTimelineControls();
                    });
                }
                return;
            }

            // This is a master document. Query the user and if it's OK, then close it and reopen it, and this
            //  will update other open master documents that might reference this one as a sub-document.
            WinFormsUtil.InvokeIfRequired(m_mainForm,
                                          delegate
            {
                DialogResult result = MessageBox.Show(
                    m_mainForm,
                    doc.Uri.LocalPath + Environment.NewLine + Environment.NewLine +
                    "The file above was changed outside the editor.".Localize() + Environment.NewLine +
                    "Reload, and lose all changes made in the editor?".Localize(),
                    "File Changed, Reload?".Localize(),
                    MessageBoxButtons.YesNo);

                // Update last write time, as the file may have been saved again while the
                // message box was displayed
                fileInfo      = new FileInfo(uri.LocalPath);
                lastWriteTime = fileInfo.LastWriteTime;

                if (result == DialogResult.Yes)
                {
                    // Reload the document
                    m_reloading = true;
                    doc.Dirty   = false;
                    Close(doc.TimelineControl);
                    Open(doc.Uri);
                    m_loadedWriteTimes[uri] = lastWriteTime;
                    m_reloading             = false;
                    InvalidateTimelineControls();
                }
            });
        }
Esempio n. 12
0
        /// <summary>
        /// Loads the document at the given URI. Creates a D2dTimelineRenderer and D2dTimelineControl
        /// (through TimelineDocument's Renderer property) to render and display timelines.
        /// If isMasterDocument is true and if the file doesn't exist, a new document is created.</summary>
        /// <param name="uri">URI of document to load</param>
        /// <param name="isMasterDocument">True iff is master document</param>
        /// <returns>TimelineDocument loaded</returns>
        private TimelineDocument LoadOrCreateDocument(Uri uri, bool isMasterDocument)
        {
            // Documents need to have a absolute Uri, so that the relative references to sub-documents
            //  are not ambiguous, and so that the FileWatcherService can be used.
            string filePath;

            if (uri.IsAbsoluteUri)
            {
                filePath = uri.LocalPath;
            }
            else if (!isMasterDocument)
            {
                filePath = PathUtil.GetAbsolutePath(uri.OriginalString,
                                                    Path.GetDirectoryName(s_repository.ActiveDocument.Uri.LocalPath));
                uri = new Uri(filePath, UriKind.Absolute);
            }
            else
            {
                filePath = PathUtil.GetAbsolutePath(uri.OriginalString, Directory.GetCurrentDirectory());
                uri      = new Uri(filePath, UriKind.Absolute);
            }

            // Check if the repository contains this Uri. Remember that document Uris have to be absolute.
            bool             isNewToThisEditor = true;
            DomNode          node     = null;
            TimelineDocument document = (TimelineDocument)s_repository.GetDocument(uri);

            if (document != null)
            {
                node = document.DomNode;
                isNewToThisEditor = false;
            }
            else if (File.Exists(filePath))
            {
                // read existing document using standard XML reader
                using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    DomXmlReader reader = new DomXmlReader(s_schemaLoader);
                    node = reader.Read(stream, uri);
                }
            }
            else if (isMasterDocument)
            {
                // create new document by creating a Dom node of the root type defined by the schema
                node = new DomNode(Schema.timelineType.Type, Schema.timelineRootElement);
            }

            if (node != null)
            {
                if (document == null)
                {
                    document = node.Cast <TimelineDocument>();

                    D2dTimelineRenderer renderer = CreateTimelineRenderer();
                    document.Renderer = renderer;
                    renderer.Init(document.TimelineControl.D2dGraphics);

                    string      fileName    = Path.GetFileName(filePath);
                    ControlInfo controlInfo = new ControlInfo(fileName, filePath, StandardControlGroup.Center);

                    //Set IsDocument to true to prevent exception in command service if two files with the
                    //  same name, but in different directories, are opened.
                    controlInfo.IsDocument = true;

                    TimelineContext timelineContext = document.Cast <TimelineContext>();
                    timelineContext.ControlInfo = controlInfo;

                    document.Uri = uri;

                    if (isMasterDocument)
                    {
                        s_repository.ActiveDocument = document;//adds 'document'
                    }
                    else
                    {
                        // For sub-documents, we want ActiveDocument to remain the main document so that
                        //  TimelineValidator can identify if a sub-document or master document is being
                        //  modified.
                        IDocument previous = s_repository.ActiveDocument;
                        s_repository.ActiveDocument = document; //adds 'document'
                        s_repository.ActiveDocument = previous; //restores master document
                    }
                }

                IHierarchicalTimeline hierarchical = document.Timeline as IHierarchicalTimeline;
                if (hierarchical != null)
                {
                    ResolveAll(hierarchical, new HashSet <IHierarchicalTimeline>());
                }

                // Listen to events if this is the first time we've seen this.
                if (isNewToThisEditor)
                {
                    // The master document/context needs to listen to events on any sub-document
                    //  so that transactions can be cancelled correctly.
                    if (isMasterDocument)
                    {
                        node.AttributeChanging += DomNode_AttributeChanging;
                    }
                    else
                    {
                        DomNode masterNode = s_repository.ActiveDocument.As <DomNode>();
                        node.SubscribeToEvents(masterNode);
                    }
                }

                // Initialize Dom extensions now that the data is complete
                node.InitializeExtensions();
            }

            return(document);
        }
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
        /// <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. 15
0
        private void observable_ItemChanged(object sender, ItemChangedEventArgs <object> e)
        {
            TimelineDocument doc = sender.Cast <TimelineDocument>();

            InvalidateTimelineControls();
        }
Esempio n. 16
0
        private void observable_Reloaded(object sender, EventArgs e)
        {
            TimelineDocument doc = sender.Cast <TimelineDocument>();

            InvalidateTimelineControls();
        }