Esempio n. 1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="initialData">Represents the current contents of the file. Reference is not held. A copy is made.</param>
 /// <param name="path"></param>
 /// <param name="data"></param>
 /// <param name="serializer"></param>
 private LocalizationFile(Id <FileInProject> id, MemoryStream initialData, DocumentPath path, LocalizerData data, ISerializer <LocalizerData> serializer, UpToDateFile.BackEnd backend)
 {
     Id        = id;
     m_backend = backend;
     m_file    = new SaveableFileExternalChangedSource(initialData, path.FileInfo, s => { serializer.Write(m_data, s); }, Changed, Saved, backend);
     m_data    = data;
 }
Esempio n. 2
0
 public static void TestEverything()
 {
     using (UpToDateFile.BackEnd backEnd = new UpToDateFile.BackEnd())
     {
         using (MemoryStream m = new MemoryStream())
         {
             using (SaveableFileUndoable file = new SaveableFileUndoable(m, new FileInfo("ignore.txt"), a => { }, backEnd))
             {
                 Assert.False(file.Changed);
                 file.Change(new GenericUndoAction(() => { }, () => { }, ""));
                 Assert.True(file.Changed);
                 file.UndoQueue.Undo();
                 Assert.False(file.Changed);
                 file.UndoQueue.Redo();
                 Assert.True(file.Changed);
                 file.Save();
                 Assert.False(file.Changed);
                 file.Change(new GenericUndoAction(() => { }, () => { }, ""));
                 Assert.True(file.Changed);
                 file.UndoQueue.Undo();
                 Assert.False(file.Changed);
                 file.UndoQueue.Undo();
                 Assert.True(file.Changed);
                 file.UndoQueue.Redo();
                 Assert.False(file.Changed);
             }
         }
     }
 }
Esempio n. 3
0
        public static void StressTest()
        {
            MemoryStream data = new MemoryStream();

            using (StreamWriter w = new StreamWriter(data, Encoding.UTF8, 1024, true))
            {
                w.WriteLine("asgfladhfldsalkhdsfdsfasf");
            }
            data.Position = 0;

            Action <Stream> saveto = s =>
            {
                data.Position = 0;
                data.CopyTo(s);
                data.Position = 0;
            };

            using (FileStream file = new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.Write))
            {
                saveto(file);
            }

            using (UpToDateFile.BackEnd backEnd = new UpToDateFile.BackEnd())
            {
                using (UpToDateFile f = new UpToDateFile(data, new FileInfo("test.txt"), saveto, backEnd))
                {
                    f.FileChanged += () =>
                    {
                        Assert.Fail("FileChange should not have triggered");
                    };

                    try
                    {
                        for (int i = 0; i < 200; i++)
                        {
                            f.Save();
                            f.Save();

                            data.Position = 10;
                            data.WriteByte((byte)(i % 256));

                            f.Save();
                            Console.WriteLine(i);
                        }
                    }
                    catch (MyFileLoadException)
                    {
                        Assert.Fail();
                    }
                }
            }
        }
Esempio n. 4
0
        public ProjectMenuController(SharedContext context, ConfigParameterList <string> config, INodeFactory conversationNodeFactory, INodeFactory domainNodeFactory, Action <Action> executeInGuiThread, PluginsConfig pluginsConfig, Func <IAudioProviderCustomization> audioCustomization, UpToDateFile.BackEnd backend)
        {
            m_context                 = context;
            m_executeInGuiThread      = executeInGuiThread;
            m_conversationNodeFactory = conversationNodeFactory;
            m_domainNodeFactory       = domainNodeFactory;
            m_config                = config;
            m_pluginsConfig         = pluginsConfig;
            m_audioCustomization    = audioCustomization;
            m_backend               = backend;
            m_context.ProjectMoved += WeakCallback <Changed <FileInfo> > .Handler(this, (me, a) => me.ProjectMoved(a.From, a.To));

            m_context.CurrentProject.Changed.Register(this, (a, b) => UpdateRecentlyOpenedConfig());

            var file = m_config.Value.FirstOrDefault(a => true, a => a, "");

            if (File.Exists(file))
            {
                OpenProject(file);
            }
        }
