Skip to content

Commit

Permalink
Open Dynamo Template as new workspace (#14871)
Browse files Browse the repository at this point in the history
* Open Template UI change

* Add more functions for template opening

* add comments

* reuse open function

* Open Template with FileName as empty

* Give user notification

* Add message confirmation

* Unit test

* Unit test

* comments

* comments

* reuse ShowOpenDialogAndOpenResult code

* clean up
  • Loading branch information
QilongTang authored Jan 27, 2024
1 parent 497a73f commit ffbc181
Show file tree
Hide file tree
Showing 14 changed files with 264 additions and 27 deletions.
5 changes: 5 additions & 0 deletions src/DynamoCore/Configuration/IPathResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ public interface IPathManager
/// </summary>
string SamplesDirectory { get; }

/// <summary>
/// The root directory where all template files are stored
/// </summary>
string TemplatesDirectory { get; }

/// <summary>
/// The directory where the automatically saved files will be stored.
/// </summary>
Expand Down
57 changes: 56 additions & 1 deletion src/DynamoCore/Configuration/PathManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ internal static Lazy<PathManager>
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";
Expand All @@ -82,6 +83,7 @@ internal static Lazy<PathManager>
private string commonPackages;
private string logDirectory;
private string samplesDirectory;
private string templatesDirectory;
private string backupDirectory;
private string defaultBackupDirectory;
private string preferenceFilePath;
Expand Down Expand Up @@ -240,6 +242,14 @@ public string SamplesDirectory
get { return samplesDirectory; }
}

/// <summary>
/// Dynamo Templates folder
/// </summary>
public string TemplatesDirectory
{
get { return templatesDirectory; }
}

public string BackupDirectory
{
get { return backupDirectory; }
Expand Down Expand Up @@ -572,6 +582,7 @@ private void BuildCommonDirectories()
commonDefinitions = Path.Combine(commonDataDir, DefinitionsDirectoryName);
commonPackages = Path.Combine(commonDataDir, PackagesDirectoryName);
samplesDirectory = GetSamplesFolder(commonDataDir);
templatesDirectory = GetTemplateFolder(commonDataDir);

rootDirectories = new List<string> { userDataDir };

Expand Down Expand Up @@ -715,7 +726,51 @@ private static string GetSamplesFolder(string dataRootDirectory)

return sampleDirectory;
}


/// <summary>
/// Get template folder path from common data directory
/// </summary>
/// <param name="dataRootDirectory"></param>
/// <returns></returns>
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}\templates" 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<string> LibrarySearchPaths(string library)
{
// Strip out possible directory from library path.
Expand Down
35 changes: 30 additions & 5 deletions src/DynamoCore/Models/DynamoModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1957,6 +1957,29 @@ public void OpenFileFromPath(string filePath, bool forceManualExecutionMode = fa
}
}

/// <summary>
/// Opens a Dynamo workspace from a path to a template on disk.
/// </summary>
/// <param name="filePath">Path to file</param>
/// <param name="forceManualExecutionMode">Set this to true to discard
/// execution mode specified in the file and set manual mode</param>
public void OpenTemplateFromPath(string filePath, bool forceManualExecutionMode = false)
{

if (DynamoUtilities.PathHelper.isValidJson(filePath, out string fileContents, out Exception ex))
{
OpenJsonFileFromPath(fileContents, filePath, forceManualExecutionMode, true);
}
else
{
// These kind of exceptions indicate that file is not accessible
if (ex is IOException || ex is UnauthorizedAccessException || ex is JsonReaderException)
{
throw ex;
}
}
}

