-
Notifications
You must be signed in to change notification settings - Fork 679
Add RecordNodeHelpData feature #16870
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
zeusongit
wants to merge
7
commits into
DynamoDS:master
Choose a base branch
from
zeusongit:recordnodehelp
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
417c73c
Add RecordNodeHelpData feature and UI
zeusongit ea2c54d
Update PublicAPI.Unshipped.txt
zeusongit fcc6baf
Apply suggestions from code review
zeusongit c286ec1
Merge branch 'master' into recordnodehelp
zeusongit 4a15b8a
Merge branch 'master' into recordnodehelp
zeusongit d3446fe
Merge branch 'master' into recordnodehelp
zeusongit 1af81ae
Merge branch 'master' into recordnodehelp
johnpierson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4499,6 +4499,231 @@ internal bool CanDumpNodeIconData(object obj) | |
| return true; | ||
| } | ||
|
|
||
| internal bool CanRecordNodeHelpData(object obj) | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Records help documentation for the currently selected node. | ||
| /// Generates: .md file, _img.jpg screenshot, and .dyn sample graph. | ||
| /// Debug-only feature for creating node help documentation. | ||
| /// </summary> | ||
| internal void RecordNodeHelpData(object parameter) | ||
| { | ||
| // 1. Validate selection - need exactly one node selected | ||
| var selectedNodes = DynamoSelection.Instance.Selection.OfType<NodeModel>().ToList(); | ||
|
|
||
| if (selectedNodes.Count == 0) | ||
| { | ||
| ToastManager?.CreateRealTimeInfoWindow("Please select a node to record help data.", true); | ||
| return; | ||
| } | ||
|
|
||
| if (selectedNodes.Count > 1) | ||
| { | ||
| ToastManager?.CreateRealTimeInfoWindow("Please select only one node to record help data.", true); | ||
| return; | ||
| } | ||
|
|
||
| var selectedNode = selectedNodes.First(); | ||
|
|
||
| // 2. Get minimum qualified name for file naming (no hash) | ||
| var mqn = GetMinimumQualifiedName(selectedNode); | ||
|
zeusongit marked this conversation as resolved.
|
||
|
|
||
| // 3. Use node name for display in toast | ||
| var nodeName = selectedNode.Name; | ||
|
|
||
| // 4. Get output directory - backtrack from bin\AnyCPU\Debug to doc\distrib\NodeHelpFiles\en-US | ||
| DirectoryInfo nodeHelpDocPath; | ||
| try | ||
| { | ||
| // Get the executing assembly location (bin\AnyCPU\Debug) | ||
| var assemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); | ||
|
|
||
| // Backtrack to Dynamo root: go up 3 levels from bin\AnyCPU\Debug | ||
| var dynamoRoot = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(assemblyLocation))); | ||
|
|
||
| // Build path to doc\distrib\NodeHelpFiles\en-US | ||
| var docPath = Path.Combine(dynamoRoot, "doc", "distrib", "NodeHelpFiles", "en-US"); | ||
| nodeHelpDocPath = new DirectoryInfo(docPath); | ||
|
|
||
| // Create directory if it doesn't exist | ||
| if (!nodeHelpDocPath.Exists) | ||
| { | ||
| nodeHelpDocPath.Create(); | ||
| } | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| ToastManager?.CreateRealTimeInfoWindow($"Failed to create output directory: {ex.Message}", true); | ||
| return; | ||
| } | ||
|
|
||
| // 5. Generate file paths using minimum qualified name directly (no hash) | ||
| var mdFileName = $"{mqn}.md"; | ||
| var imgFileName = $"{mqn}_img.jpg"; | ||
| var dynFileName = $"{mqn}.dyn"; | ||
|
|
||
| var mdFilePath = Path.Combine(nodeHelpDocPath.FullName, mdFileName); | ||
| var imgFilePath = Path.Combine(nodeHelpDocPath.FullName, imgFileName); | ||
| var dynFilePath = Path.Combine(nodeHelpDocPath.FullName, dynFileName); | ||
|
|
||
| try | ||
| { | ||
| // 6. Export workspace image with 3D background overlay | ||
| ExportWorkspaceImageWithBackground(imgFilePath); | ||
|
|
||
| // 7. Save sample graph (.dyn) | ||
| SaveAs(dynFilePath, SaveContext.Save, false); | ||
|
|
||
| // 8. Generate markdown file | ||
| GenerateNodeHelpMarkdown(selectedNode, mqn, mdFilePath, imgFileName); | ||
|
|
||
| // 9. Show success toast with node name | ||
| var message = $"Node help files created for '{nodeName}':\n" + | ||
| $" {mdFileName}\n" + | ||
| $" {imgFileName}\n" + | ||
| $" {dynFileName}\n" + | ||
| $"Location: {nodeHelpDocPath.FullName}"; | ||
| ToastManager?.CreateRealTimeInfoWindow(message, true); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| ToastManager?.CreateRealTimeInfoWindow($"Error recording node help data: {ex.Message}", true); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Exports workspace image with 3D background overlay. | ||
| /// Combines the 3D preview background with the workspace graph view. | ||
| /// </summary> | ||
|
zeusongit marked this conversation as resolved.
|
||
| private void ExportWorkspaceImageWithBackground(string outputPath) | ||
| { | ||
| var tempDir = Path.GetTempPath(); | ||
| var backgroundPath = Path.Combine(tempDir, $"bg_{Guid.NewGuid()}.png"); | ||
| var foregroundPath = Path.Combine(tempDir, $"fg_{Guid.NewGuid()}.png"); | ||
|
|
||
| try | ||
| { | ||
| // Export 3D background | ||
| BackgroundPreviewViewModel?.ZoomToFitCommand?.Execute(null); | ||
| var backgroundImageArgs = new ImageSaveEventArgs(backgroundPath); | ||
| OnRequestSave3DImage(this, backgroundImageArgs); | ||
|
|
||
| // Export workspace (graph view) | ||
| var foregroundImageArgs = new ImageSaveEventArgs(foregroundPath); | ||
| OnRequestSaveImage(this, foregroundImageArgs); | ||
|
|
||
| // Combine images if both exist | ||
| if (File.Exists(backgroundPath) && File.Exists(foregroundPath)) | ||
| { | ||
| using (var combined = OverlayWorkspaceImages(backgroundPath, foregroundPath)) | ||
| { | ||
| if (combined != null) | ||
| { | ||
| combined.Save(outputPath, System.Drawing.Imaging.ImageFormat.Jpeg); | ||
| } | ||
| else | ||
| { | ||
| // Fallback: just copy the workspace image | ||
| File.Copy(foregroundPath, outputPath, true); | ||
| } | ||
| } | ||
| } | ||
| else if (File.Exists(foregroundPath)) | ||
| { | ||
| // Fallback: just use workspace image if 3D background not available | ||
| File.Copy(foregroundPath, outputPath, true); | ||
| } | ||
| } | ||
| finally | ||
| { | ||
| // Clean up temp files | ||
| try { if (File.Exists(backgroundPath)) File.Delete(backgroundPath); } catch { } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, a comment as to why the exception is eaten could not hurt |
||
| try { if (File.Exists(foregroundPath)) File.Delete(foregroundPath); } catch { } | ||
|
zeusongit marked this conversation as resolved.
|
||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Overlay workspace graph over 3D background. | ||
| /// </summary> | ||
|
zeusongit marked this conversation as resolved.
|
||
| private static System.Drawing.Bitmap OverlayWorkspaceImages(string backgroundPath, string foregroundPath) | ||
| { | ||
| try | ||
| { | ||
| using (var baseImage = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(backgroundPath)) | ||
| using (var overlayImage = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(foregroundPath)) | ||
| { | ||
| // Calculate scale to fit overlay properly | ||
| var scale = 1.5; | ||
|
zeusongit marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, a comment here too, explain why 1.5 |
||
| var scaleFactor = Math.Max( | ||
| overlayImage.Width / (float)baseImage.Width, | ||
| overlayImage.Height / (float)baseImage.Height); | ||
| var newWidth = (int)(baseImage.Width * scaleFactor * scale); | ||
| var newHeight = (int)(baseImage.Height * scaleFactor * scale); | ||
|
|
||
| var finalImage = new System.Drawing.Bitmap(newWidth, newHeight, | ||
| System.Drawing.Imaging.PixelFormat.Format32bppArgb); | ||
|
|
||
| using (var graphics = System.Drawing.Graphics.FromImage(finalImage)) | ||
| { | ||
| graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; | ||
| graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; | ||
| graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; | ||
|
|
||
| // Dynamo-white background | ||
| graphics.Clear(System.Drawing.Color.FromArgb(249, 249, 249)); | ||
|
|
||
| // Draw resized background slightly down (15% from top) | ||
| using (var resizedBg = new System.Drawing.Bitmap(baseImage, newWidth, newHeight)) | ||
| { | ||
| graphics.DrawImage(resizedBg, 0, (int)(newHeight * 0.15f)); | ||
| } | ||
|
|
||
| // Draw workspace overlay in upper center | ||
| var offsetX = (newWidth - overlayImage.Width) / 2; | ||
| var offsetY = (int)((newHeight - overlayImage.Height) * 0.25f); | ||
|
zeusongit marked this conversation as resolved.
Outdated
zeusongit marked this conversation as resolved.
Outdated
|
||
| graphics.DrawImage(overlayImage, offsetX, offsetY); | ||
| } | ||
|
|
||
| return finalImage; | ||
| } | ||
| } | ||
| catch | ||
| { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Generates the markdown help file for a node. | ||
| /// </summary> | ||
|
zeusongit marked this conversation as resolved.
|
||
| private void GenerateNodeHelpMarkdown(NodeModel node, string mqn, | ||
| string outputPath, string imgFileName) | ||
| { | ||
| var sb = new System.Text.StringBuilder(); | ||
|
|
||
| // Add HTML comment header with node name (pattern from existing help files) | ||
| sb.AppendLine($"<!--- {mqn} --->"); | ||
|
|
||
| // In Depth section with node description | ||
| sb.AppendLine("## In Depth"); | ||
| var description = !string.IsNullOrWhiteSpace(node.Description) | ||
| ? node.Description | ||
| : $"{node.Name} - [Add description here]"; | ||
| sb.AppendLine(description); | ||
| sb.AppendLine(); | ||
|
|
||
| // Example file section with image | ||
| sb.AppendLine("___"); | ||
| sb.AppendLine("## Example File"); | ||
| sb.AppendLine(); | ||
| sb.AppendLine($""); | ||
|
|
||
| File.WriteAllText(outputPath, sb.ToString()); | ||
| } | ||
|
|
||
| #region Shutdown related methods | ||
|
|
||
| /// <summary> | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.