Esempio n. 5
0
        public static void Test()
        {
            IEnumerable <GraphAndUI <NodeUIData> > nodes = Enumerable.Empty <GraphAndUI <NodeUIData> >();
            List <NodeGroup>               groups        = new List <NodeGroup>();
            MemoryStream                   rawData       = new MemoryStream();
            DocumentPath                   file          = DocumentPath.FromPath("DeleteMe.txt", new DirectoryInfo("."));
            ISerializer <TData>            serializer    = null;
            ReadOnlyCollection <LoadError> errors        = new ReadOnlyCollection <LoadError>(new List <LoadError>());
            INodeFactory                   nodeFactory   = null;
            GenerateAudio                  generateAudio = null;
            var source = new DynamicEnumParameter.Source();
            Func <IDynamicEnumParameter, object, DynamicEnumParameter.Source> getDocumentSource = (a, b) => source;
            IAudioLibrary audioProvider = new DummyAudioLibrary();

            List <List <ConversationNode> > states = new List <List <ConversationNode <INodeGui> > >
            {
                new List <ConversationNode>()
            };

            Random r = new Random(0);

            UpToDateFile.BackEnd backend = new UpToDateFile.BackEnd();
            var id = Id <FileInProject> .Parse("6a1bd06a-0028-4099-a375-475f1a5320db");

            using (ConversationFile conversationFile = new ConversationFile(id, nodes, groups, rawData, file, serializer, errors, nodeFactory, generateAudio, getDocumentSource, audioProvider, backend))
            {
                for (int i = 0; i < 10; i++)
                {
                    var node  = MakeNode();
                    var state = states[i].ToList();
                    state.Add(node);
                    conversationFile.Add(new[] { node }, Enumerable.Empty <NodeGroup>(), null);
                    CheckState(conversationFile, state);
                    states.Add(state);
                }

                Action <ConversationNode> CheckNode = node =>
                {
                    var connector = conversationFile.UIInfo(node.Data.Connectors.First(), false);
                    Assert.That(connector.Area.Value, Is.EqualTo(TopPosition(node.Renderer.Area)));
                };

                for (int n = 0; n < 10000; n++)
                {
                    var node = states.Last().Last();
                    node.Renderer.MoveTo(new PointF((float)r.NextDouble() * 1000, (float)r.NextDouble() * 1000));
                    CheckNode(node);
                }

                for (int i = 9; i >= 0; i--)
                {
                    conversationFile.UndoableFile.UndoQueue.Undo();
                    var state = states[i];
                    CheckState(conversationFile, state);
                }
                for (int i = 1; i <= 10; i++)
                {
                    conversationFile.UndoableFile.UndoQueue.Redo();
                    var state = states[i];
                    CheckState(conversationFile, state);
                }
            }
            Assert.Inconclusive();
        }
Esempio n. 6
0
 internal static ILocalizationFile Load(DocumentPath path, Id <FileInProject> id, ISerializer <LocalizerData> serializer, UpToDateFile.BackEnd backend)
 {
     if (path.Exists)
     {
         try
         {
             LocalizerData data;
             using (FileStream file = Util.LoadFileStream(path.AbsolutePath, FileMode.Open, FileAccess.Read))
             {
                 using (MemoryStream m = new MemoryStream((int)file.Length))
                 {
                     file.CopyTo(m);
                     m.Position = 0;
                     XmlLocalization.Deserializer d = new XmlLocalization.Deserializer();
                     data       = d.Read(m);
                     m.Position = 0;
                     LocalizationFile result = new LocalizationFile(id, m, path, data, serializer, backend);
                     return(result);
                 }
             }
         }
         catch (MyFileLoadException e)
         {
             Console.Out.WriteLine(e.Message);
             Console.Out.WriteLine(e.StackTrace);
             Console.Out.WriteLine(e.InnerException.Message);
             Console.Out.WriteLine(e.InnerException.StackTrace);
             MessageBox.Show("File: " + path.AbsolutePath + " could not be accessed");
             return(new MissingLocalizationFile(id, path));
         }
     }
     else
     {
         return(new MissingLocalizationFile(id, path));
     }
 }
Esempio n. 7
0
        internal static LocalizationFile MakeNew(DirectoryInfo directory, Func <string, Id <FileInProject>, ISerializer <LocalizerData> > serializer, Func <FileInfo, bool> pathOk, UpToDateFile.BackEnd backend, DirectoryInfo origin)
        {
            //Create a stream under an available filename
            FileInfo path = null;

            for (int i = 0; path == null; i++)
            {
                path = new FileInfo(directory.FullName + Path.DirectorySeparatorChar + "New Localization " + i + ".loc");
                if (!pathOk(path))
                {
                    path = null;
                }
            }

            LocalizerData data = new LocalizerData();

            using (var file = Util.LoadFileStream(path, FileMode.CreateNew, FileAccess.Write))
            {
            }
            using (var mem = new MemoryStream())
            {
                var id = Id <FileInProject> .New();

                LocalizationFile result = new LocalizationFile(id, mem, DocumentPath.FromPath(path, origin), data, serializer(path.FullName, id), backend); //Make a new localization file for an existing project
                result.File.Writable.Save();
                return(result);
            }
        }
