Exemplo n.º 1
0
        public void ChangesCanBeIteratedOverSinceAChange()
        {
            var h = new DocumentHistory();

            h.Add(FakeChange("foo"));
            h.Add(FakeChange("bar"));
            h.Add(FakeChange("baz"));

            Assert.AreEqual(
                new string[] { "bar", "baz" },
                h.IterateChangesAfter("foo").Select(c => c.Id).ToArray()
                );

            Assert.AreEqual(
                new string[] { "baz" },
                h.IterateChangesAfter("bar").Select(c => c.Id).ToArray()
                );

            Assert.AreEqual(
                new string[] {},
                h.IterateChangesAfter("baz").Select(c => c.Id).ToArray()
                );

            Assert.AreEqual(
                new string[] {},
                h.IterateChangesAfter("xxx").Select(c => c.Id).ToArray()
                );

            Assert.AreEqual(
                new string[] {},
                new DocumentHistory().IterateChangesAfter("xxx").Select(c => c.Id).ToArray()
                );
        }
Exemplo n.º 2
0
        public DocumentInfo CreateDocument(CreateDocumentInput input, Stream stream)
        {
            var documentInfo = Mapper.Map <DocumentInfo>(input);

            StoreDocumentFile(documentInfo, stream);
            HandleTifFile(documentInfo.FileType, documentInfo.Path);

            documentInfo.Key            = Guid.NewGuid().ToString();
            documentInfo.CreateTime     = DateTime.Now;
            documentInfo.ModifyTime     = documentInfo.CreateTime;
            documentInfo.ModifyUserId   = documentInfo.CreateUserID;
            documentInfo.ModifyUserName = documentInfo.CreateUserName;
            documentInfo.CurrentVersion = 1;

            _context.DocumentInfos.Add(documentInfo);
            _context.SaveChanges();

            var             historyPath = StoreHistoryFile(stream, documentInfo.FileType);
            DocumentHistory fileHistory = new DocumentHistory
            {
                DocumentInfoId  = documentInfo.Id,
                Version         = 1,
                PreviousVersion = -1,
                Key             = documentInfo.Key,
                Path            = historyPath,
                UserId          = input.CreateUserID,
                UserName        = input.CreateUserName,
                CreateTime      = DateTime.Now
            };

            _context.DocumentHistories.Add(fileHistory);
            _context.SaveChanges();

            return(documentInfo);
        }
Exemplo n.º 3
0
        private void CreateDocument(DocumentHistory history)
        {
            _logger.LogDebug("create document: {0}", history.Path);

            if (_documentsByPath.TryGetValue(history.Path, out var _))
            {
                _logger.LogWarning($"invalid created log found: {history.Id}");
                UpdateDocument(history);
            }

            var document = new MaintainanceDocument()
            {
                DocumentId   = _documentId++,
                Path         = history.Path,
                StorageKey   = history.StorageKey,
                ContentType  = history.ContentType,
                FileSize     = history.FileSize,
                Hash         = history.Hash,
                Created      = history.Created,
                LastModified = history.LastModified,
                Histories    = new List <DocumentHistory>()
                {
                    history
                }
            };

            _documentStore.Add(document.DocumentId, document);
            _documentsByPath.Add(document.Path, document);
        }
Exemplo n.º 4
0
        private void UpdateDocument(DocumentHistory history)
        {
            _logger.LogDebug("update document: {0}", history.Path);

            if (!_documentsByPath.TryGetValue(history.Path, out var document))
            {
                _logger.LogWarning($"invalid update history found: {history.Id}");
                CreateDocument(history);
            }
            else
            {
                if (history.FileSize != document.FileSize ||
                    history.Hash != document.Hash ||
                    history.LastModified != document.LastModified ||
                    history.Created != document.Created)
                {
                    document.Histories.Add(history);
                    document.Path         = history.Path;
                    document.StorageKey   = history.StorageKey;
                    document.ContentType  = history.ContentType;
                    document.FileSize     = history.FileSize;
                    document.Hash         = history.Hash;
                    document.Created      = history.Created;
                    document.LastModified = history.LastModified;
                    document.Histories.Add(history);
                }
                else
                {
                    _deletableHistories.Add(history);
                }
            }
        }
        public Row(DocumentHistory documentHistory)
        {
            Time = documentHistory.Time.ToLongTimeString();
            string state;

            switch (documentHistory.State)
            {
            case DocumentPrintState.BeginPrinting:
                state = "Начало печати"; break;

            case DocumentPrintState.Printed:
                state = "Распечатано"; break;

            case DocumentPrintState.PrintingError:
                state = "Ошибка печати"; break;

            case DocumentPrintState.PrintingRepeat:
                state = "Ошибка. Повторная отправка задания печати"; break;

            default:
                state = documentHistory.State.ToString();
                break;
            }
            State = state;
        }
Exemplo n.º 6
0
        public void Apply(DocumentHistory history)
        {
            if (!AssertHistory(history))
            {
                _deletableHistories.Add(history);
                return;
            }
            switch (history.Discriminator)
            {
            case DocumentHistoryDiscriminator.DocumentCreated:
                CreateDocument(history);
                break;

            case DocumentHistoryDiscriminator.DocumentDeleted:
                DeleteDocument(history);
                break;

            case DocumentHistoryDiscriminator.DocumentUpdated:
                UpdateDocument(history);
                break;

            default:
                break;
            }
        }
 private void Deleted(DocmsContext ctx, string path, int contentId)
 {
     ctx.DocumentHistories.Add(DocumentHistory.DocumentDeleted(
                                   DateTime.UtcNow,
                                   contentId,
                                   path));
 }
Exemplo n.º 8
0
        /***************************************************/
        /**** Public Methods                            ****/
        /***************************************************/

        public static void Serialize <T>(IEnumerable <T> bhomObjects, BH.oM.XML.GBXML gbx, string fileName, XMLSettings settings) where T : IObject
        {
            switch (settings.ExportDetail)
            {
            case ExportDetail.Full:
                SerializeCollectionFull(bhomObjects as dynamic, gbx, settings);
                break;

            case ExportDetail.BuildingShell:
                SerializeBuildingShell(bhomObjects as dynamic, gbx, settings);
                break;

            case ExportDetail.IndividualSpaces:
                SerializeSpaces(bhomObjects, fileName, settings);
                break;

            default:
                throw new NotImplementedException("That option has not been implemented");
            }

            // Document History
            DocumentHistory DocumentHistory = new DocumentHistory();

            DocumentHistory.CreatedBy.Date = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss");
            gbx.DocumentHistory            = DocumentHistory;
        }
