Project and solution enhancements - they actually work now

This commit is contained in:
Michael Becker 2019-10-25 01:05:14 -04:00
parent 985dacd494
commit 4662aa8999
10 changed files with 490 additions and 11 deletions

View File

@ -35,5 +35,49 @@ namespace UniversalEditor.ObjectModels.Project
clone.Folders.Add(folder.Clone() as ProjectFolder);
}
}
public void AddFile(string sourceFileName, string destinationFileName, char pathSeparator)
{
string[] paths = destinationFileName.Split(pathSeparator);
ProjectFolder parentFolder = null;
for (int i = 0; i < paths.Length - 1; i++)
{
if (parentFolder == null)
{
if (Folders[paths[i]] != null)
{
parentFolder = Folders[paths[i]];
}
else
{
parentFolder = Folders.Add(paths[i]);
}
}
else
{
if (parentFolder.Folders[paths[i]] != null)
{
parentFolder = parentFolder.Folders[paths[i]];
}
else
{
parentFolder = parentFolder.Folders.Add(paths[i]);
}
}
}
ProjectFile pf = new ProjectFile();
pf.SourceFileName = sourceFileName;
pf.DestinationFileName = paths[paths.Length - 1];
if (parentFolder == null)
{
Files.Add(pf);
}
else
{
parentFolder.Files.Add(pf);
}
}
}
}

View File

@ -24,13 +24,28 @@ namespace UniversalEditor.ObjectModels.Project
return folder;
}
private Dictionary<string, ProjectFolder> _itemsByName = new Dictionary<string, ProjectFolder>();
public ProjectFolder this[string name]
{
get
{
if (_itemsByName.ContainsKey(name))
return _itemsByName[name];
return null;
}
}
protected override void InsertItem(int index, ProjectFolder item)
{
base.InsertItem(index, item);
item.Parent = _parent;
_itemsByName[item.Name] = item;
}
protected override void RemoveItem(int index)
{
if (_itemsByName.ContainsKey(this[index].Name))
_itemsByName.Remove(this[index].Name);
this[index].Parent = null;
base.RemoveItem(index);
}
@ -42,6 +57,15 @@ namespace UniversalEditor.ObjectModels.Project
}
base.ClearItems();
}
protected override void SetItem(int index, ProjectFolder item)
{
if (_itemsByName.ContainsKey(this[index].Name))
_itemsByName.Remove(this[index].Name);
base.SetItem(index, item);
_itemsByName[item.Name] = item;
}
}
public ProjectFolder()

View File

@ -91,6 +91,8 @@ namespace UniversalEditor.UserInterface.Dialogs
this.lblProjectName = new Label ((Mode == NewDialogMode.File ? "Project" : "Solution") + " na_me:");
this.lblProjectName.HorizontalAlignment = HorizontalAlignment.Left;
this.txtFileName.Changed += txtFileName_Changed;
Container tableParams = new Container();
tableParams.Layout = new GridLayout();
tableParams.Controls.Add(lblName, new GridLayout.Constraints(0, 0));
@ -119,5 +121,6 @@ namespace UniversalEditor.UserInterface.Dialogs
this.MinimumSize = new MBS.Framework.Drawing.Dimension2D (500, 400);
this.Size = new MBS.Framework.Drawing.Dimension2D (600, 500);
}
}
}

View File

