diff --git a/Bonsai.Editor/EditorForm.Designer.cs b/Bonsai.Editor/EditorForm.Designer.cs index aefbf8a84..4782fdbbc 100644 --- a/Bonsai.Editor/EditorForm.Designer.cs +++ b/Bonsai.Editor/EditorForm.Designer.cs @@ -139,6 +139,8 @@ private void InitializeComponent() this.createGroupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.subscribeSubjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.multicastSubjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.renameSubjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.goToDefinitionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.commandExecutor = new Bonsai.Design.CommandExecutor(); this.workflowFileWatcher = new System.IO.FileSystemWatcher(); this.exportImageDialog = new System.Windows.Forms.SaveFileDialog(); @@ -944,6 +946,7 @@ private void InitializeComponent() this.toolboxTreeView.Size = new System.Drawing.Size(197, 222); this.toolboxTreeView.TabIndex = 0; this.toolboxTreeView.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.toolboxTreeView_ItemDrag); + this.toolboxTreeView.AfterLabelEdit += new System.Windows.Forms.NodeLabelEditEventHandler(this.toolboxTreeView_AfterLabelEdit); this.toolboxTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.toolboxTreeView_AfterSelect); this.toolboxTreeView.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.toolboxTreeView_NodeMouseDoubleClick); this.toolboxTreeView.Enter += new System.EventHandler(this.toolboxTreeView_Enter); @@ -1159,9 +1162,11 @@ private void InitializeComponent() this.createBranchToolStripMenuItem, this.createGroupToolStripMenuItem, this.subscribeSubjectToolStripMenuItem, - this.multicastSubjectToolStripMenuItem}); + this.multicastSubjectToolStripMenuItem, + this.renameSubjectToolStripMenuItem, + this.goToDefinitionToolStripMenuItem}); this.toolboxContextMenuStrip.Name = "toolboxContextMenuStrip"; - this.toolboxContextMenuStrip.Size = new System.Drawing.Size(207, 136); + this.toolboxContextMenuStrip.Size = new System.Drawing.Size(207, 202); // // insertAfterToolStripMenuItem // @@ -1211,6 +1216,22 @@ private void InitializeComponent() this.multicastSubjectToolStripMenuItem.Text = "Multicast"; this.multicastSubjectToolStripMenuItem.Click += new System.EventHandler(this.createGroupToolStripMenuItem_Click); // + // renameSubjectToolStripMenuItem + // + this.renameSubjectToolStripMenuItem.Name = "renameSubjectToolStripMenuItem"; + this.renameSubjectToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F2; + this.renameSubjectToolStripMenuItem.Size = new System.Drawing.Size(206, 22); + this.renameSubjectToolStripMenuItem.Text = "Rename"; + this.renameSubjectToolStripMenuItem.Click += new System.EventHandler(this.renameSubjectToolStripMenuItem_Click); + // + // goToDefinitionToolStripMenuItem + // + this.goToDefinitionToolStripMenuItem.Name = "goToDefinitionToolStripMenuItem"; + this.goToDefinitionToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F12; + this.goToDefinitionToolStripMenuItem.Size = new System.Drawing.Size(206, 22); + this.goToDefinitionToolStripMenuItem.Text = "Go To Definition"; + this.goToDefinitionToolStripMenuItem.Click += new System.EventHandler(this.goToDefinitionToolStripMenuItem_Click); + // // commandExecutor // this.commandExecutor.StatusChanged += new System.EventHandler(this.commandExecutor_StatusChanged); @@ -1368,6 +1389,8 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem createGroupToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem subscribeSubjectToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem multicastSubjectToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem renameSubjectToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem goToDefinitionToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; private System.Windows.Forms.ToolStripMenuItem reloadExtensionsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem reloadExtensionsDebugToolStripMenuItem; diff --git a/Bonsai.Editor/EditorForm.cs b/Bonsai.Editor/EditorForm.cs index d72a46f3f..b27827ecc 100644 --- a/Bonsai.Editor/EditorForm.cs +++ b/Bonsai.Editor/EditorForm.cs @@ -444,7 +444,7 @@ IObservable InitializeSubjectSources() var isEmpty = subjectCategory.Nodes.Count == 0; subjectCategory.Nodes.Clear(); - var nameProperty = TypeDescriptor.GetProperties(typeof(SubscribeSubjectBuilder))["Name"]; + var nameProperty = TypeDescriptor.GetProperties(typeof(SubscribeSubjectBuilder))[nameof(SubscribeSubjectBuilder.Name)]; var subjects = nameProperty.Converter.GetStandardValues(new TypeDescriptorContext(workflowBuilder, nameProperty, editorSite)); if (subjects != null && subjects.Count > 0) { @@ -1452,6 +1452,36 @@ void HandleWorkflowCompleted() else clearErrors(); } + void HighlightDeclaration(WorkflowGraphView workflowView, ExpressionDeclaration declaration) + { + if (workflowView == null) + { + throw new ArgumentNullException(nameof(workflowView)); + } + + var graphNode = workflowView.FindGraphNode(declaration.Value); + if (graphNode != null) + { + workflowView.GraphView.SelectedNode = graphNode; + var nestedDeclaration = declaration.InnerDeclaration; + if (nestedDeclaration != null) + { + workflowView.LaunchWorkflowView(graphNode); + var editorLauncher = workflowView.GetWorkflowEditorLauncher(graphNode); + if (editorLauncher != null) + { + HighlightDeclaration(editorLauncher.WorkflowGraphView, nestedDeclaration); + } + } + else + { + var ownerForm = workflowView.EditorControl.ParentForm; + if (ownerForm != null) ownerForm.Activate(); + workflowView.SelectGraphNode(graphNode); + } + } + } + #endregion #region Workflow Controller @@ -1767,6 +1797,9 @@ private void searchTextBox_KeyDown(object sender, KeyEventArgs e) toolboxTreeView.SelectedNode = toolboxTreeView.SelectedNode.NextVisibleNode ?? toolboxTreeView.SelectedNode; e.Handled = true; break; + case Keys.F2: + toolboxTreeView_KeyDown(sender, e); + break; case Keys.Return: toolboxTreeView_KeyDown(sender, e); searchTextBox.Clear(); @@ -1846,17 +1879,80 @@ void UpdateTreeViewSelection(bool focused) selectedNode.BackColor = focused ? Color.Empty : themeRenderer.ToolStripRenderer.ColorTable.InactiveCaption; } + void SelectTreeViewSubjectNode(string subjectName) + { + var subjectCategory = toolboxCategories[SubjectCategoryName]; + var subjectNode = subjectCategory.Nodes.Find(subjectName, false); + if (subjectNode.Length > 0) + { + toolboxTreeView.SelectedNode = subjectNode[0]; + } + } + private void toolboxTreeView_KeyDown(object sender, KeyEventArgs e) { - if (e.KeyCode == Keys.Return && - toolboxTreeView.SelectedNode != null && - toolboxTreeView.SelectedNode.Tag != null) + var selectedNode = toolboxTreeView.SelectedNode; + if (e.KeyCode == Keys.Return && selectedNode?.Tag != null) { - var typeNode = toolboxTreeView.SelectedNode; - CreateGraphNode(typeNode, e.Modifiers); + CreateGraphNode(selectedNode, e.Modifiers); e.Handled = true; e.SuppressKeyPress = true; } + + var rename = e.KeyCode == Keys.F2; + var goToDefinition = e.KeyCode == Keys.F12; + if ((rename || goToDefinition) && selectedNode?.Tag != null) + { + var elementCategory = WorkflowGraphView.GetToolboxElementCategory(selectedNode); + if (!selectedNode.IsEditing && elementCategory == ~ElementCategory.Source) + { + var currentName = selectedNode.Name; + var selectedView = selectionModel.SelectedView; + var definition = workflowBuilder.GetSubjectDefinition(selectedView.Workflow, currentName); + if (definition == null || rename && definition.IsReadOnly) + { + var message = definition == null + ? Resources.SubjectDefinitionNotFound_Error + : string.Format(Resources.RenameReadOnlySubjectDefinition_Error, currentName); + editorSite.ShowError(message); + return; + } + + if (rename) + { + toolboxTreeView.LabelEdit = true; + selectedNode.BeginEdit(); + } + else + { + var declaration = workflowBuilder.GetDeclaration(definition.Subject); + HighlightDeclaration(editorControl.WorkflowGraphView, declaration); + } + } + } + } + + private void toolboxTreeView_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) + { + e.CancelEdit = true; + + var selectedView = selectionModel.SelectedView; + if (e.Node == null || string.IsNullOrEmpty(e.Label) || selectedView == null) + { + return; + } + + var newName = e.Label; + var currentName = e.Node.Name; + var currentLabel = e.Node.Text; + var definition = workflowBuilder.GetSubjectDefinition(selectedView.Workflow, currentName); + selectedView.Editor.RenameSubject(definition, newName); + e.Node.Name = newName; + e.Node.Text = newName + currentLabel.Substring(currentName.Length); + toolboxTreeView.LabelEdit = false; + searchTextBox.Clear(); + SelectTreeViewSubjectNode(newName); + UpdatePropertyGrid(); } private void toolboxTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) @@ -1893,6 +1989,8 @@ private void toolboxTreeView_MouseUp(object sender, MouseEventArgs e) } subscribeSubjectToolStripMenuItem.Visible = true; multicastSubjectToolStripMenuItem.Visible = true; + renameSubjectToolStripMenuItem.Visible = true; + goToDefinitionToolStripMenuItem.Visible = true; } else { @@ -1908,6 +2006,8 @@ private void toolboxTreeView_MouseUp(object sender, MouseEventArgs e) createGroupToolStripMenuItem.Visible = allowGroup || selectionType != null; subscribeSubjectToolStripMenuItem.Visible = false; multicastSubjectToolStripMenuItem.Visible = false; + renameSubjectToolStripMenuItem.Visible = false; + goToDefinitionToolStripMenuItem.Visible = false; insertBeforeToolStripMenuItem.Visible = true; } toolboxContextMenuStrip.Show(toolboxTreeView, e.X, e.Y); @@ -1946,6 +2046,32 @@ private void createGroupToolStripMenuItem_Click(object sender, EventArgs e) toolboxTreeView_KeyDown(sender, new KeyEventArgs(Keys.Control | Keys.Return)); } + private void renameSubjectToolStripMenuItem_Click(object sender, EventArgs e) + { + if (!toolboxTreeView.Focused) + { + var model = selectionModel.SelectedView; + if (!model.GraphView.Focused) return; + + var selection = selectionModel.SelectedNodes.ToArray(); + var selectedBuilder = selection?.Length == 1 && selection?[0].Value is InspectBuilder inspectBuilder ? inspectBuilder.Builder : null; + if (selectedBuilder is SubjectExpressionBuilder || + selectedBuilder is SubscribeSubjectBuilder || + selectedBuilder is MulticastSubjectBuilder) + { + var subjectName = ((INamedElement)selectedBuilder).Name; + SelectTreeViewSubjectNode(subjectName); + } + } + + toolboxTreeView_KeyDown(sender, new KeyEventArgs(Keys.F2)); + } + + private void goToDefinitionToolStripMenuItem_Click(object sender, EventArgs e) + { + toolboxTreeView_KeyDown(sender, new KeyEventArgs(Keys.F12)); + } + private void MainForm_KeyDown(object sender, KeyEventArgs e) { editorSite.OnKeyDown(e); @@ -2290,6 +2416,7 @@ public void OnKeyDown(KeyEventArgs e) HandleMenuItemShortcutKeys(e, siteForm.startToolStripButtonMenuItem, siteForm.startToolStripMenuItem_Click); HandleMenuItemShortcutKeys(e, siteForm.restartToolStripMenuItem, siteForm.restartToolStripMenuItem_Click); HandleMenuItemShortcutKeys(e, siteForm.stopToolStripMenuItem, siteForm.stopToolStripMenuItem_Click); + HandleMenuItemShortcutKeys(e, siteForm.renameSubjectToolStripMenuItem, siteForm.renameSubjectToolStripMenuItem_Click); } public void OnKeyPress(KeyPressEventArgs e) @@ -2443,6 +2570,19 @@ public bool HasDefinition(object component) public void ShowDefinition(object component) { + if (component is INamedElement namedElement && + (namedElement is SubscribeSubjectBuilder || namedElement is MulticastSubjectBuilder)) + { + var model = siteForm.selectionModel.SelectedView ?? siteForm.editorControl.WorkflowGraphView; + var definition = siteForm.workflowBuilder.GetSubjectDefinition(model.Workflow, namedElement.Name); + if (definition != null) + { + var declaration = siteForm.workflowBuilder.GetDeclaration(definition.Subject); + siteForm.HighlightDeclaration(siteForm.editorControl.WorkflowGraphView, declaration); + return; + } + } + Type componentType; if (siteForm.scriptEnvironment == null) return; if (siteForm.scriptEnvironment.AssemblyName != null && diff --git a/Bonsai.Editor/GraphModel/WorkflowBuilderExtensions.cs b/Bonsai.Editor/GraphModel/WorkflowBuilderExtensions.cs new file mode 100644 index 000000000..074427959 --- /dev/null +++ b/Bonsai.Editor/GraphModel/WorkflowBuilderExtensions.cs @@ -0,0 +1,209 @@ +using System.Collections.Generic; +using System.Linq; +using Bonsai.Expressions; + +namespace Bonsai.Editor.GraphModel +{ + static class WorkflowBuilderExtensions + { + public static bool IsGroup(this IWorkflowExpressionBuilder builder) + { + return builder is IncludeWorkflowBuilder || builder is GroupWorkflowBuilder; + } + + static bool GetCallContext(ExpressionBuilderGraph source, bool readOnly, ExpressionBuilderGraph target, Stack callContext) + { + var context = new ContextGrouping(source, readOnly); + callContext.Push(context); + if (source == target) + { + return true; + } + + foreach (var element in context) + { + var groupBuilder = element.Builder as IWorkflowExpressionBuilder; + if (IsGroup(groupBuilder) && groupBuilder.Workflow == target) + { + return true; + } + + if (element.Builder is WorkflowExpressionBuilder workflowBuilder) + { + if (GetCallContext(workflowBuilder.Workflow, element.IsReadOnly, target, callContext)) + { + return true; + } + } + } + + callContext.Pop(); + return false; + } + + public static SubjectDefinition GetSubjectDefinition(this WorkflowBuilder source, ExpressionBuilderGraph target, string name) + { + var callContext = new Stack(); + if (GetCallContext(source.Workflow, readOnly: false, target, callContext)) + { + return (from level in callContext + from element in level + let subjectBuilder = element.Builder as SubjectExpressionBuilder + where subjectBuilder != null && subjectBuilder.Name == name + select new SubjectDefinition(level, subjectBuilder, element.IsReadOnly)) + .LastOrDefault(); + } + + return null; + } + + public static IEnumerable GetDependentExpressions(this SubjectDefinition source) + { + var callContext = new Stack(); + callContext.Push(source.Root); + + while (callContext.Count > 0) + { + var root = callContext.Pop(); + + var exclude = false; + var snapshot = callContext.Count; + foreach (var element in root) + { + if (element.Builder is SubjectExpressionBuilder subjectDefinition && + subjectDefinition != source.Subject && + subjectDefinition.Name == source.Subject.Name) + { + exclude = true; + while (callContext.Count > snapshot) callContext.Pop(); + break; + } + + if (element.Builder is WorkflowExpressionBuilder workflowBuilder) + { + callContext.Push(new ContextGrouping(workflowBuilder.Workflow, element.IsReadOnly)); + } + } + + if (!exclude) + { + yield return root; + } + } + } + + public static ExpressionDeclaration GetDeclaration(this WorkflowBuilder source, ExpressionBuilder target) + { + return GetDeclaration(source.Workflow, target); + } + + static ExpressionDeclaration GetDeclaration(ExpressionBuilderGraph source, ExpressionBuilder target) + { + foreach (var node in source) + { + var builder = ExpressionBuilder.Unwrap(node.Value); + if (builder == target) + { + return new ExpressionDeclaration(node.Value, innerDeclaration: null); + } + + if (builder is IWorkflowExpressionBuilder workflowBuilder) + { + var innerDeclaration = GetDeclaration(workflowBuilder.Workflow, target); + if (innerDeclaration != null) + { + return new ExpressionDeclaration(node.Value, innerDeclaration); + } + } + } + + return null; + } + } + + class ExpressionDeclaration + { + public ExpressionDeclaration(ExpressionBuilder value, ExpressionDeclaration innerDeclaration) + { + Value = value; + InnerDeclaration = innerDeclaration; + } + + public ExpressionBuilder Value { get; } + + public ExpressionDeclaration InnerDeclaration { get; } + } + + class SubjectDefinition + { + public SubjectDefinition(ContextGrouping root, SubjectExpressionBuilder subject, bool readOnly) + { + Root = root; + Subject = subject; + IsReadOnly = readOnly; + } + + public ContextGrouping Root { get; } + + public SubjectExpressionBuilder Subject { get; } + + public bool IsReadOnly { get; } + } + + struct ContextElement + { + public ExpressionBuilder Builder; + public bool IsReadOnly; + + public ContextElement(ExpressionBuilder element, bool readOnly) + { + Builder = element; + IsReadOnly = readOnly; + } + } + + class ContextGrouping : IGrouping + { + public ContextGrouping(ExpressionBuilderGraph key, bool readOnly) + { + Key = key; + IsReadOnly = readOnly; + Elements = SelectContextElements(key, readOnly); + } + + public ExpressionBuilderGraph Key { get; } + + public bool IsReadOnly { get; } + + IEnumerable Elements { get; } + + public IEnumerator GetEnumerator() + { + return Elements.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + static IEnumerable SelectContextElements(ExpressionBuilderGraph source, bool readOnly) + { + foreach (var node in source) + { + var builder = ExpressionBuilder.Unwrap(node.Value); + yield return new ContextElement(builder, readOnly); + + if (builder is IWorkflowExpressionBuilder workflowBuilder && workflowBuilder.IsGroup()) + { + var workflow = workflowBuilder.Workflow; + if (workflow == null) continue; + foreach (var groupElement in SelectContextElements(workflow, readOnly || workflowBuilder is IncludeWorkflowBuilder)) + { + yield return groupElement; + } + } + } + } + } +} diff --git a/Bonsai.Editor/GraphModel/WorkflowEditor.cs b/Bonsai.Editor/GraphModel/WorkflowEditor.cs index ea5f9a118..59cda57c9 100644 --- a/Bonsai.Editor/GraphModel/WorkflowEditor.cs +++ b/Bonsai.Editor/GraphModel/WorkflowEditor.cs @@ -1,4 +1,4 @@ -using Bonsai.Dag; +using Bonsai.Dag; using Bonsai.Design; using Bonsai.Editor.Properties; using Bonsai.Expressions; @@ -20,6 +20,7 @@ class WorkflowEditor readonly Subject error; readonly Subject updateLayout; readonly Subject updateParentLayout; + readonly Subject invalidateLayout; readonly Subject> updateSelection; readonly Subject closeWorkflowEditor; @@ -31,6 +32,7 @@ public WorkflowEditor(IServiceProvider provider, IGraphView view) error = new Subject(); updateLayout = new Subject(); updateParentLayout = new Subject(); + invalidateLayout = new Subject(); updateSelection = new Subject>(); closeWorkflowEditor = new Subject(); } @@ -43,6 +45,8 @@ public WorkflowEditor(IServiceProvider provider, IGraphView view) public IObservable UpdateParentLayout => updateParentLayout; + public IObservable InvalidateLayout => invalidateLayout; + public IObservable> UpdateSelection => updateSelection; public IObservable CloseWorkflowEditor => closeWorkflowEditor; @@ -93,6 +97,11 @@ private Action CreateUpdateGraphLayoutDelegate() return () => updateLayout.OnNext(true); } + private Action CreateInvalidateGraphLayoutDelegate() + { + return () => invalidateLayout.OnNext(true); + } + private Action CreateUpdateSelectionDelegate() { return CreateUpdateSelectionDelegate(Enumerable.Empty()); @@ -1588,6 +1597,70 @@ public void EnableGraphNodes(IEnumerable nodes) UpdateGraphNodes(nodes, EnableGraphNode); } + public void RenameSubject(SubjectDefinition definition, string newName) + { + if (definition == null) + { + throw new ArgumentNullException(nameof(definition)); + } + + if (definition.IsReadOnly) + { + throw new ArgumentException(Resources.ReadOnlySubjectDefinition_Error, nameof(definition)); + } + + var currentName = definition.Subject.Name; + var subscribeDependents = new List(); + var multicastDependents = new List(); + foreach (var dependent in definition.GetDependentExpressions() + .SelectMany(context => context) + .Where(element => element.Builder is INamedElement namedElement && + namedElement.Name == definition.Subject.Name)) + { + if (dependent.IsReadOnly) continue; + else if (dependent.Builder is SubscribeSubjectBuilder subscribeSubject) + { + subscribeDependents.Add(subscribeSubject); + } + else if (dependent.Builder is MulticastSubjectBuilder multicastSubject) + { + multicastDependents.Add(multicastSubject); + } + } + + var invalidateGraphLayout = CreateInvalidateGraphLayoutDelegate(); + commandExecutor.BeginCompositeCommand(); + commandExecutor.Execute(EmptyAction, invalidateGraphLayout); + commandExecutor.Execute(() => + { + definition.Subject.Name = newName; + foreach (var dependent in subscribeDependents) + { + dependent.Name = newName; + } + + foreach (var dependent in multicastDependents) + { + dependent.Name = newName; + } + }, + () => + { + definition.Subject.Name = currentName; + foreach (var dependent in subscribeDependents) + { + dependent.Name = currentName; + } + + foreach (var dependent in multicastDependents) + { + dependent.Name = currentName; + } + }); + commandExecutor.Execute(invalidateGraphLayout, EmptyAction); + commandExecutor.EndCompositeCommand(); + } + public GraphNode FindGraphNode(ExpressionBuilder value) { return graphView.Nodes.SelectMany(layer => layer).FirstOrDefault(n => n.Value == value); diff --git a/Bonsai.Editor/GraphView/GraphViewControl.cs b/Bonsai.Editor/GraphView/GraphViewControl.cs index 538fd44eb..8ba7b52da 100644 --- a/Bonsai.Editor/GraphView/GraphViewControl.cs +++ b/Bonsai.Editor/GraphView/GraphViewControl.cs @@ -326,6 +326,21 @@ void InvalidateSelection() } } + public override void Refresh() + { + using (var graphics = CreateGraphics()) + { + foreach (var layout in layoutNodes) + { + if (layout.Text != layout.Node.Text) + { + layout.SetNodeLabel(layout.Node.Text, Font, graphics); + } + } + } + base.Refresh(); + } + public void Invalidate(GraphNode node) { if (node != null && layoutNodes.Contains(node)) diff --git a/Bonsai.Editor/GraphView/WorkflowGraphView.cs b/Bonsai.Editor/GraphView/WorkflowGraphView.cs index 69f135984..49751182f 100644 --- a/Bonsai.Editor/GraphView/WorkflowGraphView.cs +++ b/Bonsai.Editor/GraphView/WorkflowGraphView.cs @@ -371,13 +371,18 @@ internal void SelectBuilderNode(ExpressionBuilder builder) var graphNode = FindGraphNode(builder); if (graphNode != null) { - GraphView.SelectedNode = graphNode; - EditorControl.SelectTab(this); - GraphView.Select(); - UpdateSelection(); + SelectGraphNode(graphNode); } } + internal void SelectGraphNode(GraphNode node) + { + GraphView.SelectedNode = node; + EditorControl.SelectTab(this); + GraphView.Select(); + UpdateSelection(); + } + private bool HasDefaultEditor(ExpressionBuilder builder) { if (builder is IWorkflowExpressionBuilder) return true; @@ -797,6 +802,19 @@ private void UpdateGraphLayout(bool validateWorkflow) UpdateSelection(); } + private void InvalidateGraphLayout(bool validateWorkflow) + { + graphView.Refresh(); + if (Launcher != null) + { + Launcher.ParentView.InvalidateGraphLayout(validateWorkflow); + } + else if (validateWorkflow) + { + editorService.ValidateWorkflow(); + } + } + #endregion #region Controller @@ -1251,6 +1269,12 @@ private void InitializeViewBindings() } }); + Editor.InvalidateLayout.Subscribe(validateWorkflow => + { + if (Launcher != null) Launcher.WorkflowGraphView.InvalidateGraphLayout(validateWorkflow); + else InvalidateGraphLayout(validateWorkflow); + }); + Editor.UpdateSelection.Subscribe(selection => { var activeView = Launcher != null ? Launcher.WorkflowGraphView.GraphView : graphView; diff --git a/Bonsai.Editor/Properties/Resources.Designer.cs b/Bonsai.Editor/Properties/Resources.Designer.cs index 7d533524d..8687cea6d 100644 --- a/Bonsai.Editor/Properties/Resources.Designer.cs +++ b/Bonsai.Editor/Properties/Resources.Designer.cs @@ -1,578 +1,605 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bonsai.Editor.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bonsai.Editor.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to - ///The Bonsai framework includes software from the Reactive Extensions for .NET and the NuGet projects developed at the .NET Foundation (https://dotnetfoundation.org/). - /// - ///Copyright (c) .NET Foundation and Contributors. - /// - internal static string AttributionNotices { - get { - return ResourceManager.GetString("AttributionNotices", resourceCulture); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Bonsai { - get { - object obj = ResourceManager.GetObject("Bonsai", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized string similar to Bonsai. - /// - internal static string BonsaiTitle { - get { - return ResourceManager.GetString("BonsaiTitle", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Build Error. - /// - internal static string BuildError_Caption { - get { - return ResourceManager.GetString("BuildError_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to None. - /// - internal static string ContextMenu_NoneMenuItemLabel { - get { - return ResourceManager.GetString("ContextMenu_NoneMenuItemLabel", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error copying the selected elements to the clipboard: - ///{0}. - /// - internal static string CopyToClipboard_Error { - get { - return ResourceManager.GetString("CopyToClipboard_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Extensions folder does not exist in the current working directory. Do you want to create it?. - /// - internal static string CreateExtensionsFolder_Question { - get { - return ResourceManager.GetString("CreateExtensionsFolder_Question", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Create Extensions Folder. - /// - internal static string CreateExtensionsFolder_Question_Caption { - get { - return ResourceManager.GetString("CreateExtensionsFolder_Question_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The workflow must be saved before adding new extensions.. - /// - internal static string CreateExtensionsWorkflow_Warning { - get { - return ResourceManager.GetString("CreateExtensionsWorkflow_Warning", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Save Workflow. - /// - internal static string CreateExtensionsWorkflow_Warning_Caption { - get { - return ResourceManager.GetString("CreateExtensionsWorkflow_Warning_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Create Group. - /// - internal static string CreateGroupAction { - get { - return ResourceManager.GetString("CreateGroupAction", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Create Source. - /// - internal static string CreateSourceMenuItemLabel { - get { - return ResourceManager.GetString("CreateSourceMenuItemLabel", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to create {0}: - ///{1}. - /// - internal static string CreateTypeNode_Error { - get { - return ResourceManager.GetString("CreateTypeNode_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Editor Error. - /// - internal static string Editor_Error_Caption { - get { - return ResourceManager.GetString("Editor_Error_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The workflow needs to be saved before proceeding. Do you want to save the workflow?. - /// - internal static string EnsureSavedWorkflow_Question { - get { - return ResourceManager.GetString("EnsureSavedWorkflow_Question", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Exception builder node not found in active workflow editor.. - /// - internal static string ExceptionNodeNotFound_Error { - get { - return ResourceManager.GetString("ExceptionNodeNotFound_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to group broken branches.. - /// - internal static string GroupBrokenBranches_Error { - get { - return ResourceManager.GetString("GroupBrokenBranches_Error", resourceCulture); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). - /// - internal static System.Drawing.Icon Icon { - get { - object obj = ResourceManager.GetObject("Icon", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// Looks up a localized string similar to Connecting the target nodes in the specified order would create a loop in the workflow. Consider inserting the operator as a branch.. - /// - internal static string InsertValidation_Error { - get { - return ResourceManager.GetString("InsertValidation_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to open script editor. - ///Do you want to install Visual Studio Code? - /// - ///NOTE: You will have to restart Bonsai for any changes to take effect.. - /// - internal static string InstallScriptEditor_Question { - get { - return ResourceManager.GetString("InstallScriptEditor_Question", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Install Script Editor. - /// - internal static string InstallScriptEditor_Question_Caption { - get { - return ResourceManager.GetString("InstallScriptEditor_Question_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The specified type is not a workflow expression builder.. - /// - internal static string InvalidExpressionBuilderType_Error { - get { - return ResourceManager.GetString("InvalidExpressionBuilderType_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Replaced node must be workflow expression builder.. - /// - internal static string InvalidReplaceGroupNode_Error { - get { - return ResourceManager.GetString("InvalidReplaceGroupNode_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error opening the workflow {0}: - ///{1}. - /// - internal static string OpenWorkflow_Error { - get { - return ResourceManager.GetString("OpenWorkflow_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Open Error. - /// - internal static string OpenWorkflow_Error_Caption { - get { - return ResourceManager.GetString("OpenWorkflow_Error_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Output. - /// - internal static string OutputMenuItemLabel { - get { - return ResourceManager.GetString("OutputMenuItemLabel", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Package updates are available. - /// - internal static string PackageUpdatesAvailable_Notification { - get { - return ResourceManager.GetString("PackageUpdatesAvailable_Notification", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error pasting the selected elements from the clipboard: - ///{0}. - /// - internal static string PasteFromClipboard_Error { - get { - return ResourceManager.GetString("PasteFromClipboard_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Ready. - /// - internal static string ReadyStatus { - get { - return ResourceManager.GetString("ReadyStatus", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The file "{0}" does not exist anymore. Do you want to remove the reference to it from the list of recent files?. - /// - internal static string RemoveRecentFile_Question { - get { - return ResourceManager.GetString("RemoveRecentFile_Question", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Bonsai. - /// - internal static string RemoveRecentFile_Question_Caption { - get { - return ResourceManager.GetString("RemoveRecentFile_Question_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error while reordering the selected nodes: - ///{0}. - /// - internal static string ReorderGraphNodes_Error { - get { - return ResourceManager.GetString("ReorderGraphNodes_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Running. - /// - internal static string RunningStatus { - get { - return ResourceManager.GetString("RunningStatus", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Runtime Error. - /// - internal static string RuntimeError_Caption { - get { - return ResourceManager.GetString("RuntimeError_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Save Error. - /// - internal static string SaveElement_Error_Caption { - get { - return ResourceManager.GetString("SaveElement_Error_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error saving the visualizer layout: - ///{0}. - /// - internal static string SaveLayout_Error { - get { - return ResourceManager.GetString("SaveLayout_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error saving the Bonsai workflow: - ///{0}. - /// - internal static string SaveWorkflow_Error { - get { - return ResourceManager.GetString("SaveWorkflow_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Search Modules (Ctrl+E). - /// - internal static string SearchModuleCueBanner { - get { - return ResourceManager.GetString("SearchModuleCueBanner", resourceCulture); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap StatusBlockedImage { - get { - object obj = ResourceManager.GetObject("StatusBlockedImage", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap StatusCriticalImage { - get { - object obj = ResourceManager.GetObject("StatusCriticalImage", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap StatusReadyImage { - get { - object obj = ResourceManager.GetObject("StatusReadyImage", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap StatusRunningImage { - get { - object obj = ResourceManager.GetObject("StatusRunningImage", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap StatusUpdateAvailable { - get { - object obj = ResourceManager.GetObject("StatusUpdateAvailable", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized string similar to Do you want to stop the workflow?. - /// - internal static string StopWorkflow_Question { - get { - return ResourceManager.GetString("StopWorkflow_Question", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Workflow Running. - /// - internal static string StopWorkflow_Question_Caption { - get { - return ResourceManager.GetString("StopWorkflow_Question_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Subject Type. - /// - internal static string SubjectTypeAction { - get { - return ResourceManager.GetString("SubjectTypeAction", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The specified type could not be found.. - /// - internal static string TypeNotFound_Error { - get { - return ResourceManager.GetString("TypeNotFound_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to evaluate uncompiled script expression. Please ensure all script files have been created and reload extensions.. - /// - internal static string UncompiledScriptExpression_Error { - get { - return ResourceManager.GetString("UncompiledScriptExpression_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Workflow has unsaved changes. Save project file?. - /// - internal static string UnsavedWorkflow_Question { - get { - return ResourceManager.GetString("UnsavedWorkflow_Question", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unsaved Changes. - /// - internal static string UnsavedWorkflow_Question_Caption { - get { - return ResourceManager.GetString("UnsavedWorkflow_Question_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was an error while updating the workflow. Please check if there are any missing packages that need to be installed before trying to upgrade again.. - /// - internal static string UpdateWorkflow_Error { - get { - return ResourceManager.GetString("UpdateWorkflow_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to This workflow file has been created with an older version of Bonsai. Further modifications will be incompatible with previous versions.. - /// - internal static string UpdateWorkflow_Warning { - get { - return ResourceManager.GetString("UpdateWorkflow_Warning", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Update Workflow. - /// - internal static string UpdateWorkflow_Warning_Caption { - get { - return ResourceManager.GetString("UpdateWorkflow_Warning_Caption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set visualizer layout with a null workflow.. - /// - internal static string VisualizerLayoutOnNullWorkflow_Error { - get { - return ResourceManager.GetString("VisualizerLayoutOnNullWorkflow_Error", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Externalized properties of this workflow can be configured below.. - /// - internal static string WorkflowPropertiesDescription { - get { - return ResourceManager.GetString("WorkflowPropertiesDescription", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Bonsai.Editor.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bonsai.Editor.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to + ///The Bonsai framework includes software from the Reactive Extensions for .NET and the NuGet projects developed at the .NET Foundation (https://dotnetfoundation.org/). + /// + ///Copyright (c) .NET Foundation and Contributors. + /// + internal static string AttributionNotices { + get { + return ResourceManager.GetString("AttributionNotices", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Bonsai { + get { + object obj = ResourceManager.GetObject("Bonsai", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized string similar to Bonsai. + /// + internal static string BonsaiTitle { + get { + return ResourceManager.GetString("BonsaiTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Build Error. + /// + internal static string BuildError_Caption { + get { + return ResourceManager.GetString("BuildError_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to None. + /// + internal static string ContextMenu_NoneMenuItemLabel { + get { + return ResourceManager.GetString("ContextMenu_NoneMenuItemLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error copying the selected elements to the clipboard: + ///{0}. + /// + internal static string CopyToClipboard_Error { + get { + return ResourceManager.GetString("CopyToClipboard_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Extensions folder does not exist in the current working directory. Do you want to create it?. + /// + internal static string CreateExtensionsFolder_Question { + get { + return ResourceManager.GetString("CreateExtensionsFolder_Question", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create Extensions Folder. + /// + internal static string CreateExtensionsFolder_Question_Caption { + get { + return ResourceManager.GetString("CreateExtensionsFolder_Question_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The workflow must be saved before adding new extensions.. + /// + internal static string CreateExtensionsWorkflow_Warning { + get { + return ResourceManager.GetString("CreateExtensionsWorkflow_Warning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save Workflow. + /// + internal static string CreateExtensionsWorkflow_Warning_Caption { + get { + return ResourceManager.GetString("CreateExtensionsWorkflow_Warning_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create Group. + /// + internal static string CreateGroupAction { + get { + return ResourceManager.GetString("CreateGroupAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create Source. + /// + internal static string CreateSourceMenuItemLabel { + get { + return ResourceManager.GetString("CreateSourceMenuItemLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to create {0}: + ///{1}. + /// + internal static string CreateTypeNode_Error { + get { + return ResourceManager.GetString("CreateTypeNode_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Editor Error. + /// + internal static string Editor_Error_Caption { + get { + return ResourceManager.GetString("Editor_Error_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The workflow needs to be saved before proceeding. Do you want to save the workflow?. + /// + internal static string EnsureSavedWorkflow_Question { + get { + return ResourceManager.GetString("EnsureSavedWorkflow_Question", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Exception builder node not found in active workflow editor.. + /// + internal static string ExceptionNodeNotFound_Error { + get { + return ResourceManager.GetString("ExceptionNodeNotFound_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to group broken branches.. + /// + internal static string GroupBrokenBranches_Error { + get { + return ResourceManager.GetString("GroupBrokenBranches_Error", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon Icon { + get { + object obj = ResourceManager.GetObject("Icon", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// Looks up a localized string similar to Connecting the target nodes in the specified order would create a loop in the workflow. Consider inserting the operator as a branch.. + /// + internal static string InsertValidation_Error { + get { + return ResourceManager.GetString("InsertValidation_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to open script editor. + ///Do you want to install Visual Studio Code? + /// + ///NOTE: You will have to restart Bonsai for any changes to take effect.. + /// + internal static string InstallScriptEditor_Question { + get { + return ResourceManager.GetString("InstallScriptEditor_Question", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Install Script Editor. + /// + internal static string InstallScriptEditor_Question_Caption { + get { + return ResourceManager.GetString("InstallScriptEditor_Question_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified type is not a workflow expression builder.. + /// + internal static string InvalidExpressionBuilderType_Error { + get { + return ResourceManager.GetString("InvalidExpressionBuilderType_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Replaced node must be workflow expression builder.. + /// + internal static string InvalidReplaceGroupNode_Error { + get { + return ResourceManager.GetString("InvalidReplaceGroupNode_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error opening the workflow {0}: + ///{1}. + /// + internal static string OpenWorkflow_Error { + get { + return ResourceManager.GetString("OpenWorkflow_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open Error. + /// + internal static string OpenWorkflow_Error_Caption { + get { + return ResourceManager.GetString("OpenWorkflow_Error_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Output. + /// + internal static string OutputMenuItemLabel { + get { + return ResourceManager.GetString("OutputMenuItemLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Package updates are available. + /// + internal static string PackageUpdatesAvailable_Notification { + get { + return ResourceManager.GetString("PackageUpdatesAvailable_Notification", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error pasting the selected elements from the clipboard: + ///{0}. + /// + internal static string PasteFromClipboard_Error { + get { + return ResourceManager.GetString("PasteFromClipboard_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified subject definition is read-only.. + /// + internal static string ReadOnlySubjectDefinition_Error { + get { + return ResourceManager.GetString("ReadOnlySubjectDefinition_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ready. + /// + internal static string ReadyStatus { + get { + return ResourceManager.GetString("ReadyStatus", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The file "{0}" does not exist anymore. Do you want to remove the reference to it from the list of recent files?. + /// + internal static string RemoveRecentFile_Question { + get { + return ResourceManager.GetString("RemoveRecentFile_Question", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bonsai. + /// + internal static string RemoveRecentFile_Question_Caption { + get { + return ResourceManager.GetString("RemoveRecentFile_Question_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The definition of {0} is read-only and cannot be renamed.. + /// + internal static string RenameReadOnlySubjectDefinition_Error { + get { + return ResourceManager.GetString("RenameReadOnlySubjectDefinition_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error while reordering the selected nodes: + ///{0}. + /// + internal static string ReorderGraphNodes_Error { + get { + return ResourceManager.GetString("ReorderGraphNodes_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Running. + /// + internal static string RunningStatus { + get { + return ResourceManager.GetString("RunningStatus", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Runtime Error. + /// + internal static string RuntimeError_Caption { + get { + return ResourceManager.GetString("RuntimeError_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save Error. + /// + internal static string SaveElement_Error_Caption { + get { + return ResourceManager.GetString("SaveElement_Error_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error saving the visualizer layout: + ///{0}. + /// + internal static string SaveLayout_Error { + get { + return ResourceManager.GetString("SaveLayout_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error saving the Bonsai workflow: + ///{0}. + /// + internal static string SaveWorkflow_Error { + get { + return ResourceManager.GetString("SaveWorkflow_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Search Modules (Ctrl+E). + /// + internal static string SearchModuleCueBanner { + get { + return ResourceManager.GetString("SearchModuleCueBanner", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap StatusBlockedImage { + get { + object obj = ResourceManager.GetObject("StatusBlockedImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap StatusCriticalImage { + get { + object obj = ResourceManager.GetObject("StatusCriticalImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap StatusReadyImage { + get { + object obj = ResourceManager.GetObject("StatusReadyImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap StatusRunningImage { + get { + object obj = ResourceManager.GetObject("StatusRunningImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap StatusUpdateAvailable { + get { + object obj = ResourceManager.GetObject("StatusUpdateAvailable", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized string similar to Do you want to stop the workflow?. + /// + internal static string StopWorkflow_Question { + get { + return ResourceManager.GetString("StopWorkflow_Question", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Workflow Running. + /// + internal static string StopWorkflow_Question_Caption { + get { + return ResourceManager.GetString("StopWorkflow_Question_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified subject definition could not be found.. + /// + internal static string SubjectDefinitionNotFound_Error { + get { + return ResourceManager.GetString("SubjectDefinitionNotFound_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Subject Type. + /// + internal static string SubjectTypeAction { + get { + return ResourceManager.GetString("SubjectTypeAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified type could not be found.. + /// + internal static string TypeNotFound_Error { + get { + return ResourceManager.GetString("TypeNotFound_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to evaluate uncompiled script expression. Please ensure all script files have been created and reload extensions.. + /// + internal static string UncompiledScriptExpression_Error { + get { + return ResourceManager.GetString("UncompiledScriptExpression_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Workflow has unsaved changes. Save project file?. + /// + internal static string UnsavedWorkflow_Question { + get { + return ResourceManager.GetString("UnsavedWorkflow_Question", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unsaved Changes. + /// + internal static string UnsavedWorkflow_Question_Caption { + get { + return ResourceManager.GetString("UnsavedWorkflow_Question_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error while updating the workflow. Please check if there are any missing packages that need to be installed before trying to upgrade again.. + /// + internal static string UpdateWorkflow_Error { + get { + return ResourceManager.GetString("UpdateWorkflow_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This workflow file has been created with an older version of Bonsai. Further modifications will be incompatible with previous versions.. + /// + internal static string UpdateWorkflow_Warning { + get { + return ResourceManager.GetString("UpdateWorkflow_Warning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update Workflow. + /// + internal static string UpdateWorkflow_Warning_Caption { + get { + return ResourceManager.GetString("UpdateWorkflow_Warning_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set visualizer layout with a null workflow.. + /// + internal static string VisualizerLayoutOnNullWorkflow_Error { + get { + return ResourceManager.GetString("VisualizerLayoutOnNullWorkflow_Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Externalized properties of this workflow can be configured below.. + /// + internal static string WorkflowPropertiesDescription { + get { + return ResourceManager.GetString("WorkflowPropertiesDescription", resourceCulture); + } + } + } +} diff --git a/Bonsai.Editor/Properties/Resources.resx b/Bonsai.Editor/Properties/Resources.resx index 591f44367..0c53dc87f 100644 --- a/Bonsai.Editor/Properties/Resources.resx +++ b/Bonsai.Editor/Properties/Resources.resx @@ -329,4 +329,13 @@ NOTE: You will have to restart Bonsai for any changes to take effect. Output + + The specified subject definition is read-only. + + + The definition of {0} is read-only and cannot be renamed. + + + The specified subject definition could not be found. + \ No newline at end of file