Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/issue-1955' into preview
Browse files Browse the repository at this point in the history
  • Loading branch information
glopesdev committed Sep 3, 2024
2 parents df9f833 + 1918966 commit c822587
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 79 deletions.
99 changes: 22 additions & 77 deletions Bonsai.Editor/EditorForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,9 @@ public partial class EditorForm : Form
{
const float DefaultEditorScale = 1.0f;
const string EditorUid = "editor";
const string BonsaiExtension = ".bonsai";
const string BonsaiPackageName = "Bonsai";
const string ExtensionsDirectory = "Extensions";
const string DefinitionsDirectory = "Definitions";
const string WorkflowCategoryName = "Workflow";
const string SubjectCategoryName = "Subject";
const string DefaultWorkflowNamespace = "Unspecified";
static readonly AttributeCollection DesignTimeAttributes = new AttributeCollection(BrowsableAttribute.Yes, DesignTimeVisibleAttribute.Yes);
static readonly AttributeCollection RuntimeAttributes = AttributeCollection.FromExisting(DesignTimeAttributes, DesignOnlyAttribute.No);
static readonly char[] ToolboxArgumentSeparator = new[] { ' ' };
Expand Down Expand Up @@ -167,7 +163,7 @@ public EditorForm(
documentationProvider = (IDocumentationProvider)serviceProvider.GetService(typeof(IDocumentationProvider));
}

definitionsPath = Path.Combine(Path.GetTempPath(), DefinitionsDirectory + "." + GuidHelper.GetProcessGuid().ToString());
definitionsPath = Project.GetDefinitionsTempPath();
editorControl = new WorkflowEditorControl(editorSite);
editorControl.Enter += new EventHandler(editorControl_Enter);
editorControl.Workflow = workflowBuilder.Workflow;
Expand Down Expand Up @@ -290,7 +286,7 @@ protected override void OnLoad(EventArgs e)
var initialFileName = FileName;
var validFileName =
!string.IsNullOrEmpty(initialFileName) &&
Path.GetExtension(initialFileName) == BonsaiExtension &&
Path.GetExtension(initialFileName) == Project.BonsaiExtension &&
File.Exists(initialFileName);

var formClosed = Observable.FromEventPattern<FormClosedEventHandler, FormClosedEventArgs>(
Expand All @@ -300,19 +296,8 @@ protected override void OnLoad(EventArgs e)
InitializeWorkflowFileWatcher().TakeUntil(formClosed).Subscribe();
updatesAvailable.TakeUntil(formClosed).ObserveOn(formScheduler).Subscribe(HandleUpdatesAvailable);

var currentDirectory = Path.GetFullPath(Environment.CurrentDirectory).TrimEnd('\\');
var appDomainBaseDirectory = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory).TrimEnd('\\');
var currentDirectoryRestricted = currentDirectory == appDomainBaseDirectory;
if (!EditorSettings.IsRunningOnMono)
{
var systemPath = Path.GetFullPath(Environment.GetFolderPath(Environment.SpecialFolder.System)).TrimEnd('\\');
var systemX86Path = Path.GetFullPath(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86)).TrimEnd('\\');
currentDirectoryRestricted |= currentDirectory == systemPath || currentDirectory == systemX86Path;
}