@ -154,6 +154,15 @@ namespace UniversalEditor.UserInterface.Dialogs
public string SolutionTitle { get; set; }
public string ProjectTitle { get; set; }
private void txtFileName_Changed(object sender, EventArgs e)
{
if (!txtSolutionName.IsChangedByUser)
{
txtSolutionName.Text = txtFileName.Text;
}
}
protected override void OnCreating(EventArgs e)
{
base.OnCreating(e);
@ -163,11 +172,15 @@ namespace UniversalEditor.UserInterface.Dialogs
case NewDialogMode.File:
{
this.Text = "New File";
this.lblProjectName.Text = "Project na_me:";
this.chkAddToSolution.Visible = true;
break;
}
case NewDialogMode.Project:
{
this.Text = "New Project";
this.lblProjectName.Text = "Solution na_me:";
this.chkAddToSolution.Visible = false;
break;
}
}
@ -506,6 +519,9 @@ namespace UniversalEditor.UserInterface.Dialogs
private void cmdOK_Click(object sender, EventArgs e)
{
SolutionTitle = txtSolutionName.Text;
ProjectTitle = txtFileName.Text;
this.DialogResult = DialogResult.OK;
/*
if (String.IsNullOrEmpty(this.txtFileName.Text))

View File

@ -586,18 +586,62 @@ namespace UniversalEditor.UserInterface
public void OpenProject(bool combineObjects = false)
{
FileDialog dlg = new FileDialog();
dlg.FileNameFilters.Add("Project files", "*.ueproj");
dlg.FileNameFilters.Add("Solution files", "*.uesln");
Association[] projectAssocs = Association.FromObjectModelOrDataFormat((new ProjectObjectModel()).MakeReference());
Association[] solutionAssocs = Association.FromObjectModelOrDataFormat((new SolutionObjectModel()).MakeReference());
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (Association projectAssoc in projectAssocs)
{
for (int i = 0; i < projectAssoc.Filters.Count; i++)
{
for (int j = 0; j < projectAssoc.Filters[i].FileNameFilters.Count; j++)
{
sb.Append(projectAssoc.Filters[i].FileNameFilters[j]);
if (j < projectAssoc.Filters[i].FileNameFilters.Count - 1)
sb.Append("; ");
}
if (i < projectAssoc.Filters.Count - 1)
sb.Append("; ");
}
}
dlg.FileNameFilters.Add("Project files", sb.ToString());
sb.Clear();
foreach (Association solutionAssoc in solutionAssocs)
{
for (int i = 0; i < solutionAssoc.Filters.Count; i++)
{
for (int j = 0; j < solutionAssoc.Filters[i].FileNameFilters.Count; j++)
{
sb.Append(solutionAssoc.Filters[i].FileNameFilters[j]);
if (j < solutionAssoc.Filters[i].FileNameFilters.Count - 1)
sb.Append("; ");
}
if (i < solutionAssoc.Filters.Count - 1)
sb.Append("; ");
}
}
dlg.FileNameFilters.Add("Solution files", sb.ToString());
dlg.Text = "Open Project or Solution";
if (dlg.ShowDialog() == DialogResult.OK)
{
OpenProject(dlg.SelectedFileNames[dlg.SelectedFileNames.Count - 1], combineObjects);
}
}
public void OpenProject(string FileName, bool combineObjects = false)
{
throw new NotImplementedException();
if (!combineObjects)
CurrentSolution = new SolutionObjectModel();
FileAccessor fa = new FileAccessor(FileName);
Association[] assocs = Association.FromAccessor(fa);
DataFormat df = assocs[0].DataFormats[0].Create();
Document.Load(_CurrentSolution, df, fa);
CurrentSolution = _CurrentSolution; // to reset the UI
}
public void SaveFile()
@ -696,12 +740,52 @@ namespace UniversalEditor.UserInterface
public void SaveProject()
{
throw new NotImplementedException();
if (_CurrentSolutionDocument != null && _CurrentSolutionDocument.IsSaved)
{
MessageDialog.ShowDialog("TODO: overwrite current solution in-place", "Implement this!", MessageDialogButtons.OK);
}
else
{
SaveProjectAs();
}
}
public void SaveProjectAs()
{
throw new NotImplementedException();
if (CurrentSolution == null)
return;
Association[] assocs = Association.FromObjectModelOrDataFormat(CurrentSolution.MakeReference());
FileDialog dlg = new FileDialog();
dlg.Mode = FileDialogMode.Save;
System.Text.StringBuilder sbFilter = new System.Text.StringBuilder();
foreach (Association assoc in assocs)
{
foreach (DataFormatFilter filter in assoc.Filters)
{
sbFilter.Clear();
for (int i = 0; i < filter.FileNameFilters.Count; i++)
{
sbFilter.Append(filter.FileNameFilters[i]);
if (i < filter.FileNameFilters.Count - 1)
sbFilter.Append("; ");
}
dlg.FileNameFilters.Add(filter.Title, sbFilter.ToString());
}
}
DataFormat df = assocs[0].DataFormats[0].Create();
if (dlg.ShowDialog() == DialogResult.OK)
{
_CurrentSolutionDocument = new Document(CurrentSolution, df, new FileAccessor(dlg.SelectedFileNames[dlg.SelectedFileNames.Count - 1], true, true));
_CurrentSolutionDocument.Accessor.Open();
_CurrentSolutionDocument.Save();
_CurrentSolutionDocument.Accessor.Close();
}
}
public void SaveProjectAs(string FileName, DataFormat df)
@ -741,7 +825,7 @@ namespace UniversalEditor.UserInterface
public void CloseProject()
{
throw new NotImplementedException();
CurrentSolution = null;
}
public void CloseWindow()
@ -913,7 +997,22 @@ namespace UniversalEditor.UserInterface
public bool FullScreen { get; set; }
public SolutionObjectModel CurrentSolution { get; set; }
private SolutionObjectModel _CurrentSolution = null;
private Document _CurrentSolutionDocument = null;
public SolutionObjectModel CurrentSolution
{
get { return _CurrentSolution; }
set
{
bool changed = (_CurrentSolution != value);
_CurrentSolution = value;
if (value == null || changed)
_CurrentSolutionDocument = null;
pnlSolutionExplorer.Solution = value;
}
}
#endregion

View File

@ -22,7 +22,9 @@ using System;
using MBS.Framework.UserInterface;
using MBS.Framework.UserInterface.Controls;
using MBS.Framework.UserInterface.Dialogs;
using MBS.Framework.UserInterface.Layouts;
using UniversalEditor.ObjectModels.Solution;
namespace UniversalEditor.UserInterface.Panels
{
@ -31,16 +33,228 @@ namespace UniversalEditor.UserInterface.Panels
private DefaultTreeModel tmSolutionExplorer = null;
private ListView tvSolutionExplorer = new ListView();
private SolutionObjectModel _Solution = null;
public SolutionObjectModel Solution
{
get { return _Solution; }
set
{
_Solution = value;
UpdateSolutionExplorer();
}
}
private TreeModelRow LoadSolutionExplorerFolder(ObjectModels.Project.ProjectFolder fold)
{
TreeModelRow rowFolder = new TreeModelRow(new TreeModelRowColumn[]
{
new TreeModelRowColumn(tmSolutionExplorer.Columns[0], fold.Name)
});
rowFolder.SetExtraData<ObjectModels.Project.ProjectFolder>("folder", fold);
foreach (ObjectModels.Project.ProjectFolder fold2 in fold.Folders)
{
TreeModelRow row = LoadSolutionExplorerFolder(fold2);
rowFolder.Rows.Add(row);
}
foreach (ObjectModels.Project.ProjectFile file in fold.Files)
{
TreeModelRow rowFile = new TreeModelRow(new TreeModelRowColumn[]
{
new TreeModelRowColumn(tmSolutionExplorer.Columns[0], file.DestinationFileName)
});
rowFile.SetExtraData<ObjectModels.Project.ProjectFile>("file", file);
rowFolder.Rows.Add(rowFile);
}
return rowFolder;
}
private void UpdateSolutionExplorer()
{
tmSolutionExplorer.Rows.Clear();
if (_Solution != null)
{
TreeModelRow rowSolution = new TreeModelRow(new TreeModelRowColumn[]
{
new TreeModelRowColumn(tmSolutionExplorer.Columns[0], _Solution.Title)
});
rowSolution.SetExtraData<ObjectModels.Solution.SolutionObjectModel>("solution", _Solution);
foreach (ObjectModels.Project.ProjectObjectModel proj in _Solution.Projects)
{
TreeModelRow rowProject = new TreeModelRow(new TreeModelRowColumn[]
{
new TreeModelRowColumn(tmSolutionExplorer.Columns[0], proj.Title)
});
rowProject.SetExtraData<ObjectModels.Project.ProjectObjectModel>("project", proj);
TreeModelRow rowReferences = new TreeModelRow(new TreeModelRowColumn[]
{
new TreeModelRowColumn(tmSolutionExplorer.Columns[0], "References")
});
foreach (ObjectModels.Project.Reference reff in proj.References)
{
rowReferences.Rows.Add(new TreeModelRow(new TreeModelRowColumn[]
{
new TreeModelRowColumn(tmSolutionExplorer.Columns[0], reff.Title)
}));
}
rowProject.Rows.Add(rowReferences);
foreach (ObjectModels.Project.ProjectFolder fold in proj.FileSystem.Folders)
{
TreeModelRow row = LoadSolutionExplorerFolder(fold);
rowProject.Rows.Add(row);
}
foreach (ObjectModels.Project.ProjectFile file in proj.FileSystem.Files)
{
TreeModelRow row = new TreeModelRow(new TreeModelRowColumn[]
{
new TreeModelRowColumn(tmSolutionExplorer.Columns[0], file.DestinationFileName)
});
row.SetExtraData<ObjectModels.Project.ProjectFile>("file", file);
rowProject.Rows.Add(row);
}
rowSolution.Rows.Add(rowProject);
}
tmSolutionExplorer.Rows.Add(rowSolution);
}
}
private Menu mnuContextProject = null;
private Menu mnuContextSolution = null;
private Menu mnuContextFolder = null;
private Menu mnuContextFile = null;
public SolutionExplorerPanel()
{
this.Layout = new BoxLayout(Orientation.Vertical);
tmSolutionExplorer = new DefaultTreeModel(new Type[] { typeof(string) });
tvSolutionExplorer.Model = tmSolutionExplorer;
tvSolutionExplorer.BeforeContextMenu += tvSolutionExplorer_BeforeContextMenu;
// (UniversalEditor.exe:24867): Gtk-CRITICAL **: 21:28:56.913: gtk_tree_store_set_value: assertion 'G_IS_VALUE (value)' failed
tvSolutionExplorer.Columns.Add(new ListViewColumnText(tmSolutionExplorer.Columns[0], "File Name"));
this.Controls.Add(tvSolutionExplorer, new BoxLayout.Constraints(true, true));
mnuContextProject = new Menu();
mnuContextProject.Items.AddRange(new MBS.Framework.UserInterface.MenuItem[]
{
new MBS.Framework.UserInterface.CommandMenuItem("B_uild Project"),
new MBS.Framework.UserInterface.CommandMenuItem("R_ebuild Project"),
new MBS.Framework.UserInterface.CommandMenuItem("C_lean Project"),
new MBS.Framework.UserInterface.CommandMenuItem("Unload"),
new MBS.Framework.UserInterface.SeparatorMenuItem(),
new MBS.Framework.UserInterface.CommandMenuItem("Run Pro_ject"),
new MBS.Framework.UserInterface.CommandMenuItem("_Debug Project"),
new MBS.Framework.UserInterface.SeparatorMenuItem(),
new MBS.Framework.UserInterface.CommandMenuItem("A_dd", new MBS.Framework.UserInterface.MenuItem[]
{
new MBS.Framework.UserInterface.CommandMenuItem("New _File..."),
new MBS.Framework.UserInterface.CommandMenuItem("E_xisting File(s)...", null, mnuContextProjectAddExistingFiles_Click)
}),
new MBS.Framework.UserInterface.SeparatorMenuItem(),
new MBS.Framework.UserInterface.CommandMenuItem("Cu_t"),
new MBS.Framework.UserInterface.CommandMenuItem("_Copy"),
new MBS.Framework.UserInterface.CommandMenuItem("_Paste"),
new MBS.Framework.UserInterface.CommandMenuItem("_Delete"),
new MBS.Framework.UserInterface.SeparatorMenuItem(),
new MBS.Framework.UserInterface.CommandMenuItem("P_roperties...")
});
mnuContextSolution = new Menu();
mnuContextSolution.Items.AddRange(new MBS.Framework.UserInterface.MenuItem[]
{
new MBS.Framework.UserInterface.CommandMenuItem("B_uild Solution"),
new MBS.Framework.UserInterface.CommandMenuItem("R_ebuild Solution"),
new MBS.Framework.UserInterface.CommandMenuItem("C_lean Solution"),
new MBS.Framework.UserInterface.CommandMenuItem("Unload"),
new MBS.Framework.UserInterface.SeparatorMenuItem(),
new MBS.Framework.UserInterface.CommandMenuItem("Run Solution"),
new MBS.Framework.UserInterface.CommandMenuItem("_Debug Solution"),
new MBS.Framework.UserInterface.SeparatorMenuItem(),
new MBS.Framework.UserInterface.CommandMenuItem("A_dd", new MBS.Framework.UserInterface.MenuItem[]
{
new MBS.Framework.UserInterface.CommandMenuItem("New _Project...", null, mnuContextSolutionAddNewProject_Click),
new MBS.Framework.UserInterface.CommandMenuItem("E_xisting Project..."),
new MBS.Framework.UserInterface.SeparatorMenuItem(),
new MBS.Framework.UserInterface.CommandMenuItem("New Fol_der")
}),
new MBS.Framework.UserInterface.SeparatorMenuItem(),
new MBS.Framework.UserInterface.CommandMenuItem("Cu_t"),
new MBS.Framework.UserInterface.CommandMenuItem("_Copy"),
new MBS.Framework.UserInterface.CommandMenuItem("_Paste"),
new MBS.Framework.UserInterface.CommandMenuItem("_Delete"),
new MBS.Framework.UserInterface.SeparatorMenuItem(),
new MBS.Framework.UserInterface.CommandMenuItem("P_roperties...")
});
mnuContextFile = new Menu();
mnuContextFolder = new Menu();
}
private void mnuContextProjectAddExistingFiles_Click(object sender, EventArgs e)
{
TreeModelRow row = tvSolutionExplorer.LastHitTest.Row;
if (row == null) return;
ObjectModels.Project.ProjectObjectModel proj = row.GetExtraData<ObjectModels.Project.ProjectObjectModel>("project");
if (proj == null) return;
FileDialog dlg = new FileDialog();
dlg.Mode = FileDialogMode.Open;
dlg.MultiSelect = true;
if (dlg.ShowDialog() == DialogResult.OK)
{
foreach (string filename in dlg.SelectedFileNames)
{
ObjectModels.Project.ProjectFile pf = new ObjectModels.Project.ProjectFile();
pf.SourceFileName = filename;
pf.DestinationFileName = System.IO.Path.GetFileName(filename);
proj.FileSystem.Files.Add(pf);
}
UpdateSolutionExplorer();
}
}
private void mnuContextSolutionAddNewProject_Click(object sender, EventArgs e)
{
MainWindow mw = (Engine.CurrentEngine.LastWindow as MainWindow);
if (mw == null) return;
mw.NewProject(true);
}
private void tvSolutionExplorer_BeforeContextMenu(object sender, EventArgs e)
{
if (tvSolutionExplorer.LastHitTest.Row != null)
{
ObjectModels.Project.ProjectObjectModel project = tvSolutionExplorer.LastHitTest.Row.GetExtraData<ObjectModels.Project.ProjectObjectModel>("project");
ObjectModels.Solution.SolutionObjectModel solution = tvSolutionExplorer.LastHitTest.Row.GetExtraData<ObjectModels.Solution.SolutionObjectModel>("solution");
ObjectModels.Project.ProjectFolder folder = tvSolutionExplorer.LastHitTest.Row.GetExtraData<ObjectModels.Project.ProjectFolder>("folder");
ObjectModels.Project.ProjectFile file = tvSolutionExplorer.LastHitTest.Row.GetExtraData<ObjectModels.Project.ProjectFile>("file");
if (project != null)
{
tvSolutionExplorer.ContextMenu = mnuContextProject;
}
else if (solution != null)
{
tvSolutionExplorer.ContextMenu = mnuContextSolution;
}
else if (folder != null)
{
tvSolutionExplorer.ContextMenu = mnuContextFolder;
}
else if (file != null)
{
tvSolutionExplorer.ContextMenu = mnuContextFile;
}
}
}
}
}

View File

@ -38,6 +38,37 @@ namespace UniversalEditor.DataFormats.Project.Microsoft.VisualStudio
{
MarkupObjectModel mom = (objectModels.Pop() as MarkupObjectModel);
ProjectObjectModel proj = (objectModels.Pop() as ProjectObjectModel);
string basePath = System.IO.Path.GetDirectoryName(Accessor.GetFileName());
MarkupTagElement tagProject = (mom.Elements["Project"] as MarkupTagElement);
if (tagProject == null) throw new InvalidDataFormatException();
for (int i = 0; i < tagProject.Elements.Count; i++)
{
MarkupTagElement tag = (tagProject.Elements[i] as MarkupTagElement);
if (tag == null) continue;
if (tag.FullName.Equals("ItemGroup"))
{
for (int j = 0; j < tag.Elements.Count; j++)
{
MarkupTagElement tag1 = (tag.Elements[j] as MarkupTagElement);
if (tag1.FullName.Equals("Compile") || tag1.FullName.Equals("Content") || tag1.FullName.Equals("None"))
{
MarkupAttribute attInclude = tag1.Attributes["Include"];
proj.FileSystem.AddFile(basePath + System.IO.Path.DirectorySeparatorChar.ToString() + attInclude.Value.Replace('\\', System.IO.Path.DirectorySeparatorChar), attInclude.Value, '\\');
}
else if (tag1.FullName.Equals("Reference"))
{
MarkupAttribute attInclude = tag1.Attributes["Include"];
Reference reff = new Reference();
reff.Title = attInclude.Value;
proj.References.Add(reff);
}
}
}
}
}
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
{

View File

@ -0,0 +1,28 @@
//
// KnownProjectTypeIDs.cs
//
// Author:
// Mike Becker <alcexhim@gmail.com>
//
// Copyright (c) 2019 Mike Becker
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
namespace UniversalEditor.DataFormats.Solution.Microsoft.VisualStudio
{
public class KnownProjectTypeIDs
{
public static readonly Guid SolutionFolder = new Guid("{2150E333-8FDC-42A3-9474-1A3956D46DE8}");
}
}

View File

@ -51,9 +51,11 @@ namespace UniversalEditor.DataFormats.Solution.Microsoft.VisualStudio
{
solutionFileName = (base.Accessor as FileAccessor).FileName;
}
sol.Title = System.IO.Path.GetFileNameWithoutExtension(solutionFileName);
solutionPath = System.IO.Path.GetDirectoryName(solutionFileName);
string signature2a = reader.ReadLine();
signature2a = signature2a.Trim();
if (!String.IsNullOrEmpty(signature2a)) throw new InvalidDataFormatException("Empty line should be present at beginning of file");
string signature2Verify = "Microsoft Visual Studio Solution File, Format Version ";
@ -86,9 +88,26 @@ namespace UniversalEditor.DataFormats.Solution.Microsoft.VisualStudio
string projectFileName = solutionPath + System.IO.Path.DirectorySeparatorChar.ToString() + projectRelativeFileName;
Guid projectID = new Guid(paramz[2].Trim());
ProjectObjectModel project = UniversalEditor.Common.Reflection.GetAvailableObjectModel<ProjectObjectModel>(projectFileName);
sol.Projects.Add(project);
lastProject = project;
if (projectTypeID == KnownProjectTypeIDs.SolutionFolder)
{
ProjectFolder pf = new ProjectFolder();
pf.Name = projectTitle;
}
else
{
projectFileName = projectFileName.Replace('\\', System.IO.Path.DirectorySeparatorChar);
if (System.IO.File.Exists(projectFileName))
{
ProjectObjectModel project = UniversalEditor.Common.Reflection.GetAvailableObjectModel<ProjectObjectModel>(projectFileName);
project.Title = projectTitle;
sol.Projects.Add(project);
lastProject = project;
}
else
{
Console.WriteLine("skipping nonexistent project file {0}", projectFileName);
}
}
}
else if (line == "EndProject")
{

View File

@ -39,6 +39,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="DataFormats\Project\Microsoft\VisualStudio\VisualStudioProjectDataFormat.cs" />
<Compile Include="DataFormats\Solution\Microsoft\VisualStudio\VisualStudioSolutionDataFormat.cs" />
<Compile Include="DataFormats\Solution\Microsoft\VisualStudio\KnownProjectTypeIDs.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Libraries\UniversalEditor.Core\UniversalEditor.Core.csproj">