Skip to content

Commit 993587d

Browse files
authored
DYN-5862 Python editor docking improvements (#13984)
* Python docking improvements * Update resources * update * Update ScriptEditorWindow.xaml.cs * update CachedEngine when editor engine is changed in docked state * Improvement python editor behavior inside a custom node. * Update DynamoViewModel.cs * Addressing comments * Update PythonNode.cs
1 parent e60d59a commit 993587d

18 files changed

+298
-164
lines changed

src/DynamoCoreWpf/Properties/Resources.Designer.cs

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/DynamoCoreWpf/Properties/Resources.en-US.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2143,7 +2143,7 @@ Do you want to install the latest Dynamo update?</value>
21432143
<value>Write note here</value>
21442144
</data>
21452145
<data name="SideBarPanelViewTitle" xml:space="preserve">
2146-
<value>SideBar Panel</value>
2146+
<value>Sidebar</value>
21472147
</data>
21482148
<data name="ExtensionAdded" xml:space="preserve">
21492149
<value>Extension tab added to the extensions side bar.</value>

src/DynamoCoreWpf/Properties/Resources.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2367,7 +2367,7 @@ Want to publish a different package?</value>
23672367
<value>Write note here</value>
23682368
</data>
23692369
<data name="SideBarPanelViewTitle" xml:space="preserve">
2370-
<value>SideBar Panel</value>
2370+
<value>Sidebar</value>
23712371
</data>
23722372
<data name="ExtensionAdded" xml:space="preserve">
23732373
<value>Extension tab added to the extensions side bar.</value>

src/DynamoCoreWpf/UI/GuidedTour/GuidesValidationMethods.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,14 +577,14 @@ internal static void ExecuteViewDetailsSideBar(Step stepInfo, StepUIAutomation u
577577
if (packageDetailsWindow == null)
578578
return;
579579
//In order to close the Package Details tab we need first to get the Tab, then get the Close button and finally call the event to close it
580-
TabItem tabitem = dynamoView.SideBarPanelTabItems.OfType<TabItem>().SingleOrDefault(n => n.Header.ToString() == packageDetailsName);
580+
TabItem tabitem = stepInfo.DynamoViewModelStep.SideBarTabItems.OfType<TabItem>().SingleOrDefault(n => n.Header.ToString() == packageDetailsName);
581581
if (tabitem == null)
582582
return;
583583
//Get the Close button from the PackageDetailsView
584584
Button closeButton = GuideUtilities.FindChild(tabitem, closeButtonName) as Button;
585585
if (closeButton == null)
586586
return;
587-
dynamoView.OnCloseRightSidePanelTab(closeButton, null);
587+
dynamoView.OnCloseRightSideBarTab(closeButton, null);
588588
}
589589
}
590590

src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Linq;
1010
using System.Reflection;
1111
using System.Windows;
12+
using System.Windows.Controls;
1213
using System.Windows.Forms;
1314
using System.Windows.Media;
1415
using System.Windows.Threading;
@@ -42,6 +43,8 @@
4243
using Dynamo.Wpf.ViewModels.FileTrust;
4344
using Dynamo.Wpf.ViewModels.Watch3D;
4445
using DynamoUtilities;
46+
using ICSharpCode.AvalonEdit;
47+
using PythonNodeModels;
4548
using ISelectable = Dynamo.Selection.ISelectable;
4649
using WpfResources = Dynamo.Wpf.Properties.Resources;
4750

@@ -63,24 +66,40 @@ public partial class DynamoViewModel : ViewModelBase, IDynamoViewModel
6366

6467
// Can the user run the graph
6568
private bool CanRunGraph => HomeSpace.RunSettings.RunEnabled && !HomeSpace.GraphRunInProgress;
66-
6769
private ObservableCollection<DefaultWatch3DViewModel> watch3DViewModels = new ObservableCollection<DefaultWatch3DViewModel>();
70+
private ObservableCollection<TabItem> sideBarTabItems = new ObservableCollection<TabItem>();
6871

6972
/// <summary>
70-
/// An observable collection of workspace view models which tracks the model
73+
/// An observable collection of workspace view models which tracks the model.
7174
/// </summary>
7275
private ObservableCollection<WorkspaceViewModel> workspaces = new ObservableCollection<WorkspaceViewModel>();
7376

7477
/// <summary>
75-
/// Set of node window id's that are currently docked in right side sidebar
78+
/// Set of node window id's that are currently docked in right side sidebar.
7679
/// </summary>
77-
internal HashSet<string> CurrentDockedWindows { get; set; } = new HashSet<string>();
80+
internal HashSet<string> DockedNodeWindows { get; set; } = new HashSet<string>();
7881

7982
/// <summary>
8083
/// Node window's state, either DockRight or FloatingWindow.
8184
/// </summary>
8285
internal Dictionary<string, ViewExtensionDisplayMode> NodeWindowsState { get; set; } = new Dictionary<string, ViewExtensionDisplayMode>();
8386

87+
/// <summary>
88+
/// Collection of Right SideBar tab items: view extensions and docked windows.
89+
/// </summary>
90+
public ObservableCollection<TabItem> SideBarTabItems
91+
{
92+
get
93+
{
94+
return sideBarTabItems;
95+
}
96+
set
97+
{
98+
sideBarTabItems = value;
99+
RaisePropertyChanged(nameof(SideBarTabItems));
100+
}
101+
}
102+
84103
public ObservableCollection<WorkspaceViewModel> Workspaces
85104
{
86105
get { return workspaces; }
@@ -1470,6 +1489,57 @@ internal void AddToRecentFiles(string path)
14701489
}
14711490
}
14721491