var workflowBaseDirectory = validFileName
? Path.GetDirectoryName(initialFileName)
: (!currentDirectoryRestricted ? currentDirectory : Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
var currentDirectory = Project.GetCurrentBaseDirectory(out bool currentDirectoryRestricted);
var workflowBaseDirectory = validFileName ? Project.GetWorkflowBaseDirectory(initialFileName) : currentDirectory;
if (currentDirectoryRestricted)
{
currentDirectory = workflowBaseDirectory;
Expand All @@ -321,7 +306,7 @@ protected override void OnLoad(EventArgs e)

directoryToolStripItem.Text = currentDirectory;
openWorkflowDialog.InitialDirectory = saveWorkflowDialog.InitialDirectory = currentDirectory;
extensionsPath = new DirectoryInfo(Path.Combine(workflowBaseDirectory, ExtensionsDirectory));
extensionsPath = new DirectoryInfo(Path.Combine(workflowBaseDirectory, Project.ExtensionsDirectory));
if (extensionsPath.Exists) OnExtensionsDirectoryChanged(EventArgs.Empty);

InitializeEditorToolboxTypes();
Expand Down Expand Up @@ -520,7 +505,7 @@ IObservable<Unit> RefreshWorkflowExtensions()
.Merge(start, changed, created, deleted, renamed)
.Throttle(TimeSpan.FromSeconds(1), Scheduler.Default)
.Select(evt => workflowExtensions
.Concat(FindWorkflows(ExtensionsDirectory))
.Concat(Project.EnumerateExtensionWorkflows(extensionsPath.FullName))
.GroupBy(x => x.Namespace)
.ToList())
.ObserveOn(formScheduler)
Expand Down Expand Up @@ -560,57 +545,6 @@ IObservable<Unit> RefreshWorkflowExtensions()
.Select(xs => Unit.Default);
}

static IEnumerable<WorkflowElementDescriptor> FindWorkflows(string basePath)
{
int basePathLength;
string[] workflowFiles;
if (!Path.IsPathRooted(basePath))
{
var currentDirectory = Environment.CurrentDirectory;
basePath = Path.Combine(currentDirectory, basePath);
basePathLength = currentDirectory.Length;
}
else basePathLength = basePath.Length;

try { workflowFiles = Directory.GetFiles(basePath, "*" + BonsaiExtension, SearchOption.AllDirectories); }
catch (UnauthorizedAccessException) { yield break; }
catch (DirectoryNotFoundException) { yield break; }

foreach (var fileName in workflowFiles)
{
var description = string.Empty;
try
{
using (var reader = XmlReader.Create(fileName, new XmlReaderSettings { IgnoreWhitespace = true }))
{
reader.ReadStartElement(typeof(WorkflowBuilder).Name);
if (reader.Name == nameof(WorkflowBuilder.Description))
{
reader.ReadStartElement();
description = reader.Value;
}
}
}
catch (SystemException) { continue; }

var relativePath = fileName.Substring(basePathLength)
.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var fileNamespace = Path.GetDirectoryName(relativePath)
.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar)
.Replace(Path.DirectorySeparatorChar, ExpressionHelper.MemberSeparator.First());
if (string.IsNullOrEmpty(fileNamespace)) fileNamespace = DefaultWorkflowNamespace;

yield return new WorkflowElementDescriptor
{
Name = Path.GetFileNameWithoutExtension(relativePath),
Namespace = fileNamespace,
FullyQualifiedName = relativePath,
Description = description,
ElementTypes = new[] { ~ElementCategory.Workflow }
};
}
}