Esempio n. 8
0
        /// <param name="context">Context used when localizing to reference current localization</param>
        /// <param name="usedGuids"></param>
        /// <param name="shouldClean"></param>
        /// <param name="shouldExpand"></param>
        /// <param name="pathOk">Path is an acceptable filename for a new localization file</param>
        /// <param name="fileLocationOk">Path is an acceptable location from which to import an existing localization file</param>
        public LocalizationEngine(GetFilePath getFilePath, IEnumerable <Project.TData.LocalizerSetData> sets, ILocalizationContext context, Func <HashSet <Id <LocalizedText> > > usedGuids, Func <string, bool> shouldClean, Func <FileInfo, bool> pathOk, Func <string, bool> fileLocationOk, UpToDateFile.BackEnd backEnd, DirectoryInfo origin)
        {
            m_context   = context;
            m_usedGuids = usedGuids;
            ShouldClean = shouldClean;

            Func <IEnumerable <Tuple <Id <FileInProject>, DocumentPath> >, IEnumerable <ILocalizationFile> > load = files =>
            {
                //return files.Select(file => LocalizationFile.Load(file, MakeSerializer(file.Name), backend));
                var filesAndSerializer = files.Select(f => new { Id = f.Item1, Path = f.Item2, Serializer = MakeSerializer(f.Item2.AbsolutePath, f.Item1) }).ToList();
                return(ParallelEnumerable.Select(filesAndSerializer.AsParallel(), fs => LocalizationFile.Load(fs.Path, fs.Id, fs.Serializer, backEnd)));
            };
            Func <DirectoryInfo, LocalizationFile> makeEmpty = path => LocalizationFile.MakeNew(path, MakeSerializer, pathOk, backEnd, origin);

            m_localizers       = new ProjectElementList <ILocalizationFile>(getFilePath, fileLocationOk.Bottleneck(), load, makeEmpty);
            m_localizationSets = sets.ToHashSet();
        }
Esempio n. 9
0
        public static ConversationFile CreateEmpty(DirectoryInfo directory, Project project, INodeFactory nodeFactory,
                                                   GenerateAudio generateAudio, Func <IDynamicEnumParameter, object, DynamicEnumParameter.Source> getDocumentSource, IAudioLibrary audioProvider, UpToDateFile.BackEnd backEnd, DirectoryInfo origin)
        {
            var file = GetAvailableConversationPath(directory, project.Elements);

            var nodes  = Enumerable.Empty <GraphAndUI <NodeUIData> >();
            var groups = new List <NodeGroup>();

            //Fill the stream with the essential content
            using (MemoryStream m = new MemoryStream())
            {
                using (FileStream stream = Util.LoadFileStream(file, FileMode.CreateNew, FileAccess.Write))
                {
                    project.ConversationSerializer.Write(SerializationUtils.MakeConversationData(nodes, new ConversationEditorData(groups)), m);
                    m.Position = 0;
                    m.CopyTo(stream);
                }

                var result = new ConversationFile(Id <FileInProject> .New(), nodes, groups, m, DocumentPath.FromPath(file, origin), project.ConversationSerializer, new ReadOnlyCollection <LoadError>(new LoadError[0]), nodeFactory, generateAudio, getDocumentSource, audioProvider, backEnd);
                result.m_file.Save(); //Make sure the file starts life as a valid xml document
                return(result);
            }
        }
Esempio n. 10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="groups"></param>
        /// <param name="rawData">Represents the current contents of the file. Reference is not held. A copy is made.</param>
        /// <param name="file"></param>
        /// <param name="serializer"></param>
        /// <param name="errors"></param>
        /// <param name="nodeFactory"></param>
        /// <param name="generateAudio"></param>
        /// <param name="getDocumentSource"></param>
        /// <param name="audioProvider"></param>
        public ConversationFile(Id <FileInProject> id, IEnumerable <GraphAndUI <NodeUIData> > nodes, IEnumerable <NodeGroup> groups, MemoryStream rawData, DocumentPath file, ISerializer <TData> serializer,
                                ReadOnlyCollection <LoadError> errors, INodeFactory nodeFactory, GenerateAudio generateAudio,
                                Func <IDynamicEnumParameter, object, DynamicEnumParameter.Source> getDocumentSource, IAudioLibrary audioProvider, UpToDateFile.BackEnd backEnd)
            : base(nodes, groups, errors, nodeFactory, generateAudio, getDocumentSource, audioProvider)
        {
            Id           = id;
            m_file       = new SaveableFileUndoable(rawData, file.FileInfo, SaveTo, backEnd);
            m_serializer = serializer;

            foreach (var node in m_nodes)
            {
                //TODO: AUDIO: Why are we automatically decorrupting specifically audio parameters?
                var audios = node.Data.Parameters.OfType <IAudioParameter>();
                foreach (var aud in audios)
                {
                    if (aud.Corrupted)
                    {
                        var val = generateAudio(this);
                        aud.SetValueAction(val).Value.Redo();
                        m_file.ChangeNoUndo();
                        audioProvider.UpdateUsage(val);
                    }
                }
                node.UpdateRendererCorruption();
            }
        }
