From 6167f92db3e6fcb622fc6b7d37e141814431c4a8 Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" Date: Sun, 21 Jan 2024 22:23:05 -0500 Subject: [PATCH 01/13] Open Template UI change --- src/DynamoCore/Configuration/IPathResolver.cs | 5 ++ src/DynamoCore/Configuration/PathManager.cs | 49 +++++++++++++++- .../Properties/Resources.Designer.cs | 18 ++++++ .../Properties/Resources.en-US.resx | 8 ++- src/DynamoCoreWpf/Properties/Resources.resx | 6 ++ .../ViewModels/Core/DynamoViewModel.cs | 56 +++++++++++++++++++ .../Core/DynamoViewModelDelegateCommands.cs | 3 + src/DynamoCoreWpf/Views/Core/DynamoView.xaml | 17 +++++- .../Views/Core/DynamoView.xaml.cs | 2 +- 9 files changed, 158 insertions(+), 6 deletions(-) diff --git a/src/DynamoCore/Configuration/IPathResolver.cs b/src/DynamoCore/Configuration/IPathResolver.cs index 5273787238a..a2d7b854bbd 100644 --- a/src/DynamoCore/Configuration/IPathResolver.cs +++ b/src/DynamoCore/Configuration/IPathResolver.cs @@ -156,6 +156,11 @@ public interface IPathManager /// string SamplesDirectory { get; } + /// + /// The root directory where all template files are stored + /// + string TemplatesDirectory { get; } + /// /// The directory where the automatically saved files will be stored. /// diff --git a/src/DynamoCore/Configuration/PathManager.cs b/src/DynamoCore/Configuration/PathManager.cs index 6a794e8ab04..2c6a27e32a6 100644 --- a/src/DynamoCore/Configuration/PathManager.cs +++ b/src/DynamoCore/Configuration/PathManager.cs @@ -66,6 +66,7 @@ internal static Lazy public const string ViewExtensionsDirectoryName = "viewExtensions"; public const string DefinitionsDirectoryName = "definitions"; public const string SamplesDirectoryName = "samples"; + public const string TemplateDirectoryName = "templates"; public const string BackupDirectoryName = "backup"; public const string PreferenceSettingsFileName = "DynamoSettings.xml"; public const string PythonTemplateFileName = "PythonTemplate.py"; @@ -82,6 +83,7 @@ internal static Lazy private string commonPackages; private string logDirectory; private string samplesDirectory; + private string templatesDirectory; private string backupDirectory; private string defaultBackupDirectory; private string preferenceFilePath; @@ -240,6 +242,11 @@ public string SamplesDirectory get { return samplesDirectory; } } + public string TemplatesDirectory + { + get { return templatesDirectory; } + } + public string BackupDirectory { get { return backupDirectory; } @@ -572,6 +579,7 @@ private void BuildCommonDirectories() commonDefinitions = Path.Combine(commonDataDir, DefinitionsDirectoryName); commonPackages = Path.Combine(commonDataDir, PackagesDirectoryName); samplesDirectory = GetSamplesFolder(commonDataDir); + templatesDirectory = GetTemplateFolder(commonDataDir); rootDirectories = new List { userDataDir }; @@ -715,7 +723,46 @@ private static string GetSamplesFolder(string dataRootDirectory) return sampleDirectory; } - + + private string GetTemplateFolder(string dataRootDirectory) + { + var versionedDirectory = dataRootDirectory; + if (!Directory.Exists(versionedDirectory)) + { + // Try to see if folder "%ProgramData%\{...}\{major}.{minor}" exists, if it + // does not, then root directory would be "%ProgramData%\{...}". + // + dataRootDirectory = Directory.GetParent(versionedDirectory).FullName; + } + else if (!Directory.Exists(Path.Combine(versionedDirectory, TemplateDirectoryName))) + { + // If the folder "%ProgramData%\{...}\{major}.{minor}" exists, then try to see + // if the folder "%ProgramData%\{...}\{major}.{minor}\samples" exists. If it + // doesn't exist, then root directory would be "%ProgramData%\{...}". + // + dataRootDirectory = Directory.GetParent(versionedDirectory).FullName; + } + + var uiCulture = CultureInfo.CurrentUICulture.Name; + var templateDirectory = Path.Combine(dataRootDirectory, TemplateDirectoryName, uiCulture); + + // If the localized template directory does not exist then fall back + // to using the en-US template folder. Do an additional check to see + // if the localized folder is available but is empty. + // + var di = new DirectoryInfo(templateDirectory); + if (!Directory.Exists(templateDirectory) || + !di.GetDirectories().Any() || + !di.GetFiles("*.dyn", SearchOption.AllDirectories).Any()) + { + var neturalCommonTemplates = Path.Combine(dataRootDirectory, TemplateDirectoryName, "en-US"); + if (Directory.Exists(neturalCommonTemplates)) + templateDirectory = neturalCommonTemplates; + } + + return templateDirectory; + } + private IEnumerable LibrarySearchPaths(string library) { // Strip out possible directory from library path. diff --git a/src/DynamoCoreWpf/Properties/Resources.Designer.cs b/src/DynamoCoreWpf/Properties/Resources.Designer.cs index d92937d20cd..41adea8c7f1 100644 --- a/src/DynamoCoreWpf/Properties/Resources.Designer.cs +++ b/src/DynamoCoreWpf/Properties/Resources.Designer.cs @@ -1801,6 +1801,24 @@ public static string DynamoViewFileMenuOpen { } } + /// + /// Looks up a localized string similar to _File. + /// + public static string DynamoViewFileMenuOpenFile { + get { + return ResourceManager.GetString("DynamoViewFileMenuOpenFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _Template. + /// + public static string DynamoViewFileMenuOpenTemplate { + get { + return ResourceManager.GetString("DynamoViewFileMenuOpenTemplate", resourceCulture); + } + } + /// /// Looks up a localized string similar to Open _Recent Files. /// diff --git a/src/DynamoCoreWpf/Properties/Resources.en-US.resx b/src/DynamoCoreWpf/Properties/Resources.en-US.resx index 96504e3ea82..50aecc3915e 100644 --- a/src/DynamoCoreWpf/Properties/Resources.en-US.resx +++ b/src/DynamoCoreWpf/Properties/Resources.en-US.resx @@ -3900,4 +3900,10 @@ In certain complex graphs or host program scenarios, Automatic mode may cause in Your changes will be lost if you proceed. - + + _File + + + _Template + + \ No newline at end of file diff --git a/src/DynamoCoreWpf/Properties/Resources.resx b/src/DynamoCoreWpf/Properties/Resources.resx index 23d8634ccaa..c03ab3f6e93 100644 --- a/src/DynamoCoreWpf/Properties/Resources.resx +++ b/src/DynamoCoreWpf/Properties/Resources.resx @@ -3887,4 +3887,10 @@ In certain complex graphs or host program scenarios, Automatic mode may cause in Your changes will be lost if you proceed. + + _File + + + _Template + \ No newline at end of file diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 3a9f5248f07..7e993e1ead6 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -1939,6 +1939,62 @@ private void ShowOpenDialogAndOpenResult(object parameter) private bool CanShowOpenDialogAndOpenResultCommand(object parameter) => CanRunGraph; + /// + /// Present the open dialog and open the template that is selected. + /// + /// + private void ShowOpenTemplateDialog(object parameter) + { + if (HomeSpace.HasUnsavedChanges) + { + if (!AskUserToSaveWorkspaceOrCancel(HomeSpace)) + return; + } + + DynamoOpenFileDialog _fileDialog = new DynamoOpenFileDialog(this) + { + Filter = string.Format(Resources.FileDialogDynamoDefinitions, + BrandingResourceProvider.ProductName, "*.dyn;*.dyf") + "|" + + string.Format(Resources.FileDialogAllFiles, "*.*"), + Title = string.Format(Resources.OpenDynamoDefinitionDialogTitle, BrandingResourceProvider.ProductName) + }; + + // if you've got the current space path, use it as the inital dir + if (!string.IsNullOrEmpty(Model.PathManager.TemplatesDirectory)) + { + string path = Model.PathManager.TemplatesDirectory; + if (Directory.Exists(path)) + { + var di = new DirectoryInfo(Model.PathManager.TemplatesDirectory); + _fileDialog.InitialDirectory = di.FullName; + } + else + { + _fileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); + } + } + else // use the samples directory, if it exists + { + Assembly dynamoAssembly = Assembly.GetExecutingAssembly(); + string location = Path.GetDirectoryName(dynamoAssembly.Location); + string UICulture = CultureInfo.CurrentUICulture.Name; + string path = Path.Combine(location, "samples", UICulture); + + if (Directory.Exists(path)) + _fileDialog.InitialDirectory = path; + } + + if (_fileDialog.ShowDialog() == DialogResult.OK) + { + if (CanOpen(_fileDialog.FileName)) + { + // Replace with the template file opening API which does not modify the template file + Open(new Tuple(_fileDialog.FileName, _fileDialog.RunManualMode)); + } + } + } + + private bool CanShowOpenTemplateDialog(object parameter) => CanRunGraph; /// /// Present the open dialog and open the workspace that is selected. diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs index b8b4a4d1e6b..5200db6e86a 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs @@ -18,6 +18,7 @@ private void InitializeDelegateCommands() SaveCommand = new DelegateCommand(Save, CanSave); SaveAsCommand = new DelegateCommand(SaveAs, CanSaveAs); ShowOpenDialogAndOpenResultCommand = new DelegateCommand(ShowOpenDialogAndOpenResult, CanShowOpenDialogAndOpenResultCommand); + ShowOpenTemplateDialogCommand = new DelegateCommand(ShowOpenTemplateDialog, CanShowOpenTemplateDialog); ShowInsertDialogAndInsertResultCommand = new DelegateCommand(ShowInsertDialogAndInsertResult, CanShowInsertDialogAndInsertResultCommand); ShowSaveDialogAndSaveResultCommand = new DelegateCommand(ShowSaveDialogAndSaveResult, CanShowSaveDialogAndSaveResult); ShowSaveDialogIfNeededAndSaveResultCommand = new DelegateCommand(ShowSaveDialogIfNeededAndSaveResult, CanShowSaveDialogIfNeededAndSaveResultCommand); @@ -98,6 +99,8 @@ private void InitializeDelegateCommands() public DelegateCommand OpenIfSavedCommand { get; set; } public DelegateCommand OpenCommand { get; set; } public DelegateCommand ShowOpenDialogAndOpenResultCommand { get; set; } + public DelegateCommand ShowOpenTemplateDialogCommand { get; set; } + public DelegateCommand ShowInsertDialogAndInsertResultCommand { get; set; } public DelegateCommand WriteToLogCmd { get; set; } public DelegateCommand PostUiActivationCommand { get; set; } diff --git a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml index 3824a34408b..c90ecc59fe7 100644 --- a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml +++ b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml @@ -112,6 +112,9 @@ + @@ -334,9 +337,17 @@ + Name="openButton"> + + + + Date: Tue, 23 Jan 2024 00:04:29 -0500 Subject: [PATCH 02/13] Add more functions for template opening --- src/DynamoCore/Models/DynamoModel.cs | 25 ++++++ src/DynamoCore/Models/DynamoModelCommands.cs | 9 ++ src/DynamoCore/Models/RecordableCommands.cs | 16 +++- .../ViewModels/Core/DynamoViewModel.cs | 88 ++++++++++++++++++- 4 files changed, 134 insertions(+), 4 deletions(-) diff --git a/src/DynamoCore/Models/DynamoModel.cs b/src/DynamoCore/Models/DynamoModel.cs index 27c372b4fd3..ae1fc0f69de 100644 --- a/src/DynamoCore/Models/DynamoModel.cs +++ b/src/DynamoCore/Models/DynamoModel.cs @@ -1962,6 +1962,31 @@ public void OpenFileFromPath(string filePath, bool forceManualExecutionMode = fa } } + /// + /// Opens a Dynamo workspace from a path to a template on disk. + /// + /// Path to file + /// Set this to true to discard + /// execution mode specified in the file and set manual mode + /// Set this to true to indicate that the file is a template + public void OpenTemplateFromPath(string filePath, bool forceManualExecutionMode = false, bool isTemplate = false) + { + + if (DynamoUtilities.PathHelper.isValidJson(filePath, out string fileContents, out Exception ex)) + { + OpenJsonFileFromPath(fileContents, filePath, forceManualExecutionMode); + return; + } + else + { + // These kind of exceptions indicate that file is not accessible + if (ex is IOException || ex is UnauthorizedAccessException || ex is JsonReaderException) + { + throw ex; + } + } + } + /// /// Inserts a Dynamo graph or Custom Node inside the current workspace from a file path /// diff --git a/src/DynamoCore/Models/DynamoModelCommands.cs b/src/DynamoCore/Models/DynamoModelCommands.cs index b2259ab6ca7..90bb70fc25a 100644 --- a/src/DynamoCore/Models/DynamoModelCommands.cs +++ b/src/DynamoCore/Models/DynamoModelCommands.cs @@ -46,12 +46,21 @@ protected virtual void OpenFileImpl(OpenFileCommand command) { string filePath = command.FilePath; bool forceManualMode = command.ForceManualExecutionMode; + bool isTemplate = command.IsTemplate; OpenFileFromPath(filePath, forceManualMode); //clear the clipboard to avoid copying between dyns //ClipBoard.Clear(); } + protected virtual void OpenTemplateImpl(OpenFileCommand command) + { + string filePath = command.FilePath; + bool forceManualMode = command.ForceManualExecutionMode; + bool isTemplate = command.IsTemplate; + OpenTemplateFromPath(filePath, forceManualMode, isTemplate); + } + protected virtual void OpenFileFromJsonImpl(OpenFileFromJsonCommand command) { string fileContents = command.FileContents; diff --git a/src/DynamoCore/Models/RecordableCommands.cs b/src/DynamoCore/Models/RecordableCommands.cs index 44355e6cf15..af0232dd2e4 100644 --- a/src/DynamoCore/Models/RecordableCommands.cs +++ b/src/DynamoCore/Models/RecordableCommands.cs @@ -458,14 +458,16 @@ public class OpenFileCommand : RecordableCommand #region Public Class Methods /// - /// + /// Constructor /// /// The path to the file. /// Should the file be opened in manual execution mode? - public OpenFileCommand(string filePath, bool forceManualExecutionMode = false) + /// Is Dynamo opening a template file? + public OpenFileCommand(string filePath, bool forceManualExecutionMode = false, bool isTemplate = false) { FilePath = filePath; ForceManualExecutionMode = forceManualExecutionMode; + IsTemplate = isTemplate; } private static string TryFindFile(string xmlFilePath, string uriString = null) @@ -507,6 +509,7 @@ internal static OpenFileCommand DeserializeCore(XmlElement element) [DataMember] internal string FilePath { get; private set; } internal bool ForceManualExecutionMode { get; private set; } + internal bool IsTemplate { get; private set; } private DynamoModel dynamoModel; #endregion @@ -516,7 +519,14 @@ internal static OpenFileCommand DeserializeCore(XmlElement element) protected override void ExecuteCore(DynamoModel dynamoModel) { this.dynamoModel = dynamoModel; - dynamoModel.OpenFileImpl(this); + if (IsTemplate) + { + dynamoModel.OpenTemplateImpl(this); + } + else + { + dynamoModel.OpenFileImpl(this); + } } protected override void SerializeCore(XmlElement element) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 7e993e1ead6..52790a0d5df 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -1743,6 +1743,92 @@ private void Open(object parameters) this.ShowStartPage = false; // Hide start page if there's one. } + /// + /// Open a definition or workspace temlate. + /// For most cases, parameters variable refers to the file path to open + /// However, when this command is used in OpenFileDialog, the variable is + /// a Tuple{string, bool} instead. The boolean flag is used to override the + /// RunSetting of the workspace. + /// + /// + private void OpenTemplate(object parameters) + { + // try catch for exceptions thrown while opening files, say from a future version, + // that can't be handled reliably + filePath = string.Empty; + fileContents = string.Empty; + bool forceManualMode = false; + try + { + if (parameters is Tuple packedParams) + { + filePath = packedParams.Item1; + forceManualMode = packedParams.Item2; + } + else + { + filePath = parameters as string; + } + + var directoryName = Path.GetDirectoryName(filePath); + + // Display trust warning when file is not among trust location and warning feature is on + bool displayTrustWarning = !PreferenceSettings.IsTrustedLocation(directoryName) + && !filePath.EndsWith("dyf") + && !DynamoModel.IsTestMode + && !PreferenceSettings.DisableTrustWarnings + && FileTrustViewModel != null; + RunSettings.ForceBlockRun = displayTrustWarning; + // Execute graph open command + ExecuteCommand(new DynamoModel.OpenFileCommand(filePath, forceManualMode, true)); + // Only show trust warning popop when current opened workspace is homeworkspace and not custom node workspace + if (displayTrustWarning && (currentWorkspaceViewModel?.IsHomeSpace ?? false)) + { + // Skip these when opening dyf + FileTrustViewModel.DynFileDirectoryName = directoryName; + FileTrustViewModel.ShowWarningPopup = true; + (HomeSpaceViewModel as HomeWorkspaceViewModel).UpdateRunStatusMsgBasedOnStates(); + FileTrustViewModel.AllowOneTimeTrust = false; + } + } + catch (Exception e) + { + if (!DynamoModel.IsTestMode) + { + string commandString = String.Format(Resources.MessageErrorOpeningFileGeneral); + string errorMsgString; + // Catch all the IO exceptions and file access here. The message provided by .Net is clear enough to indicate the problem in this case. + if (e is IOException || e is UnauthorizedAccessException) + { + errorMsgString = String.Format(e.Message, filePath); + } + else if (e is System.Xml.XmlException || e is Newtonsoft.Json.JsonReaderException) + { + errorMsgString = String.Format(Resources.MessageFailedToOpenCorruptedFile, filePath); + } + else + { + errorMsgString = String.Format(Resources.MessageUnkownErrorOpeningFile, filePath); + } + model.Logger.LogNotification("Dynamo", commandString, errorMsgString, e.ToString()); + MessageBoxService.Show( + Owner, + errorMsgString, + commandString, + MessageBoxButton.OK, + MessageBoxImage.Error); + } + else + { +#pragma warning disable CA2200 // Rethrow to preserve stack details + throw e; +#pragma warning restore CA2200 // Rethrow to preserve stack details + } + return; + } + this.ShowStartPage = false; // Hide start page if there's one. + } + /// /// Insert a definition or a custom node. /// For most cases, parameters variable refers to the file path to open @@ -1989,7 +2075,7 @@ private void ShowOpenTemplateDialog(object parameter) if (CanOpen(_fileDialog.FileName)) { // Replace with the template file opening API which does not modify the template file - Open(new Tuple(_fileDialog.FileName, _fileDialog.RunManualMode)); + OpenTemplate(new Tuple(_fileDialog.FileName, _fileDialog.RunManualMode)); } } } From f466988a776f06671eb8a363015c99b3c1be33b3 Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Tue, 23 Jan 2024 13:56:21 -0500 Subject: [PATCH 03/13] add comments --- src/DynamoCore/Configuration/PathManager.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/DynamoCore/Configuration/PathManager.cs b/src/DynamoCore/Configuration/PathManager.cs index 2c6a27e32a6..1e3649483b1 100644 --- a/src/DynamoCore/Configuration/PathManager.cs +++ b/src/DynamoCore/Configuration/PathManager.cs @@ -242,6 +242,9 @@ public string SamplesDirectory get { return samplesDirectory; } } + /// + /// Dynamo Templates folder + /// public string TemplatesDirectory { get { return templatesDirectory; } @@ -724,6 +727,11 @@ private static string GetSamplesFolder(string dataRootDirectory) return sampleDirectory; } + /// + /// Get template folder path from common data directory + /// + /// + /// private string GetTemplateFolder(string dataRootDirectory) { var versionedDirectory = dataRootDirectory; @@ -737,7 +745,7 @@ private string GetTemplateFolder(string dataRootDirectory) else if (!Directory.Exists(Path.Combine(versionedDirectory, TemplateDirectoryName))) { // If the folder "%ProgramData%\{...}\{major}.{minor}" exists, then try to see - // if the folder "%ProgramData%\{...}\{major}.{minor}\samples" exists. If it + // if the folder "%ProgramData%\{...}\{major}.{minor}\templates" exists. If it // doesn't exist, then root directory would be "%ProgramData%\{...}". // dataRootDirectory = Directory.GetParent(versionedDirectory).FullName; From 38ff940a75901973285cb310e05f365f4af6b878 Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Tue, 23 Jan 2024 14:19:57 -0500 Subject: [PATCH 04/13] reuse open function --- .../ViewModels/Core/DynamoViewModel.cs | 100 ++---------------- 1 file changed, 11 insertions(+), 89 deletions(-) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 2bb2d03796a..92db8e6b799 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -1686,8 +1686,9 @@ private void OpenFromJson(object parameters) /// Open a definition or workspace. /// For most cases, parameters variable refers to the file path to open /// However, when this command is used in OpenFileDialog, the variable is - /// a Tuple{string, bool} instead. The boolean flag is used to override the - /// RunSetting of the workspace. + /// a Tuple{string, bool} instead. When this command is used in OpenTemplateDialog, + /// the variable is a Tuple{string, bool} instead. The second boolean flag is + /// used to override the RunSetting of the workspace. /// /// private void Open(object parameters) @@ -1696,7 +1697,8 @@ private void Open(object parameters) // that can't be handled reliably filePath = string.Empty; fileContents = string.Empty; - bool forceManualMode = false; + bool forceManualMode = false; + bool isTemplate = false; try { if (parameters is Tuple packedParams) @@ -1704,91 +1706,11 @@ private void Open(object parameters) filePath = packedParams.Item1; forceManualMode = packedParams.Item2; } - else - { - filePath = parameters as string; - } - - var directoryName = Path.GetDirectoryName(filePath); - - // Display trust warning when file is not among trust location and warning feature is on - bool displayTrustWarning = !PreferenceSettings.IsTrustedLocation(directoryName) - && !filePath.EndsWith("dyf") - && !DynamoModel.IsTestMode - && !PreferenceSettings.DisableTrustWarnings - && FileTrustViewModel != null; - RunSettings.ForceBlockRun = displayTrustWarning; - // Execute graph open command - ExecuteCommand(new DynamoModel.OpenFileCommand(filePath, forceManualMode)); - // Only show trust warning popop when current opened workspace is homeworkspace and not custom node workspace - if (displayTrustWarning && (currentWorkspaceViewModel?.IsHomeSpace ?? false)) - { - // Skip these when opening dyf - FileTrustViewModel.DynFileDirectoryName = directoryName; - FileTrustViewModel.ShowWarningPopup = true; - (HomeSpaceViewModel as HomeWorkspaceViewModel).UpdateRunStatusMsgBasedOnStates(); - FileTrustViewModel.AllowOneTimeTrust = false; - } - } - catch (Exception e) - { - if (!DynamoModel.IsTestMode) - { - string commandString = String.Format(Resources.MessageErrorOpeningFileGeneral); - string errorMsgString; - // Catch all the IO exceptions and file access here. The message provided by .Net is clear enough to indicate the problem in this case. - if (e is IOException || e is UnauthorizedAccessException) - { - errorMsgString = String.Format(e.Message, filePath); - } - else if (e is System.Xml.XmlException || e is Newtonsoft.Json.JsonReaderException) - { - errorMsgString = String.Format(Resources.MessageFailedToOpenCorruptedFile, filePath); - } - else - { - errorMsgString = String.Format(Resources.MessageUnkownErrorOpeningFile, filePath); - } - model.Logger.LogNotification("Dynamo", commandString, errorMsgString, e.ToString()); - MessageBoxService.Show( - Owner, - errorMsgString, - commandString, - MessageBoxButton.OK, - MessageBoxImage.Error); - } - else + else if (parameters is Tuple tupleParams) { -#pragma warning disable CA2200 // Rethrow to preserve stack details - throw e; -#pragma warning restore CA2200 // Rethrow to preserve stack details - } - return; - } - this.ShowStartPage = false; // Hide start page if there's one. - } - - /// - /// Open a definition or workspace temlate. - /// For most cases, parameters variable refers to the file path to open - /// However, when this command is used in OpenFileDialog, the variable is - /// a Tuple{string, bool} instead. The boolean flag is used to override the - /// RunSetting of the workspace. - /// - /// - private void OpenTemplate(object parameters) - { - // try catch for exceptions thrown while opening files, say from a future version, - // that can't be handled reliably - filePath = string.Empty; - fileContents = string.Empty; - bool forceManualMode = false; - try - { - if (parameters is Tuple packedParams) - { - filePath = packedParams.Item1; - forceManualMode = packedParams.Item2; + filePath = tupleParams.Item1; + forceManualMode = tupleParams.Item2; + isTemplate = tupleParams.Item3; } else { @@ -1805,7 +1727,7 @@ private void OpenTemplate(object parameters) && FileTrustViewModel != null; RunSettings.ForceBlockRun = displayTrustWarning; // Execute graph open command - ExecuteCommand(new DynamoModel.OpenFileCommand(filePath, forceManualMode, true)); + ExecuteCommand(new DynamoModel.OpenFileCommand(filePath, forceManualMode, isTemplate)); // Only show trust warning popop when current opened workspace is homeworkspace and not custom node workspace if (displayTrustWarning && (currentWorkspaceViewModel?.IsHomeSpace ?? false)) { @@ -2100,7 +2022,7 @@ private void ShowOpenTemplateDialog(object parameter) if (CanOpen(_fileDialog.FileName)) { // Replace with the template file opening API which does not modify the template file - OpenTemplate(new Tuple(_fileDialog.FileName, _fileDialog.RunManualMode)); + Open(new Tuple(_fileDialog.FileName, _fileDialog.RunManualMode, true)); } } } From fda213183018e7dc7efe4fe92d064bd89b28ce9f Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Tue, 23 Jan 2024 15:36:26 -0500 Subject: [PATCH 05/13] Open Template with FileName as empty --- src/DynamoCore/Models/DynamoModel.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/DynamoCore/Models/DynamoModel.cs b/src/DynamoCore/Models/DynamoModel.cs index 0b3eef20561..942f14bd1a5 100644 --- a/src/DynamoCore/Models/DynamoModel.cs +++ b/src/DynamoCore/Models/DynamoModel.cs @@ -1969,7 +1969,7 @@ public void OpenTemplateFromPath(string filePath, bool forceManualExecutionMode if (DynamoUtilities.PathHelper.isValidJson(filePath, out string fileContents, out Exception ex)) { - OpenJsonFileFromPath(fileContents, filePath, forceManualExecutionMode); + OpenJsonFileFromPath(fileContents, filePath, forceManualExecutionMode, isTemplate); return; } else @@ -2053,8 +2053,9 @@ static private DynamoPreferencesData DynamoPreferencesDataFromJson(string json) /// Path to file /// Set this to true to discard /// execution mode specified in the file and set manual mode + /// Set this to true to indicate that the file is a template /// True if workspace was opened successfully - private bool OpenJsonFileFromPath(string fileContents, string filePath, bool forceManualExecutionMode) + private bool OpenJsonFileFromPath(string fileContents, string filePath, bool forceManualExecutionMode, bool isTemplate = false) { try { @@ -2065,7 +2066,7 @@ private bool OpenJsonFileFromPath(string fileContents, string filePath, bool for if (true) //MigrationManager.ProcessWorkspace(dynamoPreferences.Version, xmlDoc, IsTestMode, NodeFactory)) { WorkspaceModel ws; - if (OpenJsonFile(filePath, fileContents, dynamoPreferences, forceManualExecutionMode, out ws)) + if (OpenJsonFile(filePath, fileContents, dynamoPreferences, forceManualExecutionMode, isTemplate, out ws)) { OpenWorkspace(ws); //Raise an event to deserialize the view parameters before @@ -2101,7 +2102,7 @@ private bool InsertJsonFileFromPath(string fileContents, string filePath, bool f { if (true) //MigrationManager.ProcessWorkspace(dynamoPreferences.Version, xmlDoc, IsTestMode, NodeFactory)) { - if (OpenJsonFile(filePath, fileContents, dynamoPreferences, forceManualExecutionMode, out WorkspaceModel ws)) + if (OpenJsonFile(filePath, fileContents, dynamoPreferences, forceManualExecutionMode, false, out WorkspaceModel ws)) { ExtraWorkspaceViewInfo viewInfo = ExtraWorkspaceViewInfo.ExtraWorkspaceViewInfoFromJson(fileContents); @@ -2293,6 +2294,7 @@ private bool OpenJsonFile( string fileContents, DynamoPreferencesData dynamoPreferences, bool forceManualExecutionMode, + bool isTemplate, out WorkspaceModel workspace) { if (!string.IsNullOrEmpty(filePath)) @@ -2320,7 +2322,7 @@ private bool OpenJsonFile( CustomNodeManager, this.LinterManager); - workspace.FileName = string.IsNullOrEmpty(filePath) ? "" : filePath; + workspace.FileName = string.IsNullOrEmpty(filePath) || isTemplate? "" : filePath; workspace.FromJsonGraphId = string.IsNullOrEmpty(filePath) ? WorkspaceModel.ComputeGraphIdFromJson(fileContents) : ""; workspace.ScaleFactor = dynamoPreferences.ScaleFactor; From 6d9009e1f56b8d5a23d8c755f5cdf8a048d69bac Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Wed, 24 Jan 2024 16:48:36 -0500 Subject: [PATCH 06/13] Give user notification --- src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 92db8e6b799..3d913660a4a 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -2182,7 +2182,16 @@ private void InternalSaveAs(string path, SaveContext saveContext, bool isBackup try { Model.Logger.Log(string.Format(Properties.Resources.SavingInProgress, path)); - var hasSaved = CurrentSpaceViewModel.Save(path, isBackup, Model.EngineController, saveContext); + var hasSaved = false; + if (path.Contains(Model.PathManager.TemplatesDirectory)) + { + // Give user notifications + MainGuideManager.CreateRealTimeInfoWindow("Workspaces cannot be saved to the Templates folder. Please choose a different folder to save your file."); + } + else + { + hasSaved = CurrentSpaceViewModel.Save(path, isBackup, Model.EngineController, saveContext); + } if (!isBackup && hasSaved) { From fad47ec211c1011218010fb166b8582caba4b723 Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Thu, 25 Jan 2024 18:11:05 -0500 Subject: [PATCH 07/13] Add message confirmation --- .../Properties/Resources.Designer.cs | 18 ++++++++++++++++++ .../Properties/Resources.en-US.resx | 6 ++++++ src/DynamoCoreWpf/Properties/Resources.resx | 6 ++++++ .../ViewModels/Core/DynamoViewModel.cs | 4 +++- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/DynamoCoreWpf/Properties/Resources.Designer.cs b/src/DynamoCoreWpf/Properties/Resources.Designer.cs index 89f0ee8d621..4a2d17e80b2 100644 --- a/src/DynamoCoreWpf/Properties/Resources.Designer.cs +++ b/src/DynamoCoreWpf/Properties/Resources.Designer.cs @@ -10161,6 +10161,24 @@ public static string WebView2RequiredTitle { } } + /// + /// Looks up a localized string similar to Workspaces cannot be saved to the Templates folder. Please choose a different folder to save your file.. + /// + public static string WorkspaceSaveTemplateDirectoryBlockMsg { + get { + return ResourceManager.GetString("WorkspaceSaveTemplateDirectoryBlockMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid Save Path. + /// + public static string WorkspaceSaveTemplateDirectoryBlockTitle { + get { + return ResourceManager.GetString("WorkspaceSaveTemplateDirectoryBlockTitle", resourceCulture); + } + } + /// /// Looks up a localized string similar to You haven't saved this file yet.. /// diff --git a/src/DynamoCoreWpf/Properties/Resources.en-US.resx b/src/DynamoCoreWpf/Properties/Resources.en-US.resx index f3e1beb6b85..02c8c5c4e8a 100644 --- a/src/DynamoCoreWpf/Properties/Resources.en-US.resx +++ b/src/DynamoCoreWpf/Properties/Resources.en-US.resx @@ -3906,4 +3906,10 @@ In certain complex graphs or host program scenarios, Automatic mode may cause in _Template + + Workspaces cannot be saved to the Templates folder. Please choose a different folder to save your file. + + + Invalid Save Path + \ No newline at end of file diff --git a/src/DynamoCoreWpf/Properties/Resources.resx b/src/DynamoCoreWpf/Properties/Resources.resx index b4d8ddd7675..7179ad5159b 100644 --- a/src/DynamoCoreWpf/Properties/Resources.resx +++ b/src/DynamoCoreWpf/Properties/Resources.resx @@ -3893,4 +3893,10 @@ In certain complex graphs or host program scenarios, Automatic mode may cause in _Template + + Workspaces cannot be saved to the Templates folder. Please choose a different folder to save your file. + + + Invalid Save Path + \ No newline at end of file diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 3d913660a4a..9bb02e3d363 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -47,6 +47,7 @@ using DynamoUtilities; using ICSharpCode.AvalonEdit; using PythonNodeModels; +using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip; using ISelectable = Dynamo.Selection.ISelectable; using WpfResources = Dynamo.Wpf.Properties.Resources; @@ -2186,7 +2187,8 @@ private void InternalSaveAs(string path, SaveContext saveContext, bool isBackup if (path.Contains(Model.PathManager.TemplatesDirectory)) { // Give user notifications - MainGuideManager.CreateRealTimeInfoWindow("Workspaces cannot be saved to the Templates folder. Please choose a different folder to save your file."); + DynamoMessageBox.Show(WpfResources.WorkspaceSaveTemplateDirectoryBlockMsg, WpfResources.WorkspaceSaveTemplateDirectoryBlockTitle, + MessageBoxButton.OK, MessageBoxImage.Warning); } else { From 4d13c169e330c0e94a6ee34c5de623930f3bf12f Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Thu, 25 Jan 2024 18:16:47 -0500 Subject: [PATCH 08/13] Unit test --- test/DynamoCoreWpfTests/PreferencesViewModelTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/DynamoCoreWpfTests/PreferencesViewModelTests.cs b/test/DynamoCoreWpfTests/PreferencesViewModelTests.cs index f330f7aae3d..176ffe56c74 100644 --- a/test/DynamoCoreWpfTests/PreferencesViewModelTests.cs +++ b/test/DynamoCoreWpfTests/PreferencesViewModelTests.cs @@ -157,10 +157,12 @@ public void PathManagerWithDifferentHostTest() string dynamoRevitUserDataDirectory = "C:\\Users\\user\\AppData\\Roaming\\Dynamo\\Dynamo Revit\\3.1"; string dynamoRevitCommonDataDirectory = "C:\\ProgramData\\Autodesk\\RVT 2024\\Dynamo\\3.1"; string dynamoRevitSamplesPath = "C:\\ProgramData\\Autodesk\\RVT 2024\\Dynamo\\samples\\en-US"; + string dynamoRevitTemplatesPath = "C:\\ProgramData\\Autodesk\\RVT 2024\\Dynamo\\templates\\en-US"; Assert.AreEqual(Path.GetFullPath(singletonPathManager.UserDataDirectory), Path.GetFullPath(dynamoRevitUserDataDirectory)); Assert.AreEqual(Path.GetFullPath(singletonPathManager.CommonDataDirectory), Path.GetFullPath(dynamoRevitCommonDataDirectory)); Assert.AreEqual(Path.GetFullPath(singletonPathManager.SamplesDirectory), Path.GetFullPath(dynamoRevitSamplesPath)); + Assert.AreEqual(Path.GetFullPath(singletonPathManager.TemplatesDirectory), Path.GetFullPath(dynamoRevitTemplatesPath)); } } } From 31138f057e5d6d73827a8766b255fc1bff1869ff Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Thu, 25 Jan 2024 22:36:43 -0500 Subject: [PATCH 09/13] Unit test --- src/DynamoCore/Models/DynamoModel.cs | 5 ++--- src/DynamoCore/Models/DynamoModelCommands.cs | 3 +-- test/DynamoCoreWpfTests/WorkspaceSaving.cs | 21 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/DynamoCore/Models/DynamoModel.cs b/src/DynamoCore/Models/DynamoModel.cs index 942f14bd1a5..7240f398e2e 100644 --- a/src/DynamoCore/Models/DynamoModel.cs +++ b/src/DynamoCore/Models/DynamoModel.cs @@ -1963,13 +1963,12 @@ public void OpenFileFromPath(string filePath, bool forceManualExecutionMode = fa /// Path to file /// Set this to true to discard /// execution mode specified in the file and set manual mode - /// Set this to true to indicate that the file is a template - public void OpenTemplateFromPath(string filePath, bool forceManualExecutionMode = false, bool isTemplate = false) + public void OpenTemplateFromPath(string filePath, bool forceManualExecutionMode = false) { if (DynamoUtilities.PathHelper.isValidJson(filePath, out string fileContents, out Exception ex)) { - OpenJsonFileFromPath(fileContents, filePath, forceManualExecutionMode, isTemplate); + OpenJsonFileFromPath(fileContents, filePath, forceManualExecutionMode, true); return; } else diff --git a/src/DynamoCore/Models/DynamoModelCommands.cs b/src/DynamoCore/Models/DynamoModelCommands.cs index 90bb70fc25a..eae0f04c19a 100644 --- a/src/DynamoCore/Models/DynamoModelCommands.cs +++ b/src/DynamoCore/Models/DynamoModelCommands.cs @@ -57,8 +57,7 @@ protected virtual void OpenTemplateImpl(OpenFileCommand command) { string filePath = command.FilePath; bool forceManualMode = command.ForceManualExecutionMode; - bool isTemplate = command.IsTemplate; - OpenTemplateFromPath(filePath, forceManualMode, isTemplate); + OpenTemplateFromPath(filePath, forceManualMode); } protected virtual void OpenFileFromJsonImpl(OpenFileFromJsonCommand command) diff --git a/test/DynamoCoreWpfTests/WorkspaceSaving.cs b/test/DynamoCoreWpfTests/WorkspaceSaving.cs index 24ba07e97e5..cb524c089d6 100644 --- a/test/DynamoCoreWpfTests/WorkspaceSaving.cs +++ b/test/DynamoCoreWpfTests/WorkspaceSaving.cs @@ -549,6 +549,27 @@ public void CanSaveAndReadWorkspaceDescription() Assert.AreEqual("dummy description", ViewModel.Model.CurrentWorkspace.Description); } + [Test] + [Category("UnitTests")] + public void CanOpenTemplateAsNewWorkspace() + { + // get empty workspace + var dynamoModel = ViewModel.Model; + Assert.IsNotNull(dynamoModel.CurrentWorkspace); + + // set description + dynamoModel.CurrentWorkspace.Description = "dummy description"; + + // save + var newPath = GetNewFileNameOnTempPath("dyn"); + dynamoModel.CurrentWorkspace.Save(newPath); + + // load as template + ViewModel.Model.OpenTemplateFromPath(newPath); + Assert.AreEqual(string.Empty, ViewModel.Model.CurrentWorkspace.FileName); + Assert.AreEqual("dummy description", ViewModel.Model.CurrentWorkspace.Description); + } + [Test] [Category("UnitTests")] public void CanSaveAndReadWorkspaceName() From 6a921ee9a0dc562d1b7f5053ef505b12b10a7d21 Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Fri, 26 Jan 2024 10:29:54 -0500 Subject: [PATCH 10/13] comments --- test/DynamoCoreWpfTests/PreferencesViewModelTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/DynamoCoreWpfTests/PreferencesViewModelTests.cs b/test/DynamoCoreWpfTests/PreferencesViewModelTests.cs index 176ffe56c74..e349a3594f1 100644 --- a/test/DynamoCoreWpfTests/PreferencesViewModelTests.cs +++ b/test/DynamoCoreWpfTests/PreferencesViewModelTests.cs @@ -154,10 +154,10 @@ public void PathManagerWithDifferentHostTest() string dynamoRevitHostPath = "C:\\Program Files\\Autodesk\\Revit 2024\\AddIns\\DynamoForRevit\\Revit)"; singletonPathManager.AssignHostPathAndIPathResolver(dynamoRevitHostPath, revitPathResolver); - string dynamoRevitUserDataDirectory = "C:\\Users\\user\\AppData\\Roaming\\Dynamo\\Dynamo Revit\\3.1"; - string dynamoRevitCommonDataDirectory = "C:\\ProgramData\\Autodesk\\RVT 2024\\Dynamo\\3.1"; - string dynamoRevitSamplesPath = "C:\\ProgramData\\Autodesk\\RVT 2024\\Dynamo\\samples\\en-US"; - string dynamoRevitTemplatesPath = "C:\\ProgramData\\Autodesk\\RVT 2024\\Dynamo\\templates\\en-US"; + string dynamoRevitUserDataDirectory = Path.Combine(revitResolverParams.UserDataRootFolder, "3.1"); + string dynamoRevitCommonDataDirectory = Path.Combine(revitResolverParams.CommonDataRootFolder, "3.1"); + string dynamoRevitSamplesPath = Path.Combine(revitResolverParams.CommonDataRootFolder, "samples\\en-US"); + string dynamoRevitTemplatesPath = Path.Combine(revitResolverParams.CommonDataRootFolder, "templates\\en-US"); Assert.AreEqual(Path.GetFullPath(singletonPathManager.UserDataDirectory), Path.GetFullPath(dynamoRevitUserDataDirectory)); Assert.AreEqual(Path.GetFullPath(singletonPathManager.CommonDataDirectory), Path.GetFullPath(dynamoRevitCommonDataDirectory)); From a157b84d68fb5ece28489b71a4f96e5a5d34fac5 Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Fri, 26 Jan 2024 10:35:54 -0500 Subject: [PATCH 11/13] comments --- src/DynamoCore/Models/DynamoModel.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/DynamoCore/Models/DynamoModel.cs b/src/DynamoCore/Models/DynamoModel.cs index 7240f398e2e..46293ee6158 100644 --- a/src/DynamoCore/Models/DynamoModel.cs +++ b/src/DynamoCore/Models/DynamoModel.cs @@ -1969,7 +1969,6 @@ public void OpenTemplateFromPath(string filePath, bool forceManualExecutionMode if (DynamoUtilities.PathHelper.isValidJson(filePath, out string fileContents, out Exception ex)) { OpenJsonFileFromPath(fileContents, filePath, forceManualExecutionMode, true); - return; } else { @@ -2321,8 +2320,8 @@ private bool OpenJsonFile( CustomNodeManager, this.LinterManager); - workspace.FileName = string.IsNullOrEmpty(filePath) || isTemplate? "" : filePath; - workspace.FromJsonGraphId = string.IsNullOrEmpty(filePath) ? WorkspaceModel.ComputeGraphIdFromJson(fileContents) : ""; + workspace.FileName = string.IsNullOrEmpty(filePath) || isTemplate? string.Empty : filePath; + workspace.FromJsonGraphId = string.IsNullOrEmpty(filePath) ? WorkspaceModel.ComputeGraphIdFromJson(fileContents) : string.Empty; workspace.ScaleFactor = dynamoPreferences.ScaleFactor; if (!IsTestMode && !IsHeadless) From 16348fc5b40f6cb04c7fe10e0e794a97712ac5e9 Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Fri, 26 Jan 2024 15:09:13 -0500 Subject: [PATCH 12/13] reuse ShowOpenDialogAndOpenResult code --- .../ViewModels/Core/DynamoViewModel.cs | 85 ++++++------------- .../Core/DynamoViewModelDelegateCommands.cs | 2 +- src/DynamoCoreWpf/Views/Core/DynamoView.xaml | 1 + 3 files changed, 26 insertions(+), 62 deletions(-) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 9bb02e3d363..d80708af838 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -1929,6 +1929,8 @@ private void ShowOpenDialogAndOpenResult(object parameter) return; } + bool isTemplate = (parameter as string).Equals("Template"); + DynamoOpenFileDialog _fileDialog = new DynamoOpenFileDialog(this) { Filter = string.Format(Resources.FileDialogDynamoDefinitions, @@ -1937,70 +1939,24 @@ private void ShowOpenDialogAndOpenResult(object parameter) Title = string.Format(Resources.OpenDynamoDefinitionDialogTitle,BrandingResourceProvider.ProductName) }; - // if you've got the current space path, use it as the inital dir - if (!string.IsNullOrEmpty(Model.CurrentWorkspace.FileName)) + // If opening a template, use templates dir as the initial dir + if (isTemplate && !string.IsNullOrEmpty(Model.PathManager.TemplatesDirectory)) { - string path = Model.CurrentWorkspace.FileName; - if (File.Exists(path)) - { - var fi = new FileInfo(Model.CurrentWorkspace.FileName); - _fileDialog.InitialDirectory = fi.DirectoryName; - } - else - { - _fileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); - } - } - else // use the samples directory, if it exists - { - Assembly dynamoAssembly = Assembly.GetExecutingAssembly(); - string location = Path.GetDirectoryName(dynamoAssembly.Location); - string UICulture = CultureInfo.CurrentUICulture.Name; - string path = Path.Combine(location, "samples", UICulture); - + string path = Model.PathManager.TemplatesDirectory; if (Directory.Exists(path)) - _fileDialog.InitialDirectory = path; - } - - if (_fileDialog.ShowDialog() == DialogResult.OK) - { - if (CanOpen(_fileDialog.FileName)) { - Open(new Tuple(_fileDialog.FileName, _fileDialog.RunManualMode)); + var di = new DirectoryInfo(Model.PathManager.TemplatesDirectory); + _fileDialog.InitialDirectory = di.FullName; } } - } - - private bool CanShowOpenDialogAndOpenResultCommand(object parameter) => CanRunGraph; - - /// - /// Present the open dialog and open the template that is selected. - /// - /// - private void ShowOpenTemplateDialog(object parameter) - { - if (HomeSpace.HasUnsavedChanges) - { - if (!AskUserToSaveWorkspaceOrCancel(HomeSpace)) - return; - } - - DynamoOpenFileDialog _fileDialog = new DynamoOpenFileDialog(this) - { - Filter = string.Format(Resources.FileDialogDynamoDefinitions, - BrandingResourceProvider.ProductName, "*.dyn;*.dyf") + "|" + - string.Format(Resources.FileDialogAllFiles, "*.*"), - Title = string.Format(Resources.OpenDynamoDefinitionDialogTitle, BrandingResourceProvider.ProductName) - }; - - // if you've got the current space path, use it as the inital dir - if (!string.IsNullOrEmpty(Model.PathManager.TemplatesDirectory)) + // otherwise, if you've got the current space path, use it as the initial dir + else if (!string.IsNullOrEmpty(Model.CurrentWorkspace.FileName)) { - string path = Model.PathManager.TemplatesDirectory; - if (Directory.Exists(path)) + string path = Model.CurrentWorkspace.FileName; + if (File.Exists(path)) { - var di = new DirectoryInfo(Model.PathManager.TemplatesDirectory); - _fileDialog.InitialDirectory = di.FullName; + var fi = new FileInfo(Model.CurrentWorkspace.FileName); + _fileDialog.InitialDirectory = fi.DirectoryName; } else { @@ -2017,18 +1973,25 @@ private void ShowOpenTemplateDialog(object parameter) if (Directory.Exists(path)) _fileDialog.InitialDirectory = path; } - + if (_fileDialog.ShowDialog() == DialogResult.OK) { if (CanOpen(_fileDialog.FileName)) { - // Replace with the template file opening API which does not modify the template file - Open(new Tuple(_fileDialog.FileName, _fileDialog.RunManualMode, true)); + if (isTemplate) + { + // File opening API which does not modify the original template file + Open(new Tuple(_fileDialog.FileName, _fileDialog.RunManualMode, true)); + } + else + { + Open(new Tuple(_fileDialog.FileName, _fileDialog.RunManualMode)); + } } } } - private bool CanShowOpenTemplateDialog(object parameter) => CanRunGraph; + private bool CanShowOpenDialogAndOpenResultCommand(object parameter) => CanRunGraph; /// /// Present the open dialog and open the workspace that is selected. diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs index 5200db6e86a..3d9509e52dc 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs @@ -18,7 +18,7 @@ private void InitializeDelegateCommands() SaveCommand = new DelegateCommand(Save, CanSave); SaveAsCommand = new DelegateCommand(SaveAs, CanSaveAs); ShowOpenDialogAndOpenResultCommand = new DelegateCommand(ShowOpenDialogAndOpenResult, CanShowOpenDialogAndOpenResultCommand); - ShowOpenTemplateDialogCommand = new DelegateCommand(ShowOpenTemplateDialog, CanShowOpenTemplateDialog); + ShowOpenTemplateDialogCommand = new DelegateCommand(ShowOpenDialogAndOpenResult, CanShowOpenDialogAndOpenResultCommand); ShowInsertDialogAndInsertResultCommand = new DelegateCommand(ShowInsertDialogAndInsertResult, CanShowInsertDialogAndInsertResultCommand); ShowSaveDialogAndSaveResultCommand = new DelegateCommand(ShowSaveDialogAndSaveResult, CanShowSaveDialogAndSaveResult); ShowSaveDialogIfNeededAndSaveResultCommand = new DelegateCommand(ShowSaveDialogIfNeededAndSaveResult, CanShowSaveDialogIfNeededAndSaveResultCommand); diff --git a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml index 9a8021ce70f..889c07a2ca8 100644 --- a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml +++ b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml @@ -346,6 +346,7 @@ From 33f1b087a504a254ce862c27dffdb58cd8304e71 Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Fri, 26 Jan 2024 15:11:00 -0500 Subject: [PATCH 13/13] clean up --- src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs | 1 - .../ViewModels/Core/DynamoViewModelDelegateCommands.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index d80708af838..a66dde38597 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -47,7 +47,6 @@ using DynamoUtilities; using ICSharpCode.AvalonEdit; using PythonNodeModels; -using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip; using ISelectable = Dynamo.Selection.ISelectable; using WpfResources = Dynamo.Wpf.Properties.Resources; diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs index 3d9509e52dc..56faceb04df 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModelDelegateCommands.cs @@ -100,7 +100,6 @@ private void InitializeDelegateCommands() public DelegateCommand OpenCommand { get; set; } public DelegateCommand ShowOpenDialogAndOpenResultCommand { get; set; } public DelegateCommand ShowOpenTemplateDialogCommand { get; set; } - public DelegateCommand ShowInsertDialogAndInsertResultCommand { get; set; } public DelegateCommand WriteToLogCmd { get; set; } public DelegateCommand PostUiActivationCommand { get; set; }