IObservable<Unit> InitializeTypeVisualizers()
{
var visualizerMapping = from typeVisualizer in visualizerElements
Expand Down Expand Up @@ -657,7 +591,7 @@ IEnumerable<WorkflowElementDescriptor> InitializeWorkflowExtensions(IEnumerable<

static string GetPackageDisplayName(string packageKey)
{
if (packageKey == null) return ExtensionsDirectory;
if (packageKey == null) return Project.ExtensionsDirectory;
if (packageKey == BonsaiPackageName) return packageKey;
return packageKey.Replace(BonsaiPackageName + ".", string.Empty);
}
Expand Down Expand Up @@ -855,6 +789,7 @@ bool OpenWorkflow(string fileName, bool setWorkingDirectory)
editorControl.Workflow = workflowBuilder.Workflow;
editorSite.ValidateWorkflow();

#pragma warning disable CS0612 // Support for deprecated layout config files
var layoutPath = LayoutHelper.GetLayoutPath(fileName);
if (File.Exists(layoutPath))
{
Expand All @@ -864,6 +799,7 @@ bool OpenWorkflow(string fileName, bool setWorkingDirectory)
catch (InvalidOperationException) { }
}
}
#pragma warning restore CS0612 // Support for deprecated layout config files

saveWorkflowDialog.FileName = fileName;
ResetProjectStatus();
Expand Down Expand Up @@ -917,8 +853,17 @@ bool SaveWorkflow(string fileName)
editorControl.UpdateVisualizerLayout();
if (editorControl.VisualizerLayout != null)
{
var layoutPath = LayoutHelper.GetLayoutPath(fileName);
SaveVisualizerLayout(layoutPath, editorControl.VisualizerLayout);
var layoutPath = new FileInfo(Project.GetLayoutConfigPath(fileName));
layoutPath.Directory?.Create();

SaveVisualizerLayout(layoutPath.FullName, editorControl.VisualizerLayout);
#pragma warning disable CS0612 // Support for deprecated layout config files
var legacyLayoutPath = new FileInfo(Project.GetLegacyLayoutConfigPath(fileName));
if (legacyLayoutPath.Exists)
{
legacyLayoutPath.Delete();
}
#pragma warning restore CS0612 // Support for deprecated layout config files
}

UpdateWorkflowDirectory(fileName);
Expand Down Expand Up @@ -2303,7 +2248,7 @@ static bool TryGetAssemblyResource(string path, out string assemblyName, out str
{
const char AssemblySeparator = ':';
var separatorIndex = path.IndexOf(AssemblySeparator);
if (separatorIndex >= 0 && !Path.IsPathRooted(path) && path.EndsWith(BonsaiExtension))
if (separatorIndex >= 0 && !Path.IsPathRooted(path) && path.EndsWith(Project.BonsaiExtension))
{
path = Path.ChangeExtension(path, null);
var nameElements = path.Split(new[] { AssemblySeparator }, 2);
Expand Down Expand Up @@ -2811,7 +2756,7 @@ public void ShowDefinition(object component)
extension = provider.FileExtension;
}

var directory = Directory.CreateDirectory(Path.Combine(siteForm.definitionsPath, DefinitionsDirectory));
var directory = Directory.CreateDirectory(Path.Combine(siteForm.definitionsPath, Project.DefinitionsDirectory));
var sourceFile = Path.Combine(directory.FullName, type.FullName + "." + extension);
File.WriteAllText(sourceFile, source);
ScriptEditorLauncher.Launch(siteForm, siteForm.scriptEnvironment.ProjectFileName, sourceFile);
Expand Down
7 changes: 5 additions & 2 deletions Bonsai.Editor/Layout/LayoutHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ namespace Bonsai.Design
{
static class LayoutHelper
{
const string LayoutExtension = ".layout";
static readonly XName XsdAttributeName = ((XNamespace)"http://www.w3.org/2000/xmlns/") + "xsd";
static readonly XName XsiAttributeName = ((XNamespace)"http://www.w3.org/2000/xmlns/") + "xsi";
const string XsdAttributeValue = "http://www.w3.org/2001/XMLSchema";
Expand All @@ -25,9 +24,13 @@ public static VisualizerDialogSettings GetLayoutSettings(this VisualizerLayout v
return visualizerLayout?.DialogSettings.FirstOrDefault(xs => xs.Tag == key || xs.Tag == null);
}

[Obsolete]
public static string GetLayoutPath(string fileName)
{
return Path.ChangeExtension(fileName, Path.GetExtension(fileName) + LayoutExtension);
var newLayoutPath = Editor.Project.GetLayoutConfigPath(fileName);
return File.Exists(newLayoutPath)
? newLayoutPath
: Editor.Project.GetLegacyLayoutConfigPath(fileName);
}

public static void SetLayoutTags(ExpressionBuilderGraph source, VisualizerLayout layout)
Expand Down
105 changes: 105 additions & 0 deletions Bonsai.Editor/Project.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using Bonsai.Design;

namespace Bonsai.Editor
{
static class Project
{
const string DefaultWorkflowNamespace = "Unspecified";
internal const string BonsaiExtension = ".bonsai";
internal const string LayoutFileName = "layout";
internal const string ExtensionsDirectory = "Extensions";
internal const string DefinitionsDirectory = "Definitions";

public static string GetCurrentBaseDirectory()
{
return GetCurrentBaseDirectory(out _);
}

public static string GetCurrentBaseDirectory(out bool currentDirectoryRestricted)
{
var currentDirectory = Path.GetFullPath(Environment.CurrentDirectory).TrimEnd('\\');
var appDomainBaseDirectory = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory).TrimEnd('\\');
currentDirectoryRestricted = currentDirectory == appDomainBaseDirectory;
if (!EditorSettings.IsRunningOnMono)
{
var systemPath = Path.GetFullPath(Environment.GetFolderPath(Environment.SpecialFolder.System)).TrimEnd('\\');
var systemX86Path = Path.GetFullPath(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86)).TrimEnd('\\');
currentDirectoryRestricted |= currentDirectory == systemPath || currentDirectory == systemX86Path;
}

return !currentDirectoryRestricted
? currentDirectory
: Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
}

public static string GetWorkflowBaseDirectory(string fileName)
{
return Path.GetDirectoryName(fileName);
}

public static string GetWorkflowSettingsDirectory(string fileName)
{
return Path.Combine(BonsaiExtension, Path.GetFileNameWithoutExtension(fileName));
}

public static string GetLayoutConfigPath(string fileName)
{
return Path.Combine(GetWorkflowSettingsDirectory(fileName), LayoutFileName);
}

[Obsolete]
internal static string GetLegacyLayoutConfigPath(string fileName)
{
return Path.ChangeExtension(fileName, Path.GetExtension(fileName) + "." + LayoutFileName);
}

internal static string GetDefinitionsTempPath()
{
return Path.Combine(Path.GetTempPath(), DefinitionsDirectory + "." + GuidHelper.GetProcessGuid().ToString());
}

public static IEnumerable<WorkflowElementDescriptor> EnumerateExtensionWorkflows(string basePath)
{
IEnumerable<string> workflowFiles;
try { workflowFiles = Directory.EnumerateFiles(basePath, "*" + BonsaiExtension, SearchOption.AllDirectories); }
catch (UnauthorizedAccessException) { yield break; }
catch (DirectoryNotFoundException) { yield break; }

foreach (var fileName in workflowFiles)
{
var description = string.Empty;
try
{
using var reader = XmlReader.Create(fileName, new XmlReaderSettings { IgnoreWhitespace = true });
reader.ReadStartElement(typeof(WorkflowBuilder).Name);
if (reader.Name == nameof(WorkflowBuilder.Description))
{
reader.ReadStartElement();
description = reader.Value;
}
}
catch (SystemException) { continue; }

var relativePath = PathConvert.GetProjectPath(fileName);
var fileNamespace = Path.GetDirectoryName(relativePath)
.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar)
.Replace(Path.DirectorySeparatorChar, ExpressionHelper.MemberSeparator.First());
if (string.IsNullOrEmpty(fileNamespace)) fileNamespace = DefaultWorkflowNamespace;

yield return new WorkflowElementDescriptor
{
Name = Path.GetFileNameWithoutExtension(relativePath),
Namespace = fileNamespace,
FullyQualifiedName = relativePath,
Description = description,
ElementTypes = new[] { ~ElementCategory.Workflow }
};
}
}
}
}
2 changes: 2 additions & 0 deletions Bonsai.Editor/WorkflowRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ public static void Run(
}

var workflowBuilder = ElementStore.LoadWorkflow(fileName);
#pragma warning disable CS0612 // Support for deprecated layout config files
layoutPath ??= LayoutHelper.GetLayoutPath(fileName);
#pragma warning restore CS0612 // Support for deprecated layout config files
if (visualizerProvider != null && File.Exists(layoutPath))
{
VisualizerLayout layout = null;
Expand Down

0 comments on commit c822587

Please sign in to comment.