Esempio n. 11
0
        public static IConversationFile Load(Id <FileInProject> file, DocumentPath path, INodeFactory nodeFactory, ISerializerDeserializer <TData> serializer, GenerateAudio generateAudio,
                                             Func <IDynamicEnumParameter, object, DynamicEnumParameter.Source> getDocumentSource, IAudioLibrary audioProvider, UpToDateFile.BackEnd backEnd)
        {
            try
            {
                using (var stream = Util.LoadFileStream(path.FileInfo, FileMode.Open, FileAccess.Read))
                {
                    using (MemoryStream m = new MemoryStream((int)stream.Length))
                    {
                        stream.CopyTo(m);
                        stream.Dispose();
                        m.Position = 0;
                        TData data = serializer.Read(m);
                        return(new ConversationFile(file, data.Nodes.ToList(), data.EditorData.Groups.ToList(), m, path, serializer, data.Errors, nodeFactory, generateAudio, getDocumentSource, audioProvider, backEnd));
                    }
                }
            }
            catch (MyFileLoadException e)
            {
                Console.Out.WriteLine(e.Message);
                Console.Out.WriteLine(e.StackTrace);
                Console.Out.WriteLine(e.InnerException.Message);
                Console.Out.WriteLine(e.InnerException.StackTrace);

                MessageBox.Show("File: " + path.AbsolutePath + " could not be accessed");
                return(new MissingConversationFile(file, path));
            }
            catch (DeserializerVersionMismatchException e)
            {
                MessageBox.Show("File: " + path.AbsolutePath + " could not be processed. " + e.Message);
                return(new MissingConversationFile(file, path));
            }
        }