Exemplo n.º 9
0
        public async Task Handle(DomainEventNotification <DocumentDeletedEvent> notification, CancellationToken cancellationToken = default)
        {
            var ev = notification.Event;

            _db.DocumentHistories
            .Add(DocumentHistory.DocumentDeleted(
                     ev.Timestamp,
                     ev.Entity.Id,
                     ev.Path.ToString()));
            await _db.SaveChangesAsync();
        }
Exemplo n.º 10
0
        public static DocumentHistory DocumentHistory(System.Guid cADModelId)
        {
            DocumentHistory documentHistory = new DocumentHistory();

            documentHistory.ProgramInfo = ProgramInfo();
            documentHistory.CreatedBy   = CreatedBy(cADModelId);
            documentHistory.ModifiedBy  = ModifiedBy();
            documentHistory.PersonInfo  = PersonInfo();

            return(documentHistory);
        }
Exemplo n.º 11
0
 public static DocumentHistoryDto MapToDocumentHistoryDto(DocumentHistory documentHistory)
 {
     return(new DocumentHistoryDto()
     {
         ModifiedAt = documentHistory.ModifiedAt,
         DocumentTitle = documentHistory.DocumentTitle,
         Author = documentHistory.ModifiedByUser.FirstName + " " + documentHistory.ModifiedByUser.LastName,
         CaseNumber = documentHistory.CaseNumber,
         DocumentCategoryName = documentHistory.DocumentCategoryName,
         DocumentDescription = documentHistory.DocumentDescription,
         DocumentPath = documentHistory.DocumentPath
     });
 }
Exemplo n.º 12
0
 public TransactionalNumericEditBox(DocumentHistory history)
 {
     BeginSpin += () => history.BeginTransaction();
     EndSpin   += () => {
         history.CommitTransaction();
         history.EndTransaction();
     };
     Submitted += s => {
         if (history.IsTransactionActive)
         {
             history.RollbackTransaction();
         }
     };
 }
Exemplo n.º 13
0
        private void Updated(DocmsContext ctx, string path, int contentId)
        {
            var now = DateTime.UtcNow;

            ctx.DocumentHistories.Add(DocumentHistory.DocumentUpdated(
                                          DateTime.UtcNow,
                                          contentId,
                                          path,
                                          "stragekey",
                                          "text/plain",
                                          5 + contentId.ToString().Length,
                                          Hash.CalculateHash(Encoding.UTF8.GetBytes("Hello" + contentId)),
                                          now,
                                          now));
        }
Exemplo n.º 14
0
        static void Main(string[] args)
        {
            var doc = new Document();
            var his = new DocumentHistory();

            doc.Content = "Testing Memento Pattern!";

            his.Push(doc.CreateState());
            doc.FontName = "TimeNewRoman";
            his.Push(doc.CreateState());
            Console.WriteLine(doc);

            doc.Restore(his.Pop);
            Console.WriteLine(doc);
        }
Exemplo n.º 15
0
        private void DeleteDocument(DocumentHistory history)
        {
            _logger.LogDebug("delete document: {0}", history.Path);

            if (!_documentsByPath.TryGetValue(history.Path, out var document))
            {
                _logger.LogWarning($"invalid delete history found: {history.Id}");
                _deletableHistories.Add(history);
            }
            else
            {
                document.Histories.Add(history);
                document.Deleted = true;
                _documentsByPath.Remove(document.Path);
            }
        }
Exemplo n.º 16
0
        public void ChangesCanBeTestedForContainment()
        {
            var h = new DocumentHistory();

            h.Add(FakeChange("foo"));
            h.Add(FakeChange("bar"));
            h.Add(FakeChange("baz"));

            Assert.IsTrue(h.Contains("foo"));
            Assert.IsTrue(h.Contains("bar"));
            Assert.IsTrue(h.Contains("baz"));

            Assert.IsFalse(h.Contains("xxx"));
            Assert.IsFalse(h.Contains("yyy"));
            Assert.IsFalse(h.Contains("zzz"));
        }
        public GetHistoryResponse GetHistory(GetHistoryRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            // Must have the documentId you'd like to add annotations to.
            // If you only have the document cache URI, DocumentFactory.LoadFromUri needs to be called.
            if (string.IsNullOrEmpty(request.DocumentId))
            {
                throw new ArgumentNullException("documentId");
            }

            IList <DocumentHistoryItem> items = null;

            var cache = ServiceHelper.Cache;

            using (var document = DocumentFactory.LoadFromCache(cache, request.DocumentId))
            {
                // Ensure we have the document.
                DocumentHelper.CheckLoadFromCache(document);

                DocumentHistory history = document.History;
                items = history.GetItems();

                if (items != null && request.ClearHistory)
                {
                    history.Clear();
                    document.SaveToCache();
                }
            }

            if (_loggingDocumentHistory)
            {
                ShowHistory(request.DocumentId, items);
            }

            DocumentHistoryItem[] itemsArray = new DocumentHistoryItem[items.Count];
            items.CopyTo(itemsArray, 0);
            GetHistoryResponse response = new GetHistoryResponse
            {
                Items = itemsArray
            };

            return(response);
        }
Exemplo n.º 18
0
        public async Task Handle(DomainEventNotification <DocumentUpdatedEvent> notification, CancellationToken cancellationToken = default)
        {
            var ev = notification.Event;

            _db.DocumentHistories
            .Add(DocumentHistory.DocumentUpdated(
                     ev.Timestamp,
                     ev.Entity.Id,
                     ev.Path.ToString(),
                     ev.Data.StorageKey,
                     ev.ContentType,
                     ev.Data.Length,
                     ev.Data.Hash,
                     ev.Created,
                     ev.LastModified));
            await _db.SaveChangesAsync();
        }
Exemplo n.º 19
0
        public override IDocumentHistory ToModel()
        {
            var model = new DocumentHistory
            {
                Id               = Id,
                AuditId          = AuditId,
                DocumentTypeId   = (DocumentTypes)DocumentTypeId,
                Filename         = Filename,
                PrintedOn        = PrintedOn,
                PrintedBy        = PrintedBy,
                CreatedOn        = CreatedOn,
                CreatedById      = CreatedById,
                LastModifiedOn   = LastModifiedOn,
                LastModifiedById = LastModifiedById
            };

            return(model);
        }
Exemplo n.º 20
0
        private void AddToHistory(Document document)
        {
            var documentHistoryRecord = new DocumentHistory()
            {
                DocumentHistoryId    = 0,
                Document             = document,
                DocumentId           = document.DocumentId,
                ModifiedAt           = DateTime.UtcNow,
                ModifiedByUser       = _dbContext.UserInfo.FirstOrDefault(u => u.UserId == 1),
                ModifiedByUserId     = 1,
                DocumentPath         = document.DocumentPath,
                CaseNumber           = document.Case.CaseNumber,
                DocumentCategoryName = document.DocumentCategory.DocumentCategoryTitle,
                DocumentDescription  = document.Description,
                DocumentTitle        = document.Title
            };

            _dbContext.DocumentHistory.Add(documentHistoryRecord);
            _dbContext.SaveChanges();
        }
