Skip to content
Closed
109 changes: 109 additions & 0 deletions Packages/MIES/MIES_MiesUtilities_GUI.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
/// @file MIES_MiesUtilities_GUI.ipf
/// @brief This file holds MIES utility functions for GUI

Menu "GraphPopup"
"Export graph to SVG", /Q, ExportGraphToSVG(GetCurrentWindow())
End

/// @brief Return the dimension label for the special, aka non-unique, controls
Function/S GetSpecialControlLabel(variable channelType, variable controlType)

Expand Down Expand Up @@ -845,3 +849,108 @@ Function StoreWindowCoordinatesHook(STRUCT WMWinHookStruct &s)

return 0
End

/// @brief Get Downloads folder path using PowerShell (Windows only)
///
/// Returns a colon-delimited HFS path, including a terminating colon.
///
/// @return Igor-formatted path to Downloads folder, or empty string on failure
static Function/S GetDownloadsPathIgor()

string ps, cmd, native, igorPath
variable igorPathLen

ps = "(New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path"
cmd = "powershell.exe -nologo -noprofile -command \"" + ps + "\""

// 10s timeout to avoid hanging on PowerShell invocation; ample for a shell lookup
ExecuteScriptText/B/Z/W=10 cmd
if(V_flag != 0)
DEBUGPRINT("Failed to determine Downloads folder via PowerShell")
return ""
endif

native = S_value

// Strip CR/LF aggressively
native = ReplaceString("\r", native, "")
native = ReplaceString("\n", native, "")

if(IsEmpty(native))
return ""
endif

// Convert native Windows path to Igor's HFS format
igorPath = GetHFSPath(native)
if(IsEmpty(igorPath))
DEBUGPRINT("Failed to convert Downloads path to HFS format")
return ""
endif

igorPathLen = strlen(igorPath)
if(igorPathLen > 0 && cmpstr(igorPath[igorPathLen - 1], ":") != 0)
igorPath += ":"
endif

return igorPath
End

/// @brief Export a graph to SVG format
///
/// Saves the graph as SVG to:
/// - Windows: Downloads folder (falls back to Documents if Downloads doesn't exist)
/// - Mac: Documents folder
/// @param winName Name of the window (graph) to export
/// @return 0 on success, NaN on failure
Function ExportGraphToSVG(string winName)

string savePath, fileName, fullPath, baseName, timeStamp, documentsPath
variable maxFileNameLen = 240

ASSERT(!IsEmpty(winName), "Window name must not be empty (menu invocation failed)")
ASSERT(WindowExists(winName), "Graph window does not exist or is not accessible: " + winName)

// Get Documents folder path as fallback
documentsPath = SpecialDirPath("Documents", 0, 0, 0)
ASSERT(!IsEmpty(documentsPath), "Could not determine Documents folder location.")

savePath = documentsPath

#ifdef WINDOWS
// On Windows, prefer Downloads folder over Documents
string downloadsPath = GetDownloadsPathIgor()
// Verify Downloads path exists in case the shell lookup returns an unavailable location
if(!IsEmpty(downloadsPath) && FolderExists(downloadsPath))
savePath = downloadsPath
else
print "Info: Downloads folder unavailable, using Documents: " + documentsPath
endif
#endif // WINDOWS

// Generate file name from window name and timestamp
baseName = CleanupName(winName, 0)
// localTimeZone is a boolean flag in GetISO8601TimeStamp; use local time for filenames
timeStamp = GetISO8601TimeStamp(localTimeZone = 1)
ASSERT(!IsEmpty(timeStamp), "Failed to generate timestamp for filename")
// Replace colons and hyphens with underscores for filename
timeStamp = ReplaceString(":", timeStamp, "_")
timeStamp = ReplaceString("-", timeStamp, "_")
// Cap filename at 240 chars to avoid extreme lengths; full path may still exceed Windows MAX_PATH
fileName = baseName + "_" + timeStamp
if(strlen(fileName) > maxFileNameLen)
fileName = fileName[0, maxFileNameLen - 1]
endif
fileName = fileName + ".svg"
ASSERT(!IsEmpty(fileName), "File name must not be empty")
fullPath = savePath + fileName

// Save graph as SVG (E=-9 is SVG format)
try
SavePICT/O/E=-9/WIN=$winName as fullPath
print "Graph exported to SVG: " + fullPath
catch
ASSERT(0, "Failed to save SVG file: " + fullPath + "\r" + GetRTErrMessage())
endtry

return 0
End