Esempio n. 12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <param name="data"></param>
        /// <param name="conversationNodeFactory"></param>
        /// <param name="domainNodeFactory"></param>
        /// <param name="initialContent">Represents the current contents of the file. Reference is not held. A copy is made.</param>
        /// <param name="projectFile"></param>
        /// <param name="serializer"></param>
        /// <param name="conversationSerializer"></param>
        /// <param name="conversationSerializerDeserializerFactory"></param>
        /// <param name="domainSerializer"></param>
        /// <param name="pluginsConfig"></param>
        /// <param name="audioCustomization"></param>
        public Project(ILocalizationContext context, TData data, INodeFactory conversationNodeFactory, INodeFactory domainNodeFactory, MemoryStream initialData, FileInfo projectFile, ISerializer <TData> serializer, ISerializer <TConversationData> conversationSerializer, ConversationSerializerDeserializerFactory conversationSerializerDeserializerFactory, ISerializer <TDomainData> domainSerializer, PluginsConfig pluginsConfig, Func <IAudioProviderCustomization> audioCustomization, UpToDateFile.BackEnd backend)
        {
            AssertUniqueFileIds(data);
            AssertUniqueLocalizationSetNames(data);
            AssertUniqueFilePaths(data);

            m_upToDateFileBackend = backend;
            Action <Stream> saveTo = stream =>
            {
                Write(GetFilePath, Conversations.Select(x => (x.Id)), LocalizationFiles.Select(x => (x.Id)),
                      DomainFiles.Select(x => (x.Id)), AudioFiles.Select(x => (x.Id)), Localizer.LocalizationSets, stream, m_serializer);
            };

            m_file = new SaveableFileNotUndoable(initialData, projectFile, saveTo, backend);
            ConversationNodeFactory         = conversationNodeFactory;
            DomainNodeFactory               = domainNodeFactory;
            m_serializer                    = serializer;
            ConversationSerializer          = conversationSerializer;
            m_conversationSerializerFactory = conversationSerializerDeserializerFactory;
            m_domainSerializer              = domainSerializer;

            m_filePaths = data.Conversations.Concat(data.Localizations).Concat(data.Domains).Concat(data.Audios).ToDictionary(f => f.Id, f => f.Path);

            IEnumerable <Id <FileInProject> > conversationIds = data.Conversations.Select(f => f.Id);
            IEnumerable <Id <FileInProject> > localizerIds    = data.Localizations.Select(f => f.Id);
            IEnumerable <Id <FileInProject> > domainIds       = data.Domains.Select(f => f.Id);
            IEnumerable <Id <FileInProject> > audioIds        = data.Audios.Select(f => f.Id);

            m_audioProvider = new AudioProvider(new FileInfo(projectFile.FullName), GetFilePath, s => CheckFolder(s, Origin), this, audioCustomization());
            using (m_audioProvider.SuppressUpdates())
            {
                {
                    m_audioProvider.AudioFiles.Load(audioIds);
                }

                {
                    //Dictionary<IDynamicEnumParameter, DynamicEnumParameter.Source> domainEnumSource = new Dictionary<IDynamicEnumParameter, DynamicEnumParameter.Source>();
                    Func <IDynamicEnumParameter, object, DynamicEnumParameter.Source> getDomainEnumSource = (k, o) =>
                    {
                        return(null); //Nothing should need a source (but the system will ask anyway)
                                      //if (!domainEnumSource.ContainsKey(k))
                                      //domainEnumSource[k] = new DynamicEnumParameter.Source();
                                      //return domainEnumSource[k];
                    };

                    m_domainDataSource = new DomainDomain(pluginsConfig);
                    Func <IEnumerable <Tuple <Id <FileInProject>, DocumentPath> >, IEnumerable <IDomainFile> > loader = paths =>
                    {
                        var result = DomainFile.Load(paths, m_domainDataSource, DomainSerializerDeserializer.Make, DomainNodeFactory, () => DomainUsage, getDomainEnumSource, backend).Evaluate();
                        result.ForAll(a => a.ConversationDomainModified += ConversationDatasourceModified);
                        return(result);
                    };
                    Func <DirectoryInfo, DomainFile> makeEmpty = path => DomainFile.CreateEmpty(path, m_domainDataSource, m_domainSerializer, pathOk, DomainNodeFactory, () => DomainUsage, getDomainEnumSource, backend, Origin);
                    m_domainFiles = new ProjectElementList <IDomainFile>(GetFilePath, s => CheckFolder(s, Origin), loader, makeEmpty);
                    m_domainFiles.Load(domainIds);
                }
                m_conversationDataSource = new ConversationDataSource(m_domainFiles.Select(df => df.Data));

                if (m_conversationDataSource.DomainErrors.Any())
                {
                    MessageBox.Show(string.Join("\n", m_conversationDataSource.DomainErrors.Select(error => error.Message)));
                }

                {
                    m_localizer = new LocalizationEngine(GetFilePath, data.LocalizationSets, context, UsedLocalizations, ShouldContract, pathOk, s => CheckFolder(s, Origin), backend, Origin);
                    m_localizer.Localizers.Load(localizerIds);
                    context.CurrentLocalization.Value    = m_localizer.LocalizationSets.FirstOrDefault() ?? Project.TData.LocalizerSetData.Empty;
                    m_localizer.LocalizationSetsChanged += () => { m_file.Change(); };
                }

                {
                    GenerateAudio audio = (c) =>
                    {
                        return(m_audioProvider.Generate(new AudioGenerationParameters(c.File.File, this.File.File)));
                    };

                    //This can be called from multiple threads simultaneously and in arbitrary orders by design of
                    //ConversationDataSource and the underlying ConstantTypeSet and DynamicEnumParameter.Source
                    Func <IDynamicEnumParameter, object, DynamicEnumParameter.Source> getSource = (localEnum, newSourceID) =>
                    {
                        return(m_conversationDataSource.GetSource(localEnum.TypeId, newSourceID));
                    };

                    Func <IEnumerable <Tuple <Id <FileInProject>, DocumentPath> >, IEnumerable <IConversationFile> > loadConversations = files =>
                    {
                        ISerializerDeserializer <XmlGraphData <NodeUIData, ConversationEditorData> > conversationSerializerDeserializer = m_conversationSerializerFactory(m_conversationDataSource);
                        //                                                 _/          _/                           _/                         X        _/             X            _/
                        //return files.Select(file => ConversationFile.Load(file, ConversationNodeFactory, conversationSerializerDeserializer, audio, getSource, m_audioProvider, backend));
                        //TODO: AUDIO: This is ok as long as we're not using audio parameters at all
                        return(ParallelEnumerable.Select(files.AsParallel(), file => ConversationFile.Load(file.Item1, file.Item2, ConversationNodeFactory, conversationSerializerDeserializer, audio, getSource, m_audioProvider, backend)));
                    };
                    Func <DirectoryInfo, ConversationFile> makeEmpty = path => ConversationFile.CreateEmpty(path, this, ConversationNodeFactory, audio, getSource, m_audioProvider, backend, Origin);
                    m_conversations = new ProjectElementList <IConversationFile>(GetFilePath, s => CheckFolder(s, Origin), loadConversations, makeEmpty);
                    m_conversations.Load(conversationIds);
                }

                RefreshCallbacks(m_conversations, m_actionsOnRefreshCallbacksConversations);
                RefreshCallbacks(m_audioProvider.AudioFiles, m_actionsOnRefreshCallbacksAudios);
                RefreshCallbacks(m_localizer.Localizers, m_actionsOnRefreshCallbacksLocalizations);
                RefreshCallbacks(m_domainFiles, m_actionsOnRefreshCallbacksDomains);

                m_conversations.GotChanged            += GotChanged;
                m_audioProvider.AudioFiles.GotChanged += GotChanged;
                m_localizer.Localizers.GotChanged     += GotChanged;
                m_domainFiles.GotChanged += GotChanged;

                m_conversations.GotChanged            += () => RefreshCallbacks(m_conversations, m_actionsOnRefreshCallbacksConversations);
                m_audioProvider.AudioFiles.GotChanged += () => RefreshCallbacks(m_audioProvider.AudioFiles, m_actionsOnRefreshCallbacksAudios);
                m_localizer.Localizers.GotChanged     += () => RefreshCallbacks(m_localizer.Localizers, m_actionsOnRefreshCallbacksLocalizations);
                m_domainFiles.GotChanged += () => RefreshCallbacks(m_domainFiles, m_actionsOnRefreshCallbacksDomains);


                m_domainFiles.GotChanged += ConversationDatasourceModified;
                Action <IDomainFile> MaybeConversationDatasourceModified = file => { if (!file.File.Changed())
                                                                                     {
                                                                                         ConversationDatasourceModified();
                                                                                     }
                };
                m_domainFiles.Added    += argument => { argument.File.SaveStateChanged += () => MaybeConversationDatasourceModified(argument); };
                m_domainFiles.Reloaded += (_, argument) => { argument.File.SaveStateChanged += () => MaybeConversationDatasourceModified(argument); };
                m_domainFiles.ForAll(d => d.File.SaveStateChanged += () => MaybeConversationDatasourceModified(d));
                //m_domainFiles.Added += argument => { argument.File.SaveStateChanged += () => { if (!argument.File.Changed) ReloadDatasource(); }; };
                //m_domainFiles.Reloaded += (from, to) => { to.File.SaveStateChanged += () => { if (!to.File.Changed) ReloadDatasource(); }; };
                //m_domainFiles.ForAll(d => d.File.SaveStateChanged += () => { if (!d.File.Changed) ReloadDatasource(); });

                m_domainFiles.Added                += file => m_filePaths[file.Id] = DocumentPath.FromAbsolutePath(file.File.File.FullName, Origin);
                m_conversations.Added              += file => m_filePaths[file.Id] = DocumentPath.FromAbsolutePath(file.File.File.FullName, Origin);
                m_audioProvider.AudioFiles.Added   += file => m_filePaths[file.Id] = DocumentPath.FromAbsolutePath(file.File.File.FullName, Origin);
                m_localizer.Localizers.Added       += file => m_filePaths[file.Id] = DocumentPath.FromAbsolutePath(file.File.File.FullName, Origin);
                m_domainFiles.Removed              += file => m_filePaths.Remove(file.Id);
                m_conversations.Removed            += file => m_filePaths.Remove(file.Id);
                m_audioProvider.AudioFiles.Removed += file => m_filePaths.Remove(file.Id);
                m_localizer.Localizers.Removed     += file => m_filePaths.Remove(file.Id);
                //Files being moved is setup in RefreshCallbacks()

                DomainUsage = new DomainUsage(this);

                m_audioProvider.UpdateUsage();
            }
        }