Exemplo n.º 21
0
        public static DocumentHistoryDto MapToDocumentHistoryDto(DocumentHistory documentHistory, IkarusContext _dbContext, int id)
        {
            var documentHistoryDto = new DocumentHistoryDto()
            {
                ModifiedAt           = documentHistory.ModifiedAt,
                DocumentTitle        = documentHistory.DocumentTitle,
                Author               = documentHistory.ModifiedByUser.FirstName + " " + documentHistory.ModifiedByUser.LastName,
                CaseNumber           = documentHistory.CaseNumber,
                DocumentCategoryName = documentHistory.DocumentCategoryName,
                DocumentDescription  = documentHistory.DocumentDescription,
                DocumentPath         = documentHistory.DocumentPath,
            };
            var extension = Path.GetExtension(documentHistoryDto.DocumentPath).Replace(".", "");

            if (extension != null)
            {
                documentHistoryDto.IconPath = _dbContext.FileType.FirstOrDefault(c => c.Extension == extension).IconPath;
            }

            return(documentHistoryDto);
        }
Exemplo n.º 22
0
        /// <summary>
        /// 追加修订历史信息
        /// </summary>
        /// <param name="userInfo">用户信息</param>
        /// <returns></returns>
        public bool AppendHistory(UserInfo userInfo)
        {
            if (userInfo == null)
            {
                return(false);
            }
            DocumentHistory history = new DocumentHistory();

            history.Author.Code         = userInfo.USER_ID;
            history.Author.Name         = userInfo.USER_NAME;
            history.Author.Organization = userInfo.DEPT_NAME;
            history.Timestamp           = DateTime.Now;
            if (this.textEditor1.DocumentInfo.Histories.Count <= 0)
            {
                history.Description = "创建";
            }
            else
            {
                history.Description = "修订";
            }
            this.textEditor1.DocumentInfo.Histories.Add(history);
            return(true);
        }
Exemplo n.º 23
0
        public bool ExternalRefreshFile(ExternalRefreshFileInput input)
        {
            var documentInfo = _context.DocumentInfos.FirstOrDefault(a => a.ExternalID == input.ID);

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

            DocumentHistory documentHistory = _context.DocumentHistories.FirstOrDefault(a => a.DocumentInfoId == documentInfo.Id && a.Version == documentInfo.CurrentVersion);

            documentInfo.Key    = Guid.NewGuid().ToString();
            documentHistory.Key = documentInfo.Key;
            if (!string.IsNullOrEmpty(input.NewID))
            {
                documentInfo.ExternalID = input.NewID;
            }

            documentService.StoreDocumentFile(documentInfo, input.FilePath);
            _context.SaveChanges();

            return(true);
        }
Exemplo n.º 24
0
        private static void runMemento()
        {
            var document = new Document();
            var history  = new DocumentHistory(document);

            document.Append("First revision");
            history.SnapShot();
            document.Bold();
            history.SnapShot();
            document.Italic();
            history.SnapShot();

            Console.WriteLine("Before restoring history.");
            Console.WriteLine(document.ToString());

            history.Restore(1);
            Console.WriteLine("Revision 2 restored.");
            Console.WriteLine(document.ToString());

            history.Restore(0);
            Console.WriteLine("Revision 1 restored.");
            Console.WriteLine(document.ToString());
        }
Exemplo n.º 25
0
        /*
         * This method is used to (GET) get the Document History for a given Document and for a given user from the SignNow Application
         */
        public DocumentHistory[] GetDocumentHistory(Oauth2Token token, string id)
        {
            DocumentHistory[] docshistory = new DocumentHistory[100];
            try
            {
                string requestBody = JsonConvert.SerializeObject(token, Formatting.Indented);
                var    client      = new RestClient();
                client.BaseUrl = config.GetApiBase();

                var request = new RestRequest("/document" + "/" + id + "/history", Method.GET)
                              .AddHeader("Authorization", "Bearer " + token.AccessToken);

                var    httpResponse = client.Execute(request);
                string json         = httpResponse.Content.ToString();

                if (httpResponse.StatusCode.Equals(System.Net.HttpStatusCode.OK))
                {
                    JArray jarr = JArray.Parse(json);
                    int    i    = 0;
                    foreach (JObject jobj in jarr)
                    {
                        docshistory[i] = JsonConvert.DeserializeObject <DocumentHistory>(jobj.ToString());
                        i++;
                    }
                }
                else if (httpResponse.StatusCode.Equals(System.Net.HttpStatusCode.BadRequest))
                {
                    docshistory[0] = JsonConvert.DeserializeObject <DocumentHistory>(json);;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("Exception: {0}", ex.Message));
                throw;
            }
            return(docshistory);
        }
Exemplo n.º 26
0
        private static void SerializeBuildingSpaces(IEnumerable <BH.oM.XML.Environment.DocumentBuilder> documents, string fileName, XMLSettings settings)
        {
            if (!System.IO.Directory.Exists(fileName))
            {
                System.IO.Directory.CreateDirectory(fileName);
            }

            foreach (BH.oM.XML.Environment.DocumentBuilder db in documents)
            {
                foreach (List <Panel> space in db.ElementsAsSpaces)
                {
                    if (space.IsExternal(db.ElementsAsSpaces))
                    {
                        Dictionary <String, object> spaceData = (space.Where(x => x.CustomData.ContainsKey("Space_Custom_Data")).FirstOrDefault() != null ? space.Where(x => x.CustomData.ContainsKey("Space_Custom_Data")).FirstOrDefault().CustomData["Space_Custom_Data"] as Dictionary <String, object> : new Dictionary <string, object>());
                        string spaceName = "";
                        if (spaceData.ContainsKey("SAM_SpaceName") && spaceData["SAM_SpaceName"] != null)
                        {
                            spaceName = spaceData["SAM_SpaceName"].ToString();
                        }
                        else
                        {
                            spaceName = "Space-" + Guid.NewGuid().ToString().Replace("-", "");
                        }

                        GBXML gbx = new GBXML();
                        SerializeCollection(space, db.Levels, db.UnassignedPanels, gbx, settings);

                        //Document History
                        DocumentHistory DocumentHistory = new DocumentHistory();
                        DocumentHistory.CreatedBy.Date = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss");
                        gbx.DocumentHistory            = DocumentHistory;

                        XMLWriter.Save(fileName + spaceName + ".xml", gbx);
                    }
                }
            }
        }