/// <summary>
/// Inserts a Dynamo graph or Custom Node inside the current workspace from a file path
/// </summary>
Expand Down Expand Up @@ -2028,8 +2051,9 @@ static private DynamoPreferencesData DynamoPreferencesDataFromJson(string json)
/// <param name="filePath">Path to file</param>
/// <param name="forceManualExecutionMode">Set this to true to discard
/// execution mode specified in the file and set manual mode</param>
/// <param name="isTemplate">Set this to true to indicate that the file is a template</param>
/// <returns>True if workspace was opened successfully</returns>
private bool OpenJsonFileFromPath(string fileContents, string filePath, bool forceManualExecutionMode)
private bool OpenJsonFileFromPath(string fileContents, string filePath, bool forceManualExecutionMode, bool isTemplate = false)
{
try
{
Expand All @@ -2040,7 +2064,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
Expand Down Expand Up @@ -2076,7 +2100,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);

Expand Down Expand Up @@ -2268,6 +2292,7 @@ private bool OpenJsonFile(
string fileContents,
DynamoPreferencesData dynamoPreferences,
bool forceManualExecutionMode,
bool isTemplate,
out WorkspaceModel workspace)
{
if (!string.IsNullOrEmpty(filePath))
Expand Down Expand Up @@ -2295,8 +2320,8 @@ private bool OpenJsonFile(
CustomNodeManager,
this.LinterManager);

workspace.FileName = string.IsNullOrEmpty(filePath) ? "" : 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)
Expand Down
8 changes: 8 additions & 0 deletions src/DynamoCore/Models/DynamoModelCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,20 @@ 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;
OpenTemplateFromPath(filePath, forceManualMode);
}

protected virtual void OpenFileFromJsonImpl(OpenFileFromJsonCommand command)
{
string fileContents = command.FileContents;
Expand Down
16 changes: 13 additions & 3 deletions src/DynamoCore/Models/RecordableCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,16 @@ public class OpenFileCommand : RecordableCommand
#region Public Class Methods

/// <summary>
///
/// Constructor
/// </summary>
/// <param name="filePath">The path to the file.</param>
/// <param name="forceManualExecutionMode">Should the file be opened in manual execution mode?</param>
public OpenFileCommand(string filePath, bool forceManualExecutionMode = false)
/// <param name="isTemplate">Is Dynamo opening a template file?</param>
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)
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
36 changes: 36 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion src/DynamoCoreWpf/Properties/Resources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -3900,4 +3900,16 @@ In certain complex graphs or host program scenarios, Automatic mode may cause in
<data name="ResetChangesWarningPopupMessage" xml:space="preserve">
<value>Your changes will be lost if you proceed.</value>
</data>
</root>
<data name="DynamoViewFileMenuOpenFile" xml:space="preserve">
<value>_File</value>
</data>
<data name="DynamoViewFileMenuOpenTemplate" xml:space="preserve">
<value>_Template</value>
</data>
<data name="WorkspaceSaveTemplateDirectoryBlockMsg" xml:space="preserve">
<value>Workspaces cannot be saved to the Templates folder. Please choose a different folder to save your file.</value>
</data>
<data name="WorkspaceSaveTemplateDirectoryBlockTitle" xml:space="preserve">
<value>Invalid Save Path</value>
</data>
</root>
12 changes: 12 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -3887,4 +3887,16 @@ In certain complex graphs or host program scenarios, Automatic mode may cause in
<data name="ResetChangesWarningPopupMessage" xml:space="preserve">
<value>Your changes will be lost if you proceed.</value>
</data>
<data name="DynamoViewFileMenuOpenFile" xml:space="preserve">
<value>_File</value>
</data>
<data name="DynamoViewFileMenuOpenTemplate" xml:space="preserve">
<value>_Template</value>
</data>
<data name="WorkspaceSaveTemplateDirectoryBlockMsg" xml:space="preserve">
<value>Workspaces cannot be saved to the Templates folder. Please choose a different folder to save your file.</value>
</data>
<data name="WorkspaceSaveTemplateDirectoryBlockTitle" xml:space="preserve">
<value>Invalid Save Path</value>
</data>
</root>
Loading

0 comments on commit ffbc181

Please sign in to comment.