Esempio n. 13
0
        public static Project CreateEmpty(ILocalizationContext context, FileInfo path, INodeFactory conversationNodeFactory, INodeFactory domainNodeFactory, ISerializer <TData> serializer, ISerializer <TConversationData> conversationSerializer, ConversationSerializerDeserializerFactory conversationSerializerDeserializer, ISerializer <TDomainData> domainSerializer, PluginsConfig pluginsConfig, Func <IAudioProviderCustomization> audioCustomization, UpToDateFile.BackEnd backEnd)
        {
            using (MemoryStream m = new MemoryStream())
            {
                //Create the new conversation file stream, fill with essential content and close
                FileInfo conversationFile = ConversationFile.GetAvailableConversationPath(path.Directory, Enumerable.Empty <ISaveableFileProvider>());
                using (FileStream conversationStream = Util.LoadFileStream(conversationFile, FileMode.CreateNew, FileAccess.Write))
                {
                    conversationSerializer.Write(SerializationUtils.MakeConversationData(Enumerable.Empty <ConversationNode>(), new ConversationEditorData()), conversationStream);
                }

                //Create the new project
                GetFilePath getFilePath = null; //Should never need this as all the FileId lists are empty
                Write(getFilePath, Enumerable.Empty <Id <FileInProject> >(), Enumerable.Empty <Id <FileInProject> >(), Enumerable.Empty <Id <FileInProject> >(), Enumerable.Empty <Id <FileInProject> >(), Enumerable.Empty <TData.LocalizerSetData>(), m, serializer);
                using (FileStream projectfile = Util.LoadFileStream(path, FileMode.Create, FileAccess.Write))
                {
                    m.Position = 0;
                    m.CopyTo(projectfile);
                    m.Position = 0;
                }

                TData data = new TData(Enumerable.Empty <TData.FileIdAndPath>(), Enumerable.Empty <TData.FileIdAndPath>(), Enumerable.Empty <TData.FileIdAndPath>(), Enumerable.Empty <TData.FileIdAndPath>(), Enumerable.Empty <TData.LocalizerSetData>());

                Project result = new Project(context, data, conversationNodeFactory, domainNodeFactory, m, path, serializer, conversationSerializer, conversationSerializerDeserializer, domainSerializer, pluginsConfig, audioCustomization, backEnd);
                return(result);
            }
        }