Exemplo n.º 27
0
        private bool AssertHistory(DocumentHistory history)
        {
            switch (history.Discriminator)
            {
            case DocumentHistoryDiscriminator.DocumentCreated:
            case DocumentHistoryDiscriminator.DocumentUpdated:
                return(!string.IsNullOrEmpty(history.StorageKey) &&
                       _blobKeysSet.Contains(history.StorageKey) &&
                       !string.IsNullOrEmpty(history.Path) &&
                       history.FileSize.HasValue &&
                       history.Created.HasValue &&
                       history.LastModified.HasValue);

            case DocumentHistoryDiscriminator.DocumentDeleted:
                return(string.IsNullOrEmpty(history.StorageKey) &&
                       !string.IsNullOrEmpty(history.Path) &&
                       !history.FileSize.HasValue &&
                       !history.Created.HasValue &&
                       !history.LastModified.HasValue);

            default:
                return(false);
            }
        }
Exemplo n.º 28
0
        public void ChangesCanBeAdded()
        {
            var h = new DocumentHistory();

            Assert.IsNull(h.LatestChange);

            h.Add(FakeChange("foo"));
            Assert.AreEqual(1, h.ToList().Count);
            Assert.AreEqual("foo", h.ToList()[0].Id);
            Assert.AreEqual("foo", h.LatestChange.Id);

            h.Add(FakeChange("bar"));
            Assert.AreEqual(2, h.ToList().Count);
            Assert.AreEqual("foo", h.ToList()[0].Id);
            Assert.AreEqual("bar", h.ToList()[1].Id);
            Assert.AreEqual("bar", h.LatestChange.Id);

            h.Add(FakeChange("baz"));
            Assert.AreEqual(3, h.ToList().Count);
            Assert.AreEqual("foo", h.ToList()[0].Id);
            Assert.AreEqual("bar", h.ToList()[1].Id);
            Assert.AreEqual("baz", h.ToList()[2].Id);
            Assert.AreEqual("baz", h.LatestChange.Id);
        }
