diff --git a/TuneUp/Properties/Resources.Designer.cs b/TuneUp/Properties/Resources.Designer.cs
index 703ee9e..5830686 100644
--- a/TuneUp/Properties/Resources.Designer.cs
+++ b/TuneUp/Properties/Resources.Designer.cs
@@ -349,6 +349,15 @@ public static string ToolTip_RunAll {
}
}
+ ///
+ /// Looks up a localized string similar to Custom Node mode does not support Run All..
+ ///
+ public static string ToolTip_RunAllDisabled {
+ get {
+ return ResourceManager.GetString("ToolTip_RunAllDisabled", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Combined execution time of latest and previous run..
///
diff --git a/TuneUp/Properties/Resources.en-US.resx b/TuneUp/Properties/Resources.en-US.resx
index 89cb216..43272a2 100644
--- a/TuneUp/Properties/Resources.en-US.resx
+++ b/TuneUp/Properties/Resources.en-US.resx
@@ -214,6 +214,9 @@
Execute entire graph, including nodes with no change since the latest run.
+
+ Custom Node mode does not support Run All.
+
Combined execution time of latest and previous run.
diff --git a/TuneUp/Properties/Resources.resx b/TuneUp/Properties/Resources.resx
index 813b0d5..ec2a143 100644
--- a/TuneUp/Properties/Resources.resx
+++ b/TuneUp/Properties/Resources.resx
@@ -214,6 +214,9 @@
Execute entire graph, including nodes with no change since the latest run.
+
+ Custom Node mode does not support Run All.
+
Combined execution time of latest and previous run.
diff --git a/TuneUp/TuneUpWindow.xaml b/TuneUp/TuneUpWindow.xaml
index 26b05f8..e840a62 100644
--- a/TuneUp/TuneUpWindow.xaml
+++ b/TuneUp/TuneUpWindow.xaml
@@ -345,6 +345,9 @@
+
+
+
@@ -483,10 +486,11 @@
Content="{x:Static resx:Resources.Button_RunAll}"
Cursor="Hand"
IsEnabled="{Binding Path=IsRecomputeEnabled}"
- Style="{StaticResource ButtonStyleTuneUp}" >
+ Style="{StaticResource ButtonStyleTuneUp}"
+ ToolTipService.ShowOnDisabled="True" >
-
+
diff --git a/TuneUp/TuneUpWindowViewModel.cs b/TuneUp/TuneUpWindowViewModel.cs
index 2c1ceba..27de2a2 100644
--- a/TuneUp/TuneUpWindowViewModel.cs
+++ b/TuneUp/TuneUpWindowViewModel.cs
@@ -79,6 +79,9 @@ public class TuneUpWindowViewModel : NotificationObject, IDisposable
private HashSet tempProfiledNodesLatestRun = new HashSet();
private HashSet tempProfiledNodesPreviousRun = new HashSet();
private HashSet tempProfiledNodesNotExecuted = new HashSet();
+ private bool suppressNodeReset = false;
+ private IWorkspaceModel previousWorkspace;
+ private readonly WorkspaceProfilingData cachedData = new WorkspaceProfilingData();
private HomeWorkspaceModel CurrentWorkspace
{
@@ -121,6 +124,7 @@ private set
{
isRecomputeEnabled = value;
RaisePropertyChanged(nameof(IsRecomputeEnabled));
+ RaisePropertyChanged(nameof(RunAllTooltipMessage));
}
}
}
@@ -281,6 +285,7 @@ public string SortingOrder
public const string SortByName = "name";
public const string SortByNumber = "number";
public const string SortByTime = "time";
+ public string RunAllTooltipMessage => IsRecomputeEnabled ? Resources.ToolTip_RunAll : Resources.ToolTip_RunAllDisabled;
#endregion
@@ -315,6 +320,14 @@ internal void ResetProfiledNodes()
Task.Run(() =>
{
uiContext.Post(_ => {
+ if (suppressNodeReset)
+ {
+ // Skip resetting nodes and directly refresh the UI
+ isProfilingEnabled = true;
+ RefreshUIAfterReset();
+ return;
+ }
+
// Initialize collections and dictionaries
InitializeCollectionsAndDictionaries();
@@ -1013,8 +1026,36 @@ private void CurrentWorkspaceModel_GroupRemoved(AnnotationModel group)
private void OnCurrentWorkspaceChanged(IWorkspaceModel workspace)
{
- // Profiling needs to be enabled per workspace so mark it false after switching
+ // Reset suppression flag
+ suppressNodeReset = false;
+
+ // Handle transitions based on the types of the current and previous workspaces
+ if (workspace is CustomNodeWorkspaceModel)
+ {
+ if (previousWorkspace is HomeWorkspaceModel)
+ {
+ // Cache data when moving from HomeWorkspace to CustomNodeWorkspace
+ CacheWorkspaceData();
+ }
+ }
+ else if (workspace is HomeWorkspaceModel)
+ {
+ if (previousWorkspace is CustomNodeWorkspaceModel)
+ {
+ // Restore data when moving from CustomNodeWorkspace to HomeWorkspace
+ suppressNodeReset = true;
+ RestoreWorkspaceData();
+ }
+ }
+
+ // Profiling needs to be enabled per workspace, so mark it false after switching
isProfilingEnabled = false;
+
+ // Disable IsRecomputeEnabled if the workspace is a CustomNodeWorkspaceModel
+ IsRecomputeEnabled = !(workspace is CustomNodeWorkspaceModel);
+
+ // Update the previous and current workspace references
+ previousWorkspace = workspace;
CurrentWorkspace = workspace as HomeWorkspaceModel;
}
@@ -1022,11 +1063,127 @@ private void OnCurrentWorkspaceCleared(IWorkspaceModel workspace)
{
// Profiling needs to be enabled per workspace so mark it false after closing
isProfilingEnabled = false;
+ suppressNodeReset = false;
+ ClearCacheWorkspaceData();
CurrentWorkspace = viewLoadedParams.CurrentWorkspaceModel as HomeWorkspaceModel;
}
#endregion
+ #region Cache
+
+ ///
+ /// Represents cached profiling data for a workspace. Includes node collections and execution times.
+ ///
+ private class WorkspaceProfilingData
+ {
+ ///
+ /// Guid to map graphs with cached data
+ ///
+ public Guid GraphGuid { get; set; }
+ ///
+ /// Collection to cache nodes executed in the latest run of the graph.
+ ///
+ public ObservableCollection LatestRunNodes { get; set; } = new();
+ ///
+ /// Collection to cache nodes executed in the previous run of the graph.
+ ///
+ public ObservableCollection PreviousRunNodes { get; set; } = new();
+ //
+ /// Collection to cache nodes that were not executed in the graph.
+ ///
+ public ObservableCollection NotExecutedNodes { get; set; } = new();
+ ///
+ /// String to cache the Total execution time for the graph across all runs.
+ ///
+ public string TotalGraphExecutionTime { get; set; }
+ ///
+ /// String to cache the Execution time for the latest graph run.
+ ///
+ public string LatestGraphExecutionTime { get; set; }
+ ///
+ /// String to cache the Execution time for the previous graph run.
+ ///
+ public string PreviousGraphExecutionTime { get; set; }
+ }
+
+ ///
+ /// Caches the current workspace data, including nodes, execution times, and clears old collections.
+ ///
+ private void CacheWorkspaceData()
+ {
+ // Ensure collections are initialized
+ if (ProfiledNodesLatestRun == null)
+ ProfiledNodesLatestRun = new ObservableCollection();
+ if (ProfiledNodesPreviousRun == null)
+ ProfiledNodesPreviousRun = new ObservableCollection();
+ if (ProfiledNodesNotExecuted == null)
+ ProfiledNodesNotExecuted = new ObservableCollection();
+
+ // Save the current data into the cache
+ cachedData.GraphGuid = CurrentWorkspace?.Guid ?? Guid.Empty;
+ cachedData.LatestRunNodes = new ObservableCollection(ProfiledNodesLatestRun);
+ cachedData.PreviousRunNodes = new ObservableCollection(ProfiledNodesPreviousRun);
+ cachedData.NotExecutedNodes = new ObservableCollection(ProfiledNodesNotExecuted);
+ cachedData.LatestGraphExecutionTime = LatestGraphExecutionTime ?? Resources.Label_DefaultExecutionTime;
+ cachedData.PreviousGraphExecutionTime = PreviousGraphExecutionTime ?? Resources.Label_DefaultExecutionTime;
+ cachedData.TotalGraphExecutionTime = TotalGraphExecutionTime ?? Resources.Label_DefaultExecutionTime;
+
+ // Clear the old collections
+ ProfiledNodesLatestRun.Clear();
+ ProfiledNodesPreviousRun.Clear();
+ ProfiledNodesNotExecuted.Clear();
+ LatestGraphExecutionTime = PreviousGraphExecutionTime = TotalGraphExecutionTime = defaultExecutionTime;
+
+ // Refresh the UI
+ RefreshAllCollectionViews();
+ UpdateTableVisibility();
+ }
+
+ ///
+ /// Restores cached workspace data to the current workspace and updates the UI.
+ ///
+ private void RestoreWorkspaceData()
+ {
+ // Safety check: Ensure cached data is not null
+ cachedData.LatestRunNodes ??= new ObservableCollection();
+ cachedData.PreviousRunNodes ??= new ObservableCollection();
+ cachedData.NotExecutedNodes ??= new ObservableCollection();
+ cachedData.LatestGraphExecutionTime ??= Resources.Label_DefaultExecutionTime;
+ cachedData.PreviousGraphExecutionTime ??= Resources.Label_DefaultExecutionTime;
+ cachedData.TotalGraphExecutionTime ??= Resources.Label_DefaultExecutionTime;
+
+ // Restore cached data
+ ProfiledNodesLatestRun = new ObservableCollection(cachedData.LatestRunNodes);
+ ProfiledNodesPreviousRun = new ObservableCollection(cachedData.PreviousRunNodes);
+ ProfiledNodesNotExecuted = new ObservableCollection(cachedData.NotExecutedNodes);
+ LatestGraphExecutionTime = cachedData.LatestGraphExecutionTime;
+ PreviousGraphExecutionTime = cachedData.PreviousGraphExecutionTime;
+ TotalGraphExecutionTime = cachedData.TotalGraphExecutionTime;
+
+ ClearCacheWorkspaceData();
+
+ // Refresh the UI
+ RefreshAllCollectionViews();
+ UpdateTableVisibility();
+ }
+
+ ///
+ /// Clears the cached workspace data, resetting all collections and execution times to default values.
+ ///
+ private void ClearCacheWorkspaceData()
+ {
+ cachedData.GraphGuid = Guid.Empty;
+ cachedData.LatestRunNodes = new ObservableCollection();
+ cachedData.PreviousRunNodes = new ObservableCollection();
+ cachedData.NotExecutedNodes = new ObservableCollection();
+ cachedData.LatestGraphExecutionTime = defaultExecutionTime;
+ cachedData.PreviousGraphExecutionTime = defaultExecutionTime;
+ cachedData.TotalGraphExecutionTime = defaultExecutionTime;
+ }
+
+ #endregion
+
#region Helpers
///
@@ -1214,11 +1371,7 @@ public void ApplyCustomSortingToAllCollections()
{
ApplyCustomSorting(ProfiledNodesCollectionLatestRun);
ApplyCustomSorting(ProfiledNodesCollectionPreviousRun);
- // Apply custom sorting to NotExecuted collection only if sortingOrder is "name"
- if (defaultSortingOrder == SortByName)
- {
- ApplyCustomSorting(ProfiledNodesCollectionNotExecuted);
- }
+ ApplyCustomSorting(ProfiledNodesCollectionNotExecuted, SortByName);
}
///
@@ -1377,8 +1530,12 @@ private void RefreshUIAfterReset()
ProfiledNodesCollectionNotExecuted = new CollectionViewSource { Source = ProfiledNodesNotExecuted };
// Refresh UI by raising property changes and applying sorting/filtering
+ RaisePropertyChanged(nameof(ProfiledNodesCollectionLatestRun));
+ RaisePropertyChanged(nameof(ProfiledNodesCollectionPreviousRun));
RaisePropertyChanged(nameof(ProfiledNodesCollectionNotExecuted));
- ApplyCustomSorting(ProfiledNodesCollectionNotExecuted, SortByName);
+
+ ApplyCustomSortingToAllCollections();
+
ApplyGroupNodeFilter();
UpdateTableVisibility();
}