Esempio n. 14
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="nodes"></param>
 /// <param name="groups"></param>
 /// <param name="rawData">Represents the current contents of the file. Reference is not held. A copy is made.</param>
 /// <param name="file"></param>
 /// <param name="errors"></param>
 /// <param name="datasource"></param>
 /// <param name="serializer"></param>
 /// <param name="nodeFactory"></param>
 /// <param name="domainUsage"></param>
 /// <param name="getDocumentSource"></param>
 /// <param name="autoCompletePatterns"></param>
 public DomainFile(IEnumerable <GraphAndUI <NodeUIData> > nodes, IEnumerable <NodeGroup> groups, MemoryStream rawData, Id <FileInProject> file, DocumentPath path, ReadOnlyCollection <LoadError> errors, DomainDomain datasource, ISerializer <TData> serializer, INodeFactory nodeFactory, Func <IDomainUsage <ConversationNode, TransitionNoduleUIInfo> > domainUsage, Func <IDynamicEnumParameter, object, DynamicEnumParameter.Source> getDocumentSource, IEnumerable <IAutoCompletePattern> autoCompletePatterns, UpToDateFile.BackEnd backEnd)
     : base(nodes, groups, errors, nodeFactory, null, getDocumentSource, NoAudio.Instance)
 {
     Id            = file;
     m_file        = new SaveableFileUndoable(rawData, path.FileInfo, SaveTo, backEnd);
     m_domainUsage = domainUsage;
     foreach (var node in m_nodes)
     {
         var n = node;
         node.Modified    += () => NodeModified(n);
         node.Data.Linked += () => NodeLinked(n);
     }
     m_nodes.Inserting += (n) =>
     {
         AddToData(n.Data.Only(), m_datasource);
         ConversationDomainModified.Execute(); //No need to be picky about false positives
         n.Modified    += () => NodeModified(n);
         n.Data.Linked += () => NodeLinked(n);
     };
     m_nodes.Removing += RemoveFromData;
     m_nodes.Clearing += ClearData; //Currently nothing clears the list
     m_datasource      = datasource;
     //m_conversationDatasource = conversationDataSource;
     m_serializer           = serializer;
     m_autoCompletePatterns = new List <IAutoCompletePattern>(autoCompletePatterns);
 }