Exemplo n.º 29
0
        public async Task ExecuteAsync()
        {
            var logger = services.GetService <ILogger <Program> >();

            logger.LogInformation("application started.");

            List <DocumentHistory>            allDocumentHistories;
            List <Document>                   allDocuments;
            List <Blob>                       allBlobs;
            ILookup <string, DocumentHistory> allDocumentHistoriesByStorageKey;
            ILookup <string, Document>        allDocumentsByStorageKey;
            ILookup <string, Blob>            allBlobsByStorageKey;
            HashSet <string>                  blobKeysSet;

            using (var context = CreateContext(configuration))
            {
                allDocumentHistories = (await context
                                        .DocumentHistories
                                        .ToListAsync()
                                        .ConfigureAwait(false));
                allDocuments = (await context
                                .Documents
                                .ToListAsync()
                                .ConfigureAwait(false));
                allBlobs = (await context
                            .Blobs
                            .ToListAsync()
                            .ConfigureAwait(false));

                allDocumentHistoriesByStorageKey = allDocumentHistories.ToLookup(d => d.StorageKey);
                allDocumentsByStorageKey         = allDocuments.ToLookup(d => d.StorageKey);
                allBlobsByStorageKey             = allBlobs.ToLookup(d => d.StorageKey);
            }

            var blobKeys = dataStore.ListAllKeys();

            blobKeysSet = new HashSet <string>();
            foreach (var key in blobKeys)
            {
                if (blobKeysSet.Add(key))
                {
                    if (allDocumentHistoriesByStorageKey[key].Any())
                    {
                        continue;
                    }
                    if (allDocumentsByStorageKey[key].Any())
                    {
                        continue;
                    }
                    if (allBlobsByStorageKey[key].Any())
                    {
                        continue;
                    }
                    logger.LogWarning("delete data for key: " + key);
                    await dataStore.DeleteAsync(key).ConfigureAwait(false);
                }
            }

            var documentContext             = new DocumentContext(allDocumentHistories, blobKeysSet, services);
            var maintainanceDocumentsByPath = documentContext.Documents.Where(d => !d.Deleted).ToLookup(d => d.Path);

            foreach (var dbDoc in allDocuments.Where(d => !string.IsNullOrEmpty(d.Path)).OrderBy(d => d.LastModified))
            {
                if (!maintainanceDocumentsByPath[dbDoc.Path].Any())
                {
                    logger.LogWarning("no history document found. path: " + dbDoc.Path);
                    await Task.Delay(300).ConfigureAwait(false);

                    using (var context = CreateContext(configuration))
                    {
                        var created = new DocumentHistory()
                        {
                            Id            = Guid.NewGuid(),
                            Discriminator = DocumentHistoryDiscriminator.DocumentCreated,
                            Timestamp     = DateTime.UtcNow,
                            DocumentId    = dbDoc.Id,
                            Path          = dbDoc.Path,
                            StorageKey    = dbDoc.StorageKey,
                            ContentType   = dbDoc.ContentType,
                            FileSize      = dbDoc.FileSize,
                            Hash          = dbDoc.Hash,
                            Created       = dbDoc.Created,
                            LastModified  = dbDoc.LastModified
                        };
                        context.DocumentHistories.Add(created);
                        var _blob = await context.Blobs.FindAsync(dbDoc.Path).ConfigureAwait(false);

                        if (_blob != null)
                        {
                            context.Blobs.Remove(_blob);
                        }
                        var docPath = new DocumentPath(dbDoc.Path);
                        await EnsureDirectoryExists(context, docPath.Parent).ConfigureAwait(false);

                        context.Blobs.Add(new Blob()
                        {
                            Path         = dbDoc.Path,
                            Name         = docPath.Name,
                            ParentPath   = docPath.Parent?.Value,
                            DocumentId   = dbDoc.Id,
                            StorageKey   = dbDoc.StorageKey,
                            ContentType  = dbDoc.ContentType,
                            FileSize     = dbDoc.FileSize,
                            Hash         = dbDoc.Hash,
                            Created      = dbDoc.Created,
                            LastModified = dbDoc.LastModified,
                        });
                        await context.SaveChangesAsync().ConfigureAwait(false);

                        documentContext.Apply(created);
                    }
                }
            }

            using (var context = CreateContext(configuration))
            {
                var historyIdsToRemove = documentContext.DeletableHistories.Select(h => h.Id).ToList();
                var rep = (historyIdsToRemove.Count / 1000) + 1;
                for (var i = 0; i < rep; i++)
                {
                    var historyIdsToRemoveSubset = historyIdsToRemove.Skip(i * 1000).Take(1000).ToList();
                    var historiesToRemove        = context.DocumentHistories.Where(h => historyIdsToRemoveSubset.Contains(h.Id));
                    context.DocumentHistories.RemoveRange(historiesToRemove);
                    await context.SaveChangesAsync().ConfigureAwait(false);
                }
            }

            foreach (var doc in documentContext.Documents)
            {
                var firstHistory = doc.Histories.First();
                if (firstHistory.Discriminator == DocumentHistoryDiscriminator.DocumentDeleted)
                {
                    logger.LogWarning("deleting invalid first history. path: " + firstHistory.Path);
                    using (var context = CreateContext(configuration))
                    {
                        var history = await context.DocumentHistories.FindAsync(firstHistory.Id).ConfigureAwait(false);

                        context.DocumentHistories.Remove(history);
                        await context.SaveChangesAsync().ConfigureAwait(false);
                    }
                    if (doc.Histories.Count == 1)
                    {
                        continue;
                    }
                }
                if (firstHistory.Discriminator == DocumentHistoryDiscriminator.DocumentUpdated)
                {
                    logger.LogWarning("fix first history discriminator to document created. path: " + firstHistory.Path);
                    using (var context = CreateContext(configuration))
                    {
                        var history = await context.DocumentHistories.FindAsync(firstHistory.Id).ConfigureAwait(false);

                        history.Discriminator = DocumentHistoryDiscriminator.DocumentCreated;
                        context.DocumentHistories.Update(history);
                        await context.SaveChangesAsync().ConfigureAwait(false);
                    }
                }

                if (doc.Histories.Count > 1)
                {
                    var lastHistory = doc.Histories.Last();
                    if (lastHistory.Discriminator == DocumentHistoryDiscriminator.DocumentCreated)
                    {
                        logger.LogWarning("fix last history discriminator to document updated. path: " + lastHistory.Path);
                        using (var context = CreateContext(configuration))
                        {
                            var history = await context.DocumentHistories.FindAsync(lastHistory.Id).ConfigureAwait(false);

                            history.Discriminator = DocumentHistoryDiscriminator.DocumentUpdated;
                            context.DocumentHistories.Update(history);
                            await context.SaveChangesAsync().ConfigureAwait(false);
                        }
                    }
                    foreach (var history in doc.Histories.Skip(1).Where(h => h != lastHistory))
                    {
                        if (history.Discriminator == DocumentHistoryDiscriminator.DocumentCreated)
                        {
                            logger.LogWarning("fix history discriminator to document updated. path: " + history.Path);
                            using (var context = CreateContext(configuration))
                            {
                                var _history = await context.DocumentHistories.FindAsync(lastHistory.Id).ConfigureAwait(false);

                                _history.Discriminator = DocumentHistoryDiscriminator.DocumentUpdated;
                                context.DocumentHistories.Update(_history);
                                await context.SaveChangesAsync().ConfigureAwait(false);
                            }
                        }
                    }
                }
            }

            var documentIds        = new HashSet <int>(allDocuments.Select(d => d.Id));
            var paths              = new HashSet <string>(allBlobs.Select(b => b.Path));
            var allDocumentsByPath = allDocuments.ToLookup(d => d.Path);
            var allBlobsByPath     = allBlobs.ToLookup(d => d.Path);

            foreach (var doc in documentContext.Documents)
            {
                if (doc.Deleted)
                {
                    var documentCandidates = allDocumentsByPath[null]
                                             .Where(d => d.Hash == doc.Hash && d.FileSize == doc.FileSize && d.Created == doc.Created && d.LastModified == doc.LastModified)
                                             .ToList();

                    if (documentCandidates.Count != 1)
                    {
                        logger.LogWarning("virtual document where real document not found or specified. path: " + doc.Path);
                        using (var context = CreateContext(configuration))
                        {
                            var historyIdsToRemove = doc.Histories.Select(h => h.Id).ToList();
                            var historiesToRemove  = context.DocumentHistories.Where(h => historyIdsToRemove.Contains(h.Id));
                            context.DocumentHistories.RemoveRange(historiesToRemove);
                            await context.SaveChangesAsync().ConfigureAwait(false);
                        }
                        continue;
                    }
                    var document = documentCandidates.First();
                    await FixHistoryIfNeededAsync(configuration, document, doc).ConfigureAwait(false);

                    documentIds.Remove(document.Id);
                }
                else
                {
                    var document = allDocumentsByPath[doc.Path].SingleOrDefault();
                    if (document == null)
                    {
                        logger.LogWarning("virtual document where real document not found or specified. path: " + doc.Path);
                        using (var context = CreateContext(configuration))
                        {
                            var historyIdsToRemove = doc.Histories.Select(h => h.Id).ToList();
                            var historiesToRemove  = context.DocumentHistories.Where(h => historyIdsToRemove.Contains(h.Id));
                            context.DocumentHistories.RemoveRange(historiesToRemove);
                            await context.SaveChangesAsync().ConfigureAwait(false);
                        }
                        continue;
                    }

                    if (document.Hash != doc.Hash ||
                        document.FileSize != doc.FileSize ||
                        document.Hash != doc.Hash ||
                        document.StorageKey != doc.StorageKey ||
                        document.ContentType != doc.ContentType ||
                        document.LastModified != doc.LastModified ||
                        document.Created != doc.Created)
                    {
                        logger.LogWarning("document props does not match history. creating path. path: " + doc.Path);
                        using (var context = CreateContext(configuration))
                        {
                            var created = new DocumentHistory()
                            {
                                Id            = Guid.NewGuid(),
                                Discriminator = DocumentHistoryDiscriminator.DocumentUpdated,
                                Timestamp     = DateTime.UtcNow,
                                DocumentId    = document.Id,
                                Path          = document.Path,
                                StorageKey    = document.StorageKey,
                                ContentType   = document.ContentType,
                                FileSize      = document.FileSize,
                                Hash          = document.Hash,
                                Created       = document.Created,
                                LastModified  = document.LastModified
                            };
                            context.DocumentHistories.Add(created);
                            await context.SaveChangesAsync().ConfigureAwait(false);

                            documentContext.Apply(created);
                        }
                    }

                    await FixHistoryIfNeededAsync(configuration, document, doc).ConfigureAwait(false);

                    var blob = allBlobsByPath[document.Path].SingleOrDefault();
                    if (blob == null ||
                        blob.DocumentId != document.Id ||
                        blob.FileSize != document.FileSize ||
                        blob.Hash != document.Hash ||
                        blob.StorageKey != document.StorageKey ||
                        blob.ContentType != document.ContentType ||
                        blob.LastModified != document.LastModified ||
                        blob.Created != document.Created)
                    {
                        using (var context = CreateContext(configuration))
                        {
                            var _blob = await context.Blobs.FindAsync(blob.Path).ConfigureAwait(false);

                            if (_blob != null)
                            {
                                context.Blobs.Remove(_blob);
                            }
                            var docPath = new DocumentPath(document.Path);
                            await EnsureDirectoryExists(context, docPath.Parent).ConfigureAwait(false);

                            context.Blobs.Add(new Blob()
                            {
                                Path         = document.Path,
                                Name         = docPath.Name,
                                ParentPath   = docPath.Parent?.Value,
                                DocumentId   = document.Id,
                                StorageKey   = document.StorageKey,
                                ContentType  = document.ContentType,
                                FileSize     = document.FileSize,
                                Hash         = document.Hash,
                                Created      = document.Created,
                                LastModified = document.LastModified,
                            });
                            await context.SaveChangesAsync().ConfigureAwait(false);
                        }
                    }

                    documentIds.Remove(document.Id);
                }
                doc.Histories
                .Select(h => h.StorageKey)
                .Where(h => !string.IsNullOrEmpty(h))
                .ToList()
                .ForEach(h => blobKeysSet.Remove(h));
            }

            foreach (var documentId in documentIds)
            {
                using (var context = CreateContext(configuration))
                {
                    var document = await context.Documents.FindAsync(documentId).ConfigureAwait(false);

                    if (document != null)
                    {
                        context.Documents.Remove(document);
                    }
                    var blobs = await context.Blobs.FirstOrDefaultAsync(b => b.DocumentId == documentId).ConfigureAwait(false);

                    if (blobs != null)
                    {
                        context.Blobs.RemoveRange(blobs);
                    }
                    if (document != null || blobs != null)
                    {
                        logger.LogWarning("delete document id: " + documentId + (document != null ? document.Path != null ? " path:" + document.Path : "" : ""));
                        await context.SaveChangesAsync().ConfigureAwait(false);
                    }
                }
            }

            foreach (var key in blobKeysSet)
            {
                logger.LogWarning("delete data for key: " + key);
                await dataStore.DeleteAsync(key).ConfigureAwait(false);
            }

            using (var context = CreateContext(configuration))
            {
                var emptyContainers = await context.BlobContainers
                                      .Include(b => b.Entries)
                                      .Where(b => !b.Entries.Any())
                                      .ToListAsync()
                                      .ConfigureAwait(false);

                context.BlobContainers.RemoveRange(emptyContainers);
                await context.SaveChangesAsync().ConfigureAwait(false);
            }
        }