1492+
// Get the nodemodel if a node is present in any open workspace.
1493+
internal NodeModel GetDockedWindowNodeModel(string tabId)
1494+
{
1495+
var workspaces = Model.Workspaces;
1496+
NodeModel nodeModel = null;
1497+
1498+
foreach (WorkspaceModel workspace in workspaces)
1499+
{
1500+
nodeModel = workspace.Nodes.FirstOrDefault(x => x.GUID.ToString() == tabId);
1501+
if (nodeModel != null)
1502+
{
1503+
return nodeModel;
1504+
}
1505+
}
1506+
return nodeModel;
1507+
}
1508+
1509+
/// <summary>
1510+
/// Closes any docked python script windows if there are no unsaved changes.
1511+
/// Show warning message on the script editor if it has unsaved changes.
1512+
/// </summary>
1513+
/// <param name="nodes">Nodes in the workspace</param>
1514+
internal bool CanCloseDockedNodeWindows(ObservableCollection<NodeViewModel> nodes)
1515+
{
1516+
foreach (var node in nodes)
1517+
{
1518+
var id = node.NodeModel.GUID.ToString();
1519+
if (DockedNodeWindows.Contains(id))
1520+
{
1521+
var tabItem = SideBarTabItems.OfType<TabItem>().SingleOrDefault(n => n.Uid.ToString() == id);
1522+
NodeModel nodeModel = GetDockedWindowNodeModel(tabItem.Uid);
1523+
1524+
if (nodeModel is PythonNode pythonNode)
1525+
{
1526+
var editor = (tabItem.Content as Grid).ChildOfType<TextEditor>();
1527+
if (editor != null && editor.IsModified)
1528+
{
1529+
pythonNode.OnWarnUserScript();
1530+
tabItem.Focus();
1531+
return false;
1532+
}
1533+
pythonNode.Dispose();
1534+
}
1535+
1536+
SideBarTabItems.Remove(tabItem);
1537+
DockedNodeWindows.Remove(id);
1538+
}
1539+
}
1540+
return true;
1541+
}
1542+
14731543
/// <summary>
14741544
/// Returns the file-save dialog with customized file types of Dynamo.
14751545
/// </summary>

src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,8 +1329,14 @@ private void Hide(object parameters)
13291329
}
13301330
else
13311331
{
1332-
if (!Model.HasUnsavedChanges || DynamoViewModel.AskUserToSaveWorkspaceOrCancel(Model))
1333-
DynamoViewModel.Model.RemoveWorkspace(Model);
1332+
// Close the custom workspace only if all docked node windows are saved and can be closed.
1333+
if (DynamoViewModel.CanCloseDockedNodeWindows(Nodes))
1334+
{
1335+
if (!Model.HasUnsavedChanges || DynamoViewModel.AskUserToSaveWorkspaceOrCancel(Model))
1336+
{
1337+
DynamoViewModel.Model.RemoveWorkspace(Model);
1338+
}
1339+
}
13341340
}
13351341
}
13361342

src/DynamoCoreWpf/Views/Core/DynamoView.xaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,7 @@
15561556
Grid.Row="2"
15571557
Grid.Column="4"
15581558
Grid.RowSpan="2">
1559-
<TabControl Name="tabDynamic" Background="#353535" BorderThickness="0" ItemsSource="{Binding}">
1559+
<TabControl Name="tabDynamic" Background="#353535" BorderThickness="0" ItemsSource="{Binding SideBarTabItems, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
15601560
<TabControl.Resources>
15611561
<!--Styling for the close button in the tab-->
15621562
<Style TargetType="{x:Type Button}"
@@ -1594,11 +1594,11 @@
15941594
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Header}"
15951595
FontFamily="{StaticResource ArtifaktElementBold}"
15961596
FontSize="12"
1597-
Margin="5,5,0,0"
1597+
Margin="5,7,0,0"
15981598
HorizontalAlignment="Stretch"/>
15991599

16001600
<!--Button to close a particular tab-->
1601-
<Button Name="CloseButton" Style="{StaticResource CloseButtonStyle}" DockPanel.Dock="Right" Click="OnCloseRightSidePanelTab"
1601+
<Button Name="CloseButton" Style="{StaticResource CloseButtonStyle}" DockPanel.Dock="Right" Click="OnCloseRightSideBarTab"
16021602
Margin="5,5,5,0" Uid="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Uid}">
16031603
<Image Width="18" Height="18" HorizontalAlignment="Right" VerticalAlignment="Center">
16041604
<Image.Style>
@@ -1618,7 +1618,7 @@
16181618
</Image>
16191619
</Button>
16201620
<!-- Undock -->
1621-
<Button Name="UndockButton" Style="{StaticResource CloseButtonStyle}" DockPanel.Dock="Right" Click="OnUndockRightSidePanelTab"
1621+
<Button Name="UndockButton" Style="{StaticResource CloseButtonStyle}" DockPanel.Dock="Right" Click="OnUndockRightSideBarTab"
16221622
Margin="8,5,0,0" Uid="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Uid}">
16231623
<Image Width="18" Height="18" HorizontalAlignment="Right" VerticalAlignment="Center">
16241624
<Image.Style>

0 commit comments

Comments
 (0)