Esempio n. 15
0
        internal static IEnumerable <IDomainFile> Load(IEnumerable <Tuple <Id <FileInProject>, DocumentPath> > paths, DomainDomain source, Func <DomainDomain, DomainSerializerDeserializer> serializerdeserializer, INodeFactory nodeFactory, Func <IDomainUsage <ConversationNode, TransitionNoduleUIInfo> > domainUsage, Func <IDynamicEnumParameter, object, DynamicEnumParameter.Source> getDocumentSource, UpToDateFile.BackEnd backend)
        {
            var streamsAndPaths = paths.Select((x) =>
            {
                var fileId        = x.Item1;
                DocumentPath path = x.Item2;
                try
                {
                    using (var stream = Util.LoadFileStream(path.FileInfo, FileMode.Open, FileAccess.Read))
                    {
                        return((Either <Tuple <MemoryStream, Id <FileInProject>, DocumentPath>, MissingDomainFile>)Tuple.Create(StreamUtil.Copy(stream), fileId, path));
                    }
                }
                catch (MyFileLoadException e)
                {
                    Console.Out.WriteLine(e.Message);
                    Console.Out.WriteLine(e.StackTrace);
                    Console.Out.WriteLine(e.InnerException.Message);
                    Console.Out.WriteLine(e.InnerException.StackTrace);
                    if (path.Exists)
                    {
                        MessageBox.Show("File: " + path.AbsolutePath + " could not be accessed");
                    }
                    else
                    {
                        MessageBox.Show("File: " + path.AbsolutePath + " does not exist");
                    }

                    MissingDomainFile temp = null;
                    try
                    {
                        temp = new MissingDomainFile(fileId, path);
                        Either <Tuple <MemoryStream, Id <FileInProject>, DocumentPath>, MissingDomainFile> result = temp;
                        return(result);
                    }
                    catch
                    {
                        temp?.Dispose();
                        throw;
                    }
                }
            }).Evaluate();

            var validStreamsAndPaths = Either.Split(streamsAndPaths).Item1; //TODO: Use this in the below cases where we currently use streamsAndPaths
            IReadOnlyCollection <Guid> nonUniqueGuids = serializerdeserializer(source).CheckUniqueIds(validStreamsAndPaths.Select(x => x.Item1));

            if (nonUniqueGuids.Any())
            {
                //TODO: Provide feedback to the user as to why these failed to load.
                //TODO: Unit test this
                return(streamsAndPaths.Select(x => x.Transformed(a => new MissingDomainFile(a.Item2, a.Item3), a => a)));
            }

            //We make the, hopefully, valid assumption here that the deserializers for the various concepts within a domain file have the same version requirements.
            Dictionary <DocumentPath, DeserializerVersionMismatchException> failedToParseFiles = new Dictionary <DocumentPath, DeserializerVersionMismatchException>();

            foreach (var sp in streamsAndPaths)
            {
                sp.Do(stream =>
                {
                    try
                    {
                        var categoryData = serializerdeserializer(source).CategoriesDeserializer.Read(stream.Item1);
                        DomainFile.AddToData(categoryData.Nodes.Select(n => n.GraphData), source);
                    }
                    catch (DeserializerVersionMismatchException e)
                    {
                        failedToParseFiles[stream.Item3] = e;
                    }
                }, a => { });
            }
            foreach (var sp in streamsAndPaths)
            {
                sp.Do(stream =>
                {
                    try
                    {
                        var typeData = serializerdeserializer(source).TypesDeserializer.Read(stream.Item1);
                        DomainFile.AddToData(typeData.Nodes.Select(n => n.GraphData), source);
                    }
                    catch (DeserializerVersionMismatchException e)
                    {
                        failedToParseFiles[stream.Item3] = e;
                    }
                }, a => { });
            }
            foreach (var sp in streamsAndPaths)
            {
                sp.Do(stream =>
                {
                    try
                    {
                        var connectorData = serializerdeserializer(source).ConnectorsDeserializer.Read(stream.Item1);
                        DomainFile.AddToData(connectorData.Nodes.Select(n => n.GraphData), source);
                    }
                    catch (DeserializerVersionMismatchException e)
                    {
                        failedToParseFiles[stream.Item3] = e;
                    }
                }, a => { });
            }
            foreach (var sp in streamsAndPaths)
            {
                sp.Do(stream =>
                {
                    try
                    {
                        var nodeData = serializerdeserializer(source).NodesDeserializer.Read(stream.Item1);
                        DomainFile.AddToData(nodeData.Nodes.Select(n => n.GraphData), source);
                    }
                    catch (DeserializerVersionMismatchException e)
                    {
                        failedToParseFiles[stream.Item3] = e;
                    }
                }, a => { });
            }

            {
                var result = streamsAndPaths.Select(a => a.Transformed <IDomainFile>(stream =>
                {
                    try
                    {
                        var editorData = serializerdeserializer(source).EditorDataDeserializer.Read(stream.Item1);
                        DomainFile.AddToData(editorData.Nodes.Select(n => n.GraphData), source);
                        var allData = serializerdeserializer(source).EverythingDeserializer.Read(stream.Item1);

                        List <IAutoCompletePattern> autoCompletePatterns = new List <IAutoCompletePattern>();
                        var nodeData = serializerdeserializer(source).AutoCompleteSuggestionsDeserializer.Read(stream.Item1);
                        autoCompletePatterns.AddRange(AutoCompletePattern.Generate(nodeData, source));

                        return(new DomainFile(allData.Nodes.ToList(), editorData.EditorData.Groups.ToList(), stream.Item1, stream.Item2, stream.Item3, allData.Errors, source, serializerdeserializer(source).Serializer, nodeFactory, domainUsage, getDocumentSource, autoCompletePatterns, backend));
                    }
                    catch (DeserializerVersionMismatchException e)
                    {
                        failedToParseFiles[stream.Item3] = e;
                        return(new MissingDomainFile(stream.Item2, stream.Item3));
                    }
                }, b => b));

                if (failedToParseFiles.Any())
                {
                    //TODO: expose this to the user in a consistent way with other errors (missing files, duplicated or missing guids)
                    StringBuilder message = new StringBuilder("Failed to parse files:\n");
                    foreach (var kvp in failedToParseFiles)
                    {
                        message.Append("\n");
                        message.Append(kvp.Key.RelativePath);
                        message.Append(": ");
                        message.Append(kvp.Value.Message);
                    }
                    MessageBox.Show(message.ToString());
                }

                return(result);
            }
        }
Esempio n. 16
0
        public static DomainFile CreateEmpty(DirectoryInfo directory, DomainDomain datasource, ISerializer <TData> serializer, Func <FileInfo, bool> pathOk, INodeFactory nodeFactory, Func <IDomainUsage <ConversationNode, TransitionNoduleUIInfo> > domainUsage, Func <IDynamicEnumParameter, object, DynamicEnumParameter.Source> getDocumentSource, UpToDateFile.BackEnd backEnd, DirectoryInfo origin)
        {
            //Create a stream under an available filename
            FileInfo path = null;

            for (int i = 0; path == null; i++)
            {
                path = new FileInfo(directory.FullName + Path.DirectorySeparatorChar + "New Domain " + i + ".dom");
                if (!pathOk(path))
                {
                    path = null;
                }
            }

            using (MemoryStream m = new MemoryStream())
            {
                using (var stream = Util.LoadFileStream(path, FileMode.CreateNew, FileAccess.Write))
                {
                    serializer.Write(SerializationUtils.MakeDomainData(Enumerable.Empty <ConversationNode>(), new ConversationEditorData()), m);
                    m.CopyTo(stream);
                }

                var result = new DomainFile(new List <GraphAndUI <NodeUIData> >(), new List <NodeGroup>(), m, Id <FileInProject> .New(), DocumentPath.FromPath(path, origin), new ReadOnlyCollection <LoadError>(new LoadError[0]), datasource, serializer, nodeFactory, domainUsage, getDocumentSource, new List <IAutoCompletePattern>(), backEnd);
                result.m_file.Save(); //Make sure the file starts life as a valid xml document
                return(result);
            }
        }