Exemplo n.º 30
0
        private TangerineApp(string[] args)
        {
            ChangeTangerineSettingsFolderIfNeed();
            Orange.UserInterface.Instance = new OrangeInterface();
            Orange.UserInterface.Instance.Initialize();
            Widget.EnableViewCulling = false;
            WidgetInput.AcceptMouseBeyondWidgetByDefault = false;

            if (!UserPreferences.Initialize())
            {
                UserPreferences.Instance.Clear();
                UserPreferences.Instance.Add(new AppUserPreferences());
                UserPreferences.Instance.Add(new UI.SceneView.SceneUserPreferences());
                UserPreferences.Instance.Add(new UI.Timeline.TimelineUserPreferences());
                UserPreferences.Instance.Add(new UI.FilesystemView.FilesystemUserPreferences());
                UserPreferences.Instance.Add(new CoreUserPreferences());
            }
#if WIN
            TangerineSingleInstanceKeeper.Initialize(args);
            TangerineSingleInstanceKeeper.AnotherInstanceArgsRecieved += OpenDocumentsFromArgs;
            Application.Exited += () => {
                TangerineSingleInstanceKeeper.Instance.ReleaseInstance();
            };
#endif
            switch (AppUserPreferences.Instance.ColorThemeKind)
            {
            case ColorTheme.ColorThemeKind.Light:
                SetColorTheme(ColorTheme.CreateLightTheme(), Theme.ColorTheme.CreateLightTheme());
                break;

            case ColorTheme.ColorThemeKind.Dark:
                SetColorTheme(ColorTheme.CreateDarkTheme(), Theme.ColorTheme.CreateDarkTheme());
                break;

            case ColorTheme.ColorThemeKind.Custom: {
                bool       isDark = AppUserPreferences.Instance.ColorTheme.IsDark;
                ColorTheme theme  = null;
                var        flags  =
                    BindingFlags.Public |
                    BindingFlags.GetProperty |
                    BindingFlags.SetProperty |
                    BindingFlags.Instance;
                foreach (var category in typeof(ColorTheme).GetProperties(flags))
                {
                    var categoryValue = category.GetValue(AppUserPreferences.Instance.ColorTheme);
                    if (categoryValue == null)
                    {
                        if (theme == null)
                        {
                            theme = isDark ? ColorTheme.CreateDarkTheme() : ColorTheme.CreateLightTheme();
                        }
                        category.SetValue(AppUserPreferences.Instance.ColorTheme, category.GetValue(theme));
                        category.SetValue(theme, null);
                    }
                }
                SetColorTheme(AppUserPreferences.Instance.ColorTheme, AppUserPreferences.Instance.LimeColorTheme);
                break;
            }
            }
            Application.InvalidateWindows();

            LoadFont();

            DockManager.Initialize(new Vector2(1024, 768));
            DockManager.Instance.DocumentAreaDropFilesGesture.Recognized += new ScenesDropHandler {
                ShouldCreateContextMenu = false
            }.Handle;
            TangerineMenu.Create();
            var mainWidget = DockManager.Instance.MainWindowWidget;
            mainWidget.Window.AllowDropFiles = true;
            mainWidget.AddChangeWatcher(() => Project.Current, _ => {
                SetupMainWindowTitle(mainWidget);
                TangerineMenu.RebuildCreateImportedTypeMenu();
            });
            mainWidget.AddChangeWatcher(() => CoreUserPreferences.Instance.AnimationMode, _ => Document.Current?.ForceAnimationUpdate());
            mainWidget.AddChangeWatcher(() => Document.Current?.Container, _ => Document.Current?.ForceAnimationUpdate());
            Application.Exiting += () => Project.Current.Close();
            Application.Exited  += () => {
                AppUserPreferences.Instance.DockState             = DockManager.Instance.ExportState();
                SceneUserPreferences.Instance.VisualHintsRegistry = VisualHintsRegistry.Instance;
                Core.UserPreferences.Instance.Save();
                Orange.The.Workspace.Save();
            };

            var timelinePanel      = new Panel("Timeline");
            var inspectorPanel     = new Panel("Inspector");
            var searchPanel        = new Panel("Hierarchy");
            var animationsPanel    = new Panel("Animations");
            var filesystemPanel    = new Panel("Filesystem");
            var consolePanel       = new Panel("Console");
            var backupHistoryPanel = new Panel("Backups");
            var documentPanel      = new Panel(DockManager.DocumentAreaId, undockable: false);
            documentPanel.PanelWidget = documentPanel.ContentWidget;
            var visualHintsPanel     = new Panel("Visual Hints");
            var attachmentPanel      = new Panel("Model3D Attachment");
            var remoteScriptingPanel = new Panel("Remote Scripting");
            var dockManager          = DockManager.Instance;
            new UI.Console(consolePanel);
            var root      = dockManager.Model.WindowPlacements.First();
            var placement = new LinearPlacement(LinearPlacementDirection.Horizontal);
            dockManager.AddPanel(timelinePanel, root, DockSite.Top, 0.3f);
            dockManager.DockPlacementTo(placement, root, DockSite.Bottom, 0.6f);
            dockManager.AppendPanelTo(documentPanel, placement, 0.5f);
            var commandHandlerList = CommandHandlerList.Global;
            var commandsDictionary = new Dictionary <string, Command> {
                { animationsPanel.Id, new Command(animationsPanel.Title) },
                { timelinePanel.Id, new Command(timelinePanel.Title) },
                { inspectorPanel.Id, new Command(inspectorPanel.Title) },
                { searchPanel.Id, new Command(searchPanel.Title) },
                { filesystemPanel.Id, new Command(filesystemPanel.Title) },
                { consolePanel.Id, new Command(consolePanel.Title) },
                { backupHistoryPanel.Id, new Command(backupHistoryPanel.Title) },
                { visualHintsPanel.Id, new Command(visualHintsPanel.Title) },
                { attachmentPanel.Id, new Command(attachmentPanel.Title) },
                { remoteScriptingPanel.Id, new Command(remoteScriptingPanel.Title) },
            };
            foreach (var pair in commandsDictionary)
            {
                commandHandlerList.Connect(pair.Value, new PanelCommandHandler(pair.Key));
                TangerineMenu.PanelsMenu.Add(pair.Value);
            }
            dockManager.AddPanel(inspectorPanel, placement, DockSite.Left);
            var filesystemPlacement = dockManager.AddPanel(filesystemPanel, placement, DockSite.Right);
            dockManager.AddPanel(searchPanel, filesystemPlacement, DockSite.Fill);
            dockManager.AddPanel(animationsPanel, filesystemPlacement, DockSite.Fill);
            dockManager.AddPanel(backupHistoryPanel, filesystemPlacement, DockSite.Fill);
            dockManager.AddPanel(consolePanel, filesystemPlacement, DockSite.Bottom, 0.3f);
            dockManager.AddPanel(visualHintsPanel, placement, DockSite.Right, 0.3f).Hidden     = true;
            dockManager.AddPanel(attachmentPanel, placement, DockSite.Bottom, 0.3f).Hidden     = true;
            dockManager.AddPanel(remoteScriptingPanel, placement, DockSite.Right, 0.3f).Hidden = true;
            DockManagerInitialState = dockManager.ExportState();
            var documentViewContainer = InitializeDocumentArea(dockManager);
            documentPanel.ContentWidget.Nodes.Add(dockManager.DocumentArea);
            dockManager.ImportState(AppUserPreferences.Instance.DockState);
            Document.CloseConfirmation += doc => {
                var alert = new AlertDialog($"Save the changes to document '{doc.Path}' before closing?", "Yes", "No", "Cancel");
                switch (alert.Show())
                {
                case 0: return(Document.CloseAction.SaveChanges);

                case 1: return(Document.CloseAction.DiscardChanges);

                case -1:
                default: return(Document.CloseAction.Cancel);
                }
            };
            mainWidget.Tasks.Add(HandleMissingDocumentsTask);
            Project.HandleMissingDocuments += missingDocuments => {
                foreach (var d in missingDocuments)
                {
                    missingDocumentsList.Add(d);
                }
            };
            Project.DocumentReloadConfirmation += doc => {
                if (doc.IsModified)
                {
                    var modifiedAlert = new AlertDialog($"{doc.Path}\n\nThis file has been modified by another program and has unsaved changes.\nDo you want to reload it from disk? ", "Yes", "No");
                    var res           = modifiedAlert.Show();
                    if (res == 1 || res == -1)
                    {
                        doc.History.ExternalModification();
                        return(false);
                    }
                    return(true);
                }
                if (CoreUserPreferences.Instance.ReloadModifiedFiles)
                {
                    return(true);
                }
                var alert = new AlertDialog($"{doc.Path}\n\nThis file has been modified by another program.\nDo you want to reload it from disk? ", "Yes, always", "Yes", "No");
                var r     = alert.Show();
                if (r == 0)
                {
                    CoreUserPreferences.Instance.ReloadModifiedFiles = true;
                    return(true);
                }
                if (r == 2)
                {
                    doc.History.ExternalModification();
                    return(false);
                }
                return(true);
            };

            Project.TempFileLoadConfirmation += path => {
                var alert = new AlertDialog($"Do you want to load autosaved version of '{path}'?", "Yes", "No");
                return(alert.Show() == 0);
            };

            Project.OpenFileOutsideProjectAttempt += (string filePath) => {
                var projectFilePath = SearhForCitproj(filePath);
                if (projectFilePath != null && Project.Current.CitprojPath != projectFilePath)
                {
                    var alert = new AlertDialog($"You're trying to open a document outside the project directory. Change the current project to '{Path.GetFileName(projectFilePath)}'?", "Yes", "No");
                    if (alert.Show() == 0)
                    {
                        if (FileOpenProject.Execute(projectFilePath))
                        {
                            Project.Current.OpenDocument(filePath, true);
                        }
                        return;
                    }
                }
                else if (projectFilePath == null)
                {
                    AlertDialog.Show("Can't open a document outside the project directory");
                }
            };
            Project.Tasks = dockManager.MainWindowWidget.Tasks;
            Project.Tasks.Add(new AutosaveProcessor(() => AppUserPreferences.Instance.AutosaveDelay));
            BackupManager.Instance.Activate(Project.Tasks);
            Document.NodeDecorators.AddFor <Spline>(n => n.CompoundPostPresenter.Add(new UI.SceneView.SplinePresenter()));
            Document.NodeDecorators.AddFor <Viewport3D>(n => n.CompoundPostPresenter.Add(new UI.SceneView.Spline3DPresenter()));
            Document.NodeDecorators.AddFor <Viewport3D>(n => n.CompoundPostPresenter.Add(new UI.SceneView.Animation3DPathPresenter()));
            Document.NodeDecorators.AddFor <Widget>(n => {
                if (n.AsWidget.SkinningWeights == null)
                {
                    n.AsWidget.SkinningWeights = new SkinningWeights();
                }
            });
            Document.NodeDecorators.AddFor <PointObject>(n => {
                if ((n as PointObject).SkinningWeights == null)
                {
                    (n as PointObject).SkinningWeights = new SkinningWeights();
                }
            });
            Animation.EasingEnabledChecker = (animation) => {
                var doc = Document.Current;
                return(doc == null || doc.PreviewScene || animation != doc.Animation);
            };
            if (SceneUserPreferences.Instance.VisualHintsRegistry != null)
            {
                VisualHintsRegistry.Instance = SceneUserPreferences.Instance.VisualHintsRegistry;
            }
            VisualHintsRegistry.Instance.RegisterDefaultHints();

            Document.NodeDecorators.AddFor <Node>(n => n.SetTangerineFlag(TangerineFlags.SceneNode, true));
            dockManager.UnhandledExceptionOccurred += e => {
                AlertDialog.Show(e.Message + "\n" + e.StackTrace);
                var doc = Document.Current;
                if (doc != null)
                {
                    while (doc.History.IsTransactionActive)
                    {
                        doc.History.EndTransaction();
                    }
                    var closeConfirmation = Document.CloseConfirmation;
                    try {
                        Document.CloseConfirmation = d => {
                            var alert = new AlertDialog($"Save the changes to document '{d.Path}' before closing?", "Yes", "No");
                            switch (alert.Show())
                            {
                            case 0: return(Document.CloseAction.SaveChanges);

                            default: return(Document.CloseAction.DiscardChanges);
                            }
                        };
                        var fullPath = doc.FullPath;

                        if (!File.Exists(fullPath))
                        {
                            doc.Save();
                        }
                        var path = doc.Path;
                        Project.Current.CloseDocument(doc);
                        Project.Current.OpenDocument(path);
                    } finally {
                        Document.CloseConfirmation = closeConfirmation;
                    }
                }
            };

            Document.NodeDecorators.AddFor <ParticleEmitter>(n => n.CompoundPostPresenter.Add(new UI.SceneView.ParticleEmitterPresenter()));
            DocumentHistory.AddOperationProcessorTypes(new[] {
                typeof(Core.Operations.TimelineHorizontalShift.Processor),
                typeof(Core.Operations.TimelineColumnRemove.Processor),
                typeof(Core.Operations.RemoveKeyframeRange.Processor),
                typeof(Core.Operations.SelectRow.Processor),
                typeof(Core.Operations.RenameAnimationProcessor),
                typeof(Core.Operations.SetProperty.Processor),
                typeof(Core.Operations.SetIndexedProperty.Processor),
                typeof(Core.Operations.RemoveKeyframe.Processor),
                typeof(Core.Operations.SetKeyframe.Processor),
                typeof(Core.Operations.InsertFolderItem.Processor),
                typeof(Core.Operations.AddIntoCollection <,> .Processor),
                typeof(Core.Operations.RemoveFromCollection <,> .Processor),
                typeof(Core.Operations.InsertIntoList.Processor),
                typeof(Core.Operations.RemoveFromList.Processor),
                typeof(Core.Operations.InsertIntoList <,> .Processor),
                typeof(Core.Operations.RemoveFromList <,> .Processor),
                typeof(Core.Operations.UnlinkFolderItem.Processor),
                typeof(Core.Operations.MoveNodes.Processor),
                typeof(Core.Operations.SetMarker.Processor),
                typeof(Core.Operations.DeleteMarker.Processor),
                typeof(Core.Operations.SetComponent.Processor),
                typeof(Core.Operations.DeleteComponent.Processor),
                typeof(Core.Operations.DistortionMeshProcessor),
                typeof(Core.Operations.SyncFolderDescriptorsProcessor),
                typeof(UI.SceneView.ResolutionPreviewOperation.Processor),
                typeof(UI.Timeline.Operations.SelectGridSpan.Processor),
                typeof(UI.Timeline.Operations.DeselectGridSpan.Processor),
                typeof(UI.Timeline.Operations.ClearGridSelection.Processor),
                typeof(UI.Timeline.Operations.ShiftGridSelection.Processor),
                typeof(UI.Timeline.Operations.SetCurrentColumn.Processor),
                typeof(UI.Timeline.Operations.SelectCurveKey.Processor),
                typeof(TriggersValidatorOnSetProperty),
                typeof(TriggersValidatorOnSetKeyframe),
                typeof(UpdateNodesAndApplyAnimatorsProcessor),
                typeof(RowsSynchronizer),
                typeof(Core.Operations.ReplaceContents.Processor),
                typeof(Core.Operations.DeleteRuler.Processor),
                typeof(Core.Operations.CreateRuler.Processor),
            });
            DocumentHistory.AddOperationProcessorTypes(UI.Timeline.Timeline.GetOperationProcessorTypes());

            RegisterCommands();
            InitializeHotkeys();

            AppUserPreferences.Instance.ToolbarModel.RefreshAfterLoad();
            Toolbar = new ToolbarView(dockManager.ToolbarArea, AppUserPreferences.Instance.ToolbarModel);
            RefreshCreateNodeCommands();
            Document.AttachingViews += doc => {
                if (doc.Views.Count == 0)
                {
                    doc.Views.AddRange(new IDocumentView[] {
                        new UI.Inspector.Inspector(inspectorPanel.ContentWidget),
                        new UI.Timeline.Timeline(timelinePanel),
                        new UI.SceneView.SceneView(documentViewContainer),
                        new Panels.HierarchyPanel(searchPanel.ContentWidget),
                        new Panels.BackupHistoryPanel(backupHistoryPanel.ContentWidget),
                        new Panels.AnimationsPanel(animationsPanel.ContentWidget),
                        // Use VisualHintsPanel sigleton because we need preserve its state between documents.
                        VisualHintsPanel.Instance ?? VisualHintsPanel.Initialize(visualHintsPanel),
                        new AttachmentPanel(attachmentPanel),
                    });
                    UI.SceneView.SceneView.ShowNodeDecorationsPanelButton.Clicked = () => dockManager.TogglePanel(visualHintsPanel);
                }
            };
            var proj = AppUserPreferences.Instance.CurrentProject;
            if (proj != null)
            {
                try {
                    new Project(proj).Open();
                } catch {
                    AlertDialog.Show($"Cannot open project '{proj}'. It may be deleted or be otherwise unavailable.");
                }
            }
            OpenDocumentsFromArgs(args);
            WidgetContext.Current.Root.AddChangeWatcher(() => Project.Current, project => TangerineMenu.OnProjectChanged(project));

            WidgetContext.Current.Root.AddChangeWatcher(() => ProjectUserPreferences.Instance.RecentDocuments.Count == 0 ?
                                                        null : ProjectUserPreferences.Instance.RecentDocuments[0], document => TangerineMenu.RebuildRecentDocumentsMenu());

            WidgetContext.Current.Root.AddChangeWatcher(() => AppUserPreferences.Instance.RecentProjects.Count == 0 ?
                                                        null : AppUserPreferences.Instance.RecentProjects[0], document => TangerineMenu.RebuildRecentProjectsMenu());

            new UI.FilesystemView.FilesystemPane(filesystemPanel);
            new UI.RemoteScripting.RemoteScriptingPane(remoteScriptingPanel);
            RegisterGlobalCommands();

            Documentation.Init();
            DocumentationComponent.Clicked = page => Documentation.ShowHelp(page);
        }