source: trunk/User Procedures/Nika/NI1_HDF5Browser.ipf @ 938

Last change on this file since 938 was 938, checked in by ilavsky, 2 years ago

Igor 9 related changes

File size: 115.7 KB
Line 
1#pragma TextEncoding = "UTF-8"
2#pragma rtGlobals=3             // Use modern global access method.
3//#pragma rtGlobals=1           // Use modern global access method.
4#pragma version = 1.01
5
6#include <WaveSelectorWidget>
7
8#pragma moduleName=NikaHDF5Browser
9
10//1.01 modified to compile when hdf5 xop is not available.
11// 1.0 initial release. Not working yet, but need to go ahead with release.
12//This is modified version of HDF5 Browser.ipf version 1.03 modified for use with Nika package by jan Ilavsky, January 2011
13// ilavsky@aps.anl.gov
14//this will provide limited functionality to provide user with ability to select for Nika which data to load and how. 
15
16//Menu "testing"
17//      "New HDF5 Browser", /Q, NI2_CreateNewHDF5Browser("Nika")
18//End
19
20//**********************
21//       this is the main function called by Nika or Irena to load general hdf file...
22
23Function/S NI2_LoadGeneralHDFFile(CalledFrom, fileName, PathName)
24        string CalledFrom,  fileName, PathName
25       
26        abort "General HDF5 load is broken due to Igor 9 code modifications. Remind author to fix it (and send example data set, please)"
27        //CalledFrom ... "Nika" or "Irena"
28        Wave/Z/T GroupNames=$("root:Packages:"+CalledFrom+"HDF5Loader:GroupNames")
29        //this should contain list of data sets names to load form all selected hdf5 files...
30        if(!WaveExists(GroupNames))
31                NI2_CreateNewHDF5Browser(CalledFrom)
32                DoAlert 0, "Set Hdf options first"
33        endif
34        variable locFileID
35
36#if Exists("HDF5OpenFile")     
37        HDF5OpenFile/R/P=$(PathName) locFileID as fileName
38        //Need to create temp folder to handle the whole group of stuff here...
39        string oldDf=GetDataFolder (1)
40        setDataFolder root:Packages:
41        NewDataFolder/O/S root:Packages:TempHDFLoad
42        KillWaves/A/Z           //clean the folder up
43
44        variable i              //what if user wants more groups???
45        For(i=0;i<numpnts(GroupNames);i+=1)
46                HDF5LoadGroup /O /R /T /IMAG=1 :, locFileID, GroupNames[i]
47        endfor
48        string/g GroupPathsLoaded, dataFolderPathsLoaded, ObjectPathsLoaded
49       
50        GroupPathsLoaded                =       S_groupPaths
51        dataFolderPathsLoaded   =       S_dataFolderPaths
52        ObjectPathsLoaded               =        S_objectPaths
53        HDF5CloseFile locFileID
54        if(stringmatch(CalledFrom,"Nika"))
55                NI2_ParseNikaData()
56        else
57                abort "not finished Irena or other loading in NI1_HDF5Browser#NI2_LoadGeneralHDFFile"
58        endif
59       
60        return "LoadedWave"
61       
62#else
63        Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
64#endif
65end
66
67 Function NI2_ParseNikaData()           //here we parse loaded groups for Nika. Notre - Nika expects ONE 2D image from the hdf file...
68        //need to create ONE "LoadedWave" in the Nika folder from what we have here...
69        //here is what is available:
70        setDataFolder root:Packages:TempHDFLoad
71        SVAR GroupPathsLoaded = root:Packages:TempHDFLoad:GroupPathsLoaded
72        SVAR dataFolderPathsLoaded=root:Packages:TempHDFLoad:dataFolderPathsLoaded
73        SVAR ObjectPathsLoaded=root:Packages:TempHDFLoad:ObjectPathsLoaded
74       
75        //for now assume only one group loaded for Nika.... If we will need more, we'll have to kwnowhat users want
76        //      string PathToData=stringfromList(0,GroupPathsLoaded,";")
77        //      PathToData = stringfromList(ItemsinList(PathToData, "/")-1, PathToData, "/")
78//      if(DataFolderExists(PathToData) )               //does the folder exist as expected?
79//              setDataFolder $(PathToData)
80//
81//
82//      else
83//              Abort "Parsing failed, send example of data to ilavsky@aps.anl.gov"
84//      endif
85        variable i
86        For(i=0;i<itemsInList(ObjectPathsLoaded,";");i+=1)
87                wave tempWv=$(stringFromList(i,ObjectPathsLoaded,";"))
88                if(dimsize(tempWv,1)>0 && dimsize(tempWv,2)==0) //thsi is 2 D wave
89                        //do something with this wave
90                       
91                        return 1
92                endif   
93        endfor
94        Abort "Parsing Nika data filed, not 2D wave found"
95       
96       
97end
98
99
100//*********************
101
102
103
104Structure NI2HDF5BrowserData
105        SVAR browserName
106
107        Wave/T groupsList
108        Wave/T groupAttributesList
109        Wave/T datasetsList
110        Wave/T datasetAttributesList
111       
112        Wave/T groupFullPaths
113        SVAR groupPath
114
115        SVAR hyperSelectionWavePath
116       
117        NVAR fileID
118        SVAR fileName
119        SVAR path
120        SVAR fullPath
121        NVAR readOnly
122       
123        SVAR datasetInfo                                                // Panel readout info for currently-selected dataset
124EndStructure
125//
126static Function CreateHDF5BrowserGlobals(newBrowserName)
127        String newBrowserName
128       
129        // Create globals that apply to this browser window.
130       
131        String savedDataFolder = NI2_SetBrowserDataFolder(newBrowserName)
132       
133        String/G browserName = newBrowserName
134       
135        Make/O/T/N=0 groupsList
136        Make/O/T/N=0 groupAttributesList
137        Make/O/T/N=0 datasetsList
138        Make/O/T/N=0 datasetAttributesList
139
140        Make/O/T/N=0 groupFullPaths                                     // For each group, contains the corresponding full path to that group.
141        String/G groupPath = "/"                                                // Path to currently selected group
142
143        String/G hyperSelectionWavePath                 // Path to hyperselection wave, if any.
144       
145        Variable/G fileID = 0                                                   // 0 means no file is open for this browser.
146
147        String/G fileName = ""
148        String/G path = ""
149        String/G fullPath = ""
150        Variable/G readOnly = 1
151       
152        String/G datasetInfo
153       
154        SetDataFolder savedDataFolder
155End
156//
157Function/S NI2_SetBrowserDataFolder(browserName)                // Pass "" for browserName to set to master browser folder.
158        String browserName
159       
160        String savedDataFolder = GetDataFolder(1)
161       
162        NewDataFolder/O/S root:Packages
163        NewDataFolder/O/S HDF5Browser
164       
165        if (strlen(browserName) > 0)
166                NewDataFolder/O/S $browserName
167        endif
168       
169        return savedDataFolder
170End
171//
172//static Function SetNI2HDF5BrowserData(browserName, bd)
173//      String browserName
174//      STRUCT NI2HDF5BrowserData &bd
175//     
176//      String savedDataFolder = NI2_SetBrowserDataFolder(browserName)
177//     
178//      // These statements set the structure fields to reference the corresponding waves and variables in the data folder.
179//     
180//      SVAR bd.browserName
181//     
182//      Wave/T bd.groupsList
183//      Wave/T bd.groupAttributesList
184//      Wave/T bd.datasetsList
185//      Wave/T bd.datasetAttributesList
186//     
187//      Wave/T bd.groupFullPaths
188//      SVAR bd.groupPath
189//
190//      SVAR bd.hyperSelectionWavePath
191//     
192//      NVAR bd.fileID
193//      SVAR bd.fileName
194//      SVAR bd.path
195//      SVAR bd.fullPath
196//      NVAR bd.readOnly
197//     
198//      SVAR bd.datasetInfo
199//     
200//      SetDataFolder savedDataFolder
201//End
202//
203//static Function CountSlashes(item)
204//      String item
205//     
206//      Variable slashes = 0
207//      Variable pos = 0
208//     
209//      do
210//              pos = strsearch(item, "/", pos)
211//              if (pos < 0)
212//                      break
213//              endif
214//              slashes += 1
215//              pos += 1
216//      while (1)
217//
218//      return slashes
219//End
220//
221//Function/S NI2_GetGroupHierarchy(fileID, startPath, level, mode)
222//      Variable fileID
223//      String startPath
224//      Variable level
225//      Variable mode                   // 0 to just get group names; 1 to get full path to each group.
226//
227//      String result = ""
228//
229//      String indent = ""                      // Used only for mode 0.
230//      Variable i, j
231//
232//#if Exists("HDF5ListGroup")   
233//     
234//      // This gives full hierarchy with full paths
235//      HDF5ListGroup /F /R /TYPE=1 fileID, startPath
236//      result = S_HDF5ListGroup
237//     
238//      if (mode == 0)                          // Want just names, not full paths
239//              result = ""
240//              Variable numItems = ItemsInList(S_HDF5ListGroup)
241//              for(i=0; i<numItems; i+=1)
242//                      String item = StringFromList(i, S_HDF5ListGroup)
243//                      level = CountSlashes(item)
244//                      indent = ""
245//                      for(j=0; j<level; j+=1)
246//                              indent += "    "
247//                      endfor
248//                      item = ParseFilePath(0, item, "/", 1, 0)                        // Get last element
249//                      item = indent + item                                            // Prepend indentation
250//                      result += item + ";"           
251//              endfor 
252//      endif
253//     
254//      return result
255//#else
256//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
257//#endif
258//End
259//
260//static Function/S GetFileHierarchy(bd, mode)
261//      STRUCT NI2HDF5BrowserData &bd
262//      Variable mode                                           // 0 to just get group names; 1 to get full path to each group.
263//     
264//      if (bd.fileID == 0)                                                     // No file is open?
265//              return ""
266//      endif
267//     
268//      String hierarchy, rootName
269//      if (mode == 1)
270//              rootName = "/"                                  // For purposes of storing full path, use true root name
271//      else
272//              rootName = "root"                                       // For display purposes, use "root" as root name
273//      endif
274//      hierarchy = rootName + ";" + NI2_GetGroupHierarchy(bd.fileID, "/", 1, mode)
275//     
276//      return hierarchy
277//End
278//
279//static Function ResetListSelections(bd, resetGroupsList, resetGroupAttributesList, resetDatasetsList, resetDatasetAttributesList)
280//      STRUCT NI2HDF5BrowserData &bd
281//      Variable resetGroupsList, resetGroupAttributesList, resetDatasetsList, resetDatasetAttributesList
282//
283//      if (resetGroupsList)
284//              ListBox GroupsList, win=$bd.browserName, selRow=0
285//      endif
286//      if (resetGroupAttributesList)
287//              ListBox GroupAttributesList, win=$bd.browserName, selRow=0
288//      endif
289//      if (resetDatasetsList)
290//              ListBox DatasetsList, win=$bd.browserName, selRow=0
291//      endif
292//      if (resetDatasetAttributesList)
293//              ListBox DatasetAttributesList, win=$bd.browserName, selRow=0
294//      endif
295//End
296//
297//Function/S NI2_HDF5GetObjectFullPath(groupPath, objectName)
298//      String groupPath                                        // Path to parent group
299//      String objectName                               // Name of dataset or group in parent group
300//     
301//      String fullPath
302//     
303//      if (CmpStr(groupPath, "/") == 0)
304//              fullPath = "/" + objectName
305//      else
306//              fullPath = groupPath + "/" + objectName
307//      endif
308//     
309//      return fullPath
310//End
311//
312//Function/S NI2_GetTextPreviewString(tw)
313//      Wave/T tw                                               // tw has already been flattened to 1D.
314//     
315//      String preview, temp
316//      Variable len
317//     
318//      Variable row, numRows, totalLength
319//     
320//      totalLength = 0
321//
322//      numRows = numpnts(tw)
323//      if (numRows == 0)
324//              return ""
325//      endif
326//     
327//      preview = ""
328//      row = 0
329//      do
330//              temp = tw[row]
331//              temp = ReplaceString("\r", temp, "<CR>", 1)     // Convert CR to "\r"
332//              temp = ReplaceString("\n", temp, "<LF>", 1)     // Convert LF to "\n"
333//
334//              len = strlen(temp)
335//              if (len > 128)
336//                      if (numRows == 1)
337//                              sprintf preview, "\"%s\" . . . (%d characters total)", temp[0,127], len
338//                      else
339//                              preview += " . . . <Strings too long to display here>"
340//                      endif
341//                     
342//                      row = numRows                                                   // To prevent extra . . .
343//                      break
344//              endif
345//
346//              preview += "\"" + temp + "\""
347//              row += 1
348//              totalLength += len
349//
350//              if (row >= numRows)
351//                      break
352//              endif
353//              if (totalLength >= 256)                         // Enough is enough
354//                      break
355//              endif
356//
357//              preview += ", "
358//      while(1)
359//
360//      if (row < numRows)
361//              preview += " . . ."
362//      endif
363//
364//      return preview
365//End
366//
367//Function/S NI2_GetNumericPreviewString(w)
368//      Wave w                                                  // w has already been flattened to 1D.
369//
370//      String preview, temp
371//     
372//      Variable row, numRows, totalLength
373//     
374//      totalLength = 0
375//
376//      numRows = numpnts(w)
377//      if (numRows == 0)
378//              return ""
379//      endif
380//     
381//      preview = ""
382//      row = 0
383//      do
384//              sprintf temp, "%g", w[row]
385//              preview += temp
386//              row += 1
387//              totalLength += strlen(temp)
388//
389//              if (row >= numRows)
390//                      break
391//              endif
392//              if (totalLength >= 256)                                 // Enough is enough
393//                      break
394//              endif
395//
396//              preview += ", "
397//      while(1)
398//
399//      if (row < numRows)
400//              preview += " . . ."
401//      endif
402//     
403//      return preview
404//End
405//
406//Function/S NI2_GetPreviewString(locationID, objectType, di, fullPath, attributeName)
407//      Variable locationID
408//      Variable objectType                                             // 1 = group, 2 = dataset
409//      STRUCT NI2_HDF5DataInfo &di
410//      String fullPath                                                 // Full path to group or dataset
411//      String attributeName                                    // "" if this is a dataset, not an attribute
412//     
413//      String value = "<Can't display here>"
414//      String temp
415//     
416//      Variable rank = di.ndims
417//      Variable dim, numElements
418//     
419//      if (rank == 0)
420//              numElements = 1
421//      else
422//              numElements = di.dims[0]
423//              for(dim=1; dim<rank; dim+=1)
424//                      numElements *= di.dims[dim]             
425//              endfor
426//      endif
427//
428//#if Exists("HDF5LoadData")   
429//      strswitch(di.datatype_class_str)
430//              case "H5T_INTEGER":
431//              case "H5T_FLOAT":
432//              case "H5T_ENUM":
433//              case "H5T_OPAQUE":
434//              case "H5T_BITFIELD":
435//                      if (numElements > 100)
436//                              value = "<Too big to display here>"     // It would take too long to load.
437//                              break
438//                      endif
439//                     
440//                      HDF5LoadData /A=attributeName /N=tempNumericAttributeWave /O /Q /TYPE=(objectType) /VAR=0 /Z locationID, fullPath
441//                      if (V_flag != 0)
442//                              value = "ERROR!"
443//                      else
444//                              Wave tempNumericAttributeWave
445//                             
446//                              if (rank > 1)
447//                                      // So we can treat multi-dimensional wave as one big row.
448//                                      Redimension/N=(numElements)/E=1 tempNumericAttributeWave
449//                              endif
450//                             
451//                              value = NI2_GetNumericPreviewString(tempNumericAttributeWave)
452//                      endif
453//                      KillWaves/Z tempNumericAttributeWave
454//                      break                           
455//
456//              case "H5T_REFERENCE":
457//                      if (numElements > 10)
458//                              value = "<Too big to display here>"     // It would take too long to load.
459//                              break
460//                      endif
461//             
462//                      HDF5LoadData /A=attributeName /N=tempTextAttributeWave /O /Q /TYPE=(objectType) /VAR=0 /Z locationID, fullPath
463//                      if (V_flag != 0)
464//                              value = "ERROR!"
465//                      else
466//                              if (rank > 1)
467//                                      wave tempTextAttributeWave
468//                                      // So we can treat multi-dimensional wave as one big row.
469//                                      Redimension/N=(numElements)/E=1 tempTextAttributeWave
470//                              endif
471//                             
472//                              // Remove the prefix (e.g., "D:" for a dataset, which is there for
473//                              // programmatic use but would confuse in a preview.
474//                              Wave/T references = tempTextAttributeWave                       // Created by HDF5LoadData
475//                              String tmp
476//                              Variable npnts=numpnts(references), len
477//                              Variable i
478//                              for(i=0; i<npnts; i+=1)
479//                                      tmp = references[i]
480//                                      len = strlen(tmp)
481//                                      references[i] = tmp[2,len]
482//                              endfor
483//                             
484//                              value = NI2_GetTextPreviewString(references)
485//                      endif
486//                      KillWaves/Z tempTextAttributeWave
487//                      break                           
488//
489//              case "H5T_STRING":
490//                      if (numElements > 100)
491//                              value = "<Too big to display here>"     // It would take too long to load.
492//                              break
493//                      endif
494//             
495//                      HDF5LoadData /A=attributeName /N=tempTextAttributeWave /O /Q /TYPE=(objectType) /VAR=0 /Z locationID, fullPath
496//                      if (V_flag != 0)
497//                              value = "ERROR!"
498//                      else
499//                              if (rank > 1)
500//                                      // So we can treat multi-dimensional wave as one big row.
501//                                      Redimension/N=(numElements)/E=1 tempTextAttributeWave
502//                              endif
503//                              value = NI2_GetTextPreviewString(tempTextAttributeWave)
504//                      endif
505//                      KillWaves/Z tempTextAttributeWave
506//                      break                           
507//                     
508//              case "H5T_TIME":
509//              case "H5T_COMPOUND":
510//              case "H5T_VLEN":
511//              case "H5T_ARRAY":
512//                      value = "<Can't display this type here>"
513//                      break
514//      endswitch
515//     
516//      return value
517//#else
518//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
519//#endif
520//End
521//
522//static Function FillDatasetsList(bd)
523//      STRUCT NI2HDF5BrowserData &bd
524//
525//#if Exists("HDF5ListGroup")   
526//      HDF5ListGroup /TYPE=2 bd.fileID, bd.groupPath
527//      Variable numItemsInList = ItemsInList(S_HDF5ListGroup)
528//     
529//      if (numItemsInList == 0)
530//              Redimension/N=0 bd.datasetsList
531//      else
532//              Redimension/N=(numItemsInList, 5) bd.datasetsList
533//              SetDimLabel 1, 0, Dataset, bd.datasetsList
534//              SetDimLabel 1, 1, Rank, bd.datasetsList
535//              SetDimLabel 1, 2, 'Dim Sizes', bd.datasetsList
536//              SetDimLabel 1, 3, Type, bd.datasetsList
537//              SetDimLabel 1, 4, Value, bd.datasetsList
538//              bd.datasetsList[][0] = StringFromList(p, S_HDF5ListGroup)
539//     
540//              String dataset
541//              Variable i, numDatasets
542//              Variable err
543//              numDatasets = ItemsInList(S_HDF5ListGroup)
544//              for(i=0; i<numDatasets; i+=1)
545//                      dataset = StringFromList(i, S_HDF5ListGroup)
546//                      String fullPath = NI2_HDF5GetObjectFullPath(bd.groupPath, dataset)
547//#if(IgorVersion()<9)
548//                      STRUCT NI2_HDF5DataInfo di
549//                      NI2_InitHDF5DataInfo(di)                        // Set input fields.
550//                      HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
551//#else
552//                      STRUCT HDF5DataInfo di
553//                      InitHDF5DataInfo(di)                    // Set input fields.
554//                      err = HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
555//#endif               
556//                     
557//                     
558//                      Variable rank = di.ndims
559//                      bd.datasetsList[i][1] = num2istr(rank)
560//                     
561//                      String dimsStr=""
562//                      Variable dim
563//                      for(dim=0; dim<rank; dim+=1)
564//                              dimsStr += num2istr(di.dims[dim]) + ";"
565//                      endfor
566//                      bd.datasetsList[i][2] = dimsStr
567//
568//                      bd.datasetsList[i][3] = di.datatype_str
569//
570//                      String preview = NI2_GetPreviewString(bd.fileID, 2, di, fullPath, "")
571//                      bd.datasetsList[i][4] = preview
572//              endfor
573//      endif
574//#else
575//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
576//#endif
577//End
578//             
579//static Function FillGroupAttributesList(bd)
580//      STRUCT NI2HDF5BrowserData &bd
581//
582//#if Exists("HDF5ListAttributes")     
583//      Variable numAttributes = 0
584//      String groupPath = bd.groupPath
585//      if (strlen(groupPath) > 0)
586//              HDF5ListAttributes/TYPE=1 bd.fileID, groupPath
587//              numAttributes = ItemsInList(S_HDF5ListAttributes)
588//      endif
589//     
590//      if (numAttributes == 0)
591//              Redimension/N=0 bd.groupAttributesList
592//      else
593//              Redimension/N=(numAttributes, 5) bd.groupAttributesList
594//              SetDimLabel 1, 0, Attribute,bd.groupAttributesList
595//              SetDimLabel 1, 1, Rank,bd.groupAttributesList
596//              SetDimLabel 1, 2, 'Dim Sizes',bd.groupAttributesList
597//              SetDimLabel 1, 3, Type,bd.groupAttributesList
598//              SetDimLabel 1, 4, Value,bd.groupAttributesList
599//              bd.groupAttributesList[][0] = StringFromList(p, S_HDF5ListAttributes)
600//     
601//              String attribute
602//              Variable i
603//              for(i=0; i<numAttributes; i+=1)
604//                      String attributeName
605//                      attributeName = StringFromList(i, S_HDF5ListAttributes)
606//                      attribute = attributeName
607//
608//                      STRUCT NI2_HDF5DataInfo di
609//                      NI2_InitHDF5DataInfo(di)                        // Set input fields.
610//                      HDF5AttributeInfo(bd.fileID, groupPath, 1, attribute, 0, di)
611//                     
612//                      Variable rank = di.ndims
613//                      bd.groupAttributesList[i][1] = num2istr(rank)
614//                     
615//                      String dimsStr=""
616//                      Variable dim
617//                      for(dim=0; dim<rank; dim+=1)
618//                              dimsStr += num2istr(di.dims[dim]) + ";"
619//                      endfor
620//                      bd.groupAttributesList[i][2] = dimsStr
621//
622//                      bd.groupAttributesList[i][3] = di.datatype_str
623//
624//                      String preview = NI2_GetPreviewString(bd.fileID, 1, di, groupPath, attributeName)
625//                      bd.groupAttributesList[i][4] = preview
626//              endfor
627//      endif
628//#else
629//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
630//#endif
631//End
632//             
633//static Function FillDatasetAttributesList(bd)
634//      STRUCT NI2HDF5BrowserData &bd
635//
636//#if Exists("HDF5ListAttributes")     
637//      Variable numAttributes = 0
638//      String datasetPath = NI2_SelectedDatasetPath(bd)
639//      if (strlen(datasetPath) > 0)
640//              HDF5ListAttributes/TYPE=2 bd.fileID, datasetPath
641//              numAttributes = ItemsInList(S_HDF5ListAttributes)
642//      endif
643//     
644//      if (numAttributes == 0)
645//              Redimension/N=0 bd.datasetAttributesList
646//      else
647//              Redimension/N=(numAttributes, 5) bd.datasetAttributesList
648//              SetDimLabel 1, 0, Attribute,bd.datasetAttributesList
649//              SetDimLabel 1, 1, Rank,bd.datasetAttributesList
650//              SetDimLabel 1, 2, 'Dim Sizes',bd.datasetAttributesList
651//              SetDimLabel 1, 3, Type,bd.datasetAttributesList
652//              SetDimLabel 1, 4, Value,bd.datasetAttributesList
653//              bd.datasetAttributesList[][0] = StringFromList(p, S_HDF5ListAttributes)
654//     
655//              String attribute
656//              Variable i
657//              for(i=0; i<numAttributes; i+=1)
658//                      String attributeName
659//                      attributeName = StringFromList(i, S_HDF5ListAttributes)
660//                      attribute = attributeName
661//
662//                      STRUCT NI2_HDF5DataInfo di
663//                      NI2_InitHDF5DataInfo(di)                        // Set input fields.
664//                      HDF5AttributeInfo(bd.fileID, datasetPath, 2, attribute, 0, di)
665//                     
666//                      Variable rank = di.ndims
667//                      bd.datasetAttributesList[i][1] = num2istr(rank)
668//                     
669//                      String dimsStr=""
670//                      Variable dim
671//                      for(dim=0; dim<rank; dim+=1)
672//                              dimsStr += num2istr(di.dims[dim]) + ";"
673//                      endfor
674//                      bd.datasetAttributesList[i][2] = dimsStr
675//
676//                      bd.datasetAttributesList[i][3] = di.datatype_str
677//
678//                      String preview = NI2_GetPreviewString(bd.fileID, 2, di, datasetPath, attributeName)
679//                      bd.datasetAttributesList[i][4] = preview
680//              endfor
681//      endif
682//#else
683//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
684//#endif
685//End
686//     
687//static Function FillLists(bd)
688//      STRUCT NI2HDF5BrowserData &bd
689//
690//      if (bd.fileID == 0)                                                     // No file is open?
691//              Redimension/N=(0) bd.groupsList
692//              Redimension/N=(0) bd.groupAttributesList
693//              Redimension/N=(0) bd.datasetsList
694//              Redimension/N=(0) bd.datasetAttributesList
695//              return -1
696//      endif
697//     
698//      Variable numItemsInList
699//      String hierarchy
700//     
701//      // Show entire hierarchy in Groups list.
702//      hierarchy = GetFileHierarchy(bd, 0)     
703//      numItemsInList = ItemsInList(hierarchy)
704//      Redimension/N=(numItemsInList) bd.groupsList
705//      bd.groupsList = StringFromList(p, hierarchy)
706//     
707//      // The groupFullPaths wave stores the full path to each group
708//      hierarchy = GetFileHierarchy(bd, 1)     
709//      numItemsInList = ItemsInList(hierarchy)
710//      Redimension/N=(numItemsInList) bd.groupFullPaths
711//      bd.groupFullPaths = StringFromList(p, hierarchy)
712//     
713//      // Show datasets in current group in Datasets list.
714//      FillDatasetsList(bd)
715//     
716//      // Show attributes of currently-selected group.
717//      FillGroupAttributesList(bd)
718//     
719//      // Show attributes of currently-selected dataset.
720//      FillDatasetAttributesList(bd)
721//End
722//
723//Function/S NI2_SelectedGroupName(bd)
724//      STRUCT NI2HDF5BrowserData &bd
725//     
726//      if (numpnts(bd.groupsList) == 0)
727//              return ""
728//      endif
729//
730//      ControlInfo/W=$bd.browserName GroupsList
731//      Variable selRow = V_value
732//      String groupName = bd.groupsList[selRow]
733//
734//      // Group names may have leading spaces at this point. The spaces are used to create
735//      // indentation in the list to show the hierarchy. We must remove the leading spaces.
736//      sscanf groupName, " %s", groupName
737//
738//      if (strlen(groupName) > 0)
739//              return groupName
740//      endif
741//
742//      return ""
743//End
744//
745//Function/S NI2_SelectedGroupPath(bd)
746//      STRUCT NI2HDF5BrowserData &bd
747//     
748//      String groupPath = bd.groupPath
749//
750//      return groupPath
751//End
752//
753//Function/S NI2_SelectedDatasetName(bd)
754//      STRUCT NI2HDF5BrowserData &bd
755//     
756//      if (numpnts(bd.datasetsList) == 0)
757//              return ""
758//      endif
759//
760//      ControlInfo/W=$bd.browserName DatasetsList
761//      Variable selRow = V_value
762//      String datasetName = bd.datasetsList[selRow][0]
763//      if (strlen(datasetName) > 0)
764//              return datasetName
765//      endif
766//
767//      return ""
768//End
769//
770//Function/S NI2_SelectedDatasetPath(bd)
771//      STRUCT NI2HDF5BrowserData &bd
772//
773//      String datasetName = NI2_SelectedDatasetName(bd)
774//      if (strlen(datasetName) == 0)
775//              return ""                                               // Nothing is selected
776//      endif
777//     
778//      String datasetPath = bd.groupPath
779//      if (CmpStr(datasetPath[strlen(datasetPath)-1],"/") != 0)
780//              datasetPath += "/"
781//      endif
782//      datasetPath += datasetName
783//
784//      return datasetPath
785//End
786//
787//Function/S NI2_SelectedAttributeName(bd, isGroupAttribute)
788//      STRUCT NI2HDF5BrowserData &bd
789//      Variable isGroupAttribute
790//
791//      String controlName
792//      if (isGroupAttribute)
793//              controlName = "GroupAttributesList"
794//              Wave/T list = bd.groupAttributesList
795//      else
796//              controlName = "DatasetAttributesList"
797//              Wave/T list = bd.datasetAttributesList
798//      endif
799//     
800//      if (numpnts(list) == 0)
801//              return ""
802//      endif
803//
804//      ControlInfo/W=$bd.browserName $controlName
805//      Variable selRow = V_value
806//      String attributeName = list[selRow][0]
807//     
808//      if (strlen(attributeName) > 0)
809//              return attributeName
810//      endif
811//
812//      return ""
813//End
814//
815//Function/S NI2_SelectedAttributePath(bd, isGroupAttribute)
816//      STRUCT NI2HDF5BrowserData &bd
817//      Variable isGroupAttribute
818//
819//      String attributeName = NI2_SelectedAttributeName(bd, isGroupAttribute)
820//      if (strlen(attributeName) == 0)
821//              return ""                                               // Nothing is selected
822//      endif
823//     
824//      String path
825//      if (isGroupAttribute)
826//              path = NI2_SelectedGroupPath(bd)
827//      else
828//              path = NI2_SelectedDatasetPath(bd)
829//      endif
830//     
831//      path += "/" + attributeName
832//
833//      return path
834//End
835//
836//StrConstant NI2_kLoadAllMembersString = "_Load_All_Members_"
837//
838//static Function SetMembersPopupMenu(bd)
839//      STRUCT NI2HDF5BrowserData &bd
840//     
841//#if Exists("HDF5OpenFile")   
842//      Variable hideMembers
843//      String memberList
844//
845//      hideMembers = 1
846//      memberList = NI2_kLoadAllMembersString + ";"
847//     
848//      if (bd.fileID != 0)                             // File is open for this browser?
849//              String fullPath
850//             
851//              fullPath = NI2_SelectedDatasetPath(bd)
852//              if (strlen(fullPath) > 0)
853//                      STRUCT NI2_HDF5DataInfo di
854//                      NI2_InitHDF5DataInfo(di)
855//                      HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
856//                      if (CmpStr(di.datatype_class_str, "H5T_COMPOUND") == 0)
857//                              hideMembers = 0
858//                             
859//                              ControlInfo /W=$bd.browserName Members
860//                              Variable selectedItemNumber = V_Value
861//                              STRUCT NI2_HDF5DatatypeInfo dti
862//                              NI2_InitHDF5DatatypeInfo(dti)
863//                              if (HDF5TypeInfo(bd.fileID, fullPath, "", "", 1, dti))
864//                                      memberList += "HDF5TypeInfo Error!"
865//                              else
866//                                      memberList += dti.names
867//                                      if (selectedItemNumber > dti.nmembers+1)        // +1 because of "_Load_All_Members_" item.
868//                                              selectedItemNumber = 1          // Force menu selection to be in bounds.
869//                                      endif
870//                              endif
871//                              PopupMenu Members, win=$bd.browserName, mode=selectedItemNumber
872//                      endif
873//              endif
874//      endif
875//     
876//      PopupMenu Members, win=$bd.browserName, disable=hideMembers
877//     
878//      String cmd                              // What a pain. Can't use local variable with PopupMenu value=
879//      sprintf cmd, "PopupMenu Members, win=%s, value=\"%s\"", bd.browserName, memberList
880//      Execute cmd
881//#else
882//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
883//#endif
884//End
885//
886//Function NI2_HDF5GetReadOnlySetting(browserName)
887//      String browserName
888//     
889//      Variable result
890//      ControlInfo /W=$browserName ReadOnly
891//      result = V_value
892//      return result
893//End
894//
895//Function NI2_HDF5GetCompLoadInfo(bd, isCompound, compMode, memberName)
896//      STRUCT NI2HDF5BrowserData &bd
897//      Variable &isCompound                                    // Output: If non-zero, a compound dataset is selected.
898//      Variable &compMode                                              // Output: Value suitable for passing to HDF5LoadData /COMP flag.
899//      String &memberName                                              // Output: If "" load all members.
900//     
901//      isCompound = 0
902//      memberName = ""
903//     
904//      ControlInfo /W=$bd.browserName Members
905//      if (V_disable == 0)
906//              isCompound = 1
907//              memberName = S_value
908//              if (CmpStr(memberName, NI2_kLoadAllMembersString) == 0)
909//                      memberName = ""
910//              endif
911//      endif
912//
913//      compMode = isCompound && strlen(memberName)>0
914//End
915//
916//Function NI2_HDF5GetTranspose2DSetting(browserName)
917//      String browserName
918//     
919//      Variable result
920//      ControlInfo /W=$browserName Transpose2DDatasets
921//      result = V_value
922//      return result
923//End
924//
925//static Function HDF5GetLoadDatasetOptions(browserName, tableDisplayMode, graphDisplayMode)
926//      String browserName
927//      Variable &tableDisplayMode, &graphDisplayMode
928//     
929//      ControlInfo /W=$browserName DisplayInTable
930//      tableDisplayMode = V_value - 1                                          // 0=no; 1=display; 2=append
931//     
932//      ControlInfo /W=$browserName DisplayInGraph
933//      graphDisplayMode = V_value - 1                                          // 0=no; 1=display; 2=append
934//     
935//      return tableDisplayMode || graphDisplayMode
936//End
937//
938//static Function MembersPopupProc(ctrlName,popNum,popStr) : PopupMenuControl
939//      String ctrlName
940//      Variable popNum
941//      String popStr
942//     
943//      String browserName = NI2_HDF5GetTopBrowserName()
944//     
945//      STRUCT NI2HDF5BrowserData bd
946//      SetNI2HDF5BrowserData(browserName, bd)
947//     
948//      NI2_HDF5DisplaySelectedDataset(bd)
949//End
950//
951//static Function SetButtonStates(bd)
952//      STRUCT NI2HDF5BrowserData &bd
953//     
954//      if (bd.fileID == 0)                             // No file is open for this browser?
955//              Button CreateFile, win=$bd.browserName, disable=2               // Enable Create
956//              Button OpenFile, win=$bd.browserName, disable=0         // Enable Open
957//              Button CloseFile, win=$bd.browserName, disable=2                // Disable Close
958//              Button LoadGroup, win=$bd.browserName, disable=2                // Disable Load Group
959//              Button SaveDataFolder, win=$bd.browserName, disable=2   // Disable Save Data Folder
960//              Button LoadDataset, win=$bd.browserName, disable=2      // Disable Load Dataset
961//              Button SaveWaves, win=$bd.browserName, disable=2                // Disable Save Waves
962//      else
963//              Button CreateFile, win=$bd.browserName, disable=2               // Disable Create
964//              Button OpenFile, win=$bd.browserName, disable=2         // Disable Open
965//              Button CloseFile, win=$bd.browserName, disable=0                // Enable Close
966//             
967//              String groupName = NI2_SelectedGroupName(bd)
968//              Variable code = strlen(groupName) > 0 ? 0:2
969//              Button LoadGroup, win=$bd.browserName, disable=code     // Enable Load Group
970//              code = bd.readOnly == 0 ? 0:2
971//              Button SaveDataFolder, win=$bd.browserName, disable=code        // Enable Save Data Folder
972//             
973//              String datasetName = NI2_SelectedDatasetName(bd)
974//              code = strlen(datasetName) > 0 ? 0:2
975//              Button LoadDataset, win=$bd.browserName, disable=code   // Enable Load Dataset
976//              code = bd.readOnly == 0 ? 0:2
977//              Button SaveWaves, win=$bd.browserName, disable=code             // Enable Save Waves
978//              //overwrite the code above...
979//              Button LoadGroup, win=$bd.browserName, disable=2        // Disable Load Dataset
980//              Button LoadDataset, win=$bd.browserName, disable=2      // Disable Load Dataset
981//      endif
982//      SetMembersPopupMenu(bd)
983//      SetGraphButtonTitle(bd.browserName)
984//      SetTableButtonTitle(bd.browserName)
985//      SetDumpButtonTitle(bd.browserName)
986//      SetVariable HyperSelectionWave, win=$bd.browserName, value= bd.hyperSelectionWavePath
987//End
988//
989//static Function DrawFilePath(bd)
990//      STRUCT NI2HDF5BrowserData &bd
991//     
992//      // TitleBox FilePath, win=$bd.browserName, title=bd.fullPath                    // This is limited to 63 characters.
993//      TitleBox FilePath, win=$bd.browserName, variable=bd.fullPath
994//End
995//
996//static Function DrawGroupPath(bd)
997//      STRUCT NI2HDF5BrowserData &bd
998//     
999//      TitleBox GroupPath, win=$bd.browserName, variable=bd.groupPath
1000//End
1001//
1002//static Function DrawDatasetInfo(bd)
1003//      STRUCT NI2HDF5BrowserData &bd
1004//     
1005//      TitleBox Dataset, win=$bd.browserName, variable=bd.datasetInfo
1006//End
1007//
1008//static Function UpdateAfterFileCreateOrOpen(isCreate, browserName, fileID, path, fileName)
1009//      Variable isCreate
1010//      String browserName
1011//      Variable fileID
1012//      String path, fileName
1013//     
1014//      STRUCT NI2HDF5BrowserData bd
1015//      SetNI2HDF5BrowserData(browserName, bd)
1016//
1017//      ResetListSelections(bd, 1, 1, 1, 1)
1018//
1019//      bd.fileID = fileID
1020//      bd.fileName = fileName
1021//      bd.path = path
1022//      bd.fullPath = path + fileName
1023//      DrawFilePath(bd)
1024//     
1025//      bd.readOnly = isCreate ? 0 : NI2_HDF5GetReadOnlySetting(browserName)
1026//
1027//      bd.groupPath = "/"
1028//      DrawGroupPath(bd)
1029//
1030//      SetButtonStates(bd)
1031//
1032//      FillLists(bd)
1033//     
1034//      NI2_UpdateAfterGroupSelected(bd, "/")
1035//     
1036//      String datasetName = NI2_SelectedDatasetName(bd)
1037//      if (strlen(datasetName) > 0)
1038//              NI2_SelectDataset(bd, datasetName)
1039//      endif
1040//End
1041//
1042//static Function CreateFileButtonProc(ctrlName) : ButtonControl
1043//      String ctrlName
1044//     
1045//#if Exists("HDF5OpenFile")   
1046//      String browserName = NI2_HDF5GetTopBrowserName()
1047//
1048//      STRUCT NI2HDF5BrowserData bd
1049//      SetNI2HDF5BrowserData(browserName, bd)
1050//     
1051//      Variable fileID
1052//     
1053//      HDF5CreateFile /I /O fileID  as ""
1054//      if (V_flag == 0)                // Create OK?
1055//              UpdateAfterFileCreateOrOpen(1, browserName, fileID, S_path, S_fileName)
1056//      endif
1057//#else
1058//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
1059//#endif
1060//End
1061//
1062//static Function OpenFileButtonProc(ctrlName) : ButtonControl
1063//      String ctrlName
1064//     
1065//#if Exists("HDF5OpenFile")   
1066//      String browserName = NI2_HDF5GetTopBrowserName()
1067//     
1068//      Variable readOnly = NI2_HDF5GetReadOnlySetting(browserName)
1069//     
1070//      Variable locFileID
1071//     
1072//      if (readOnly)
1073//              HDF5OpenFile/R locFileID as ""
1074//      else
1075//              HDF5OpenFile locFileID as ""
1076//      endif
1077//     
1078//      if (V_flag == 0)                                        // Open OK?
1079//              UpdateAfterFileCreateOrOpen(0, browserName, locFileID, S_path, S_fileName)
1080//      endif
1081//#else
1082//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
1083//#endif
1084//End
1085//
1086//// This detects if the file is no longer open, such as if you save the experiment, quit Igor and then reopen the experiment.
1087//Function NI2_FileWasUnexpectedlyClosed(bd)
1088//      STRUCT NI2HDF5BrowserData &bd
1089//
1090//#if Exists("HDF5OpenFile")   
1091//      if (bd.fileID == 0)
1092//              return 0                                // File is closed but not unexpectedly.
1093//      endif
1094//     
1095//      HDF5ListAttributes/Q /TYPE=1 /Z bd.fileID , "/"         // Try to list the attributes of the root of the file.
1096//      if (V_flag != 0)
1097//              return 1                                                                // Error: Assume file was closed.
1098//      endif
1099//     
1100//      return 0
1101//#else
1102//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
1103//#endif
1104//End
1105//
1106//static Function FileWasClosed(bd)                     // Does cleanup after a file is closed.
1107//      STRUCT NI2HDF5BrowserData &bd
1108//
1109//      bd.fileID = 0
1110//      Redimension/N=(0) bd.groupFullPaths
1111//      bd.groupPath = ""
1112//      bd.fileName = ""
1113//      bd.path = ""
1114//      bd.fullPath = ""
1115//      bd.datasetInfo = ""
1116//
1117//      DrawFilePath(bd)
1118//      SetButtonStates(bd)
1119//      FillLists(bd)
1120//End
1121//
1122//static Function CloseFileButtonProc(ctrlName) : ButtonControl
1123//      String ctrlName
1124//     
1125//#if Exists("HDF5OpenFile")   
1126//      String browserName = NI2_HDF5GetTopBrowserName()
1127//
1128//      STRUCT NI2HDF5BrowserData bd
1129//      SetNI2HDF5BrowserData(browserName, bd)
1130//
1131//      HDF5CloseFile bd.fileID
1132//      CloseSavePanels()
1133//      FileWasClosed(bd)
1134//#else
1135//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
1136//#endif
1137//End
1138//
1139//static Function LoadDatasetButtonProc(ctrlName) : ButtonControl
1140//      String ctrlName
1141//
1142//#if Exists("HDF5OpenFile")   
1143//      String browserName
1144//      STRUCT NI2HDF5BrowserData bd
1145//     
1146//      if(stringmatch(ctrlName,"AddGrouptoList"))
1147//             
1148//              browserName = NI2_HDF5GetTopBrowserName()
1149//     
1150//              SetNI2HDF5BrowserData(browserName, bd)
1151//             
1152//              Wave/T DataSetNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":DataSetNames")
1153//              Wave/T GroupNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":GroupNames")
1154//              SVAR BrowserNameFldr=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":BrowserNameFldr")
1155//              Redimension/N=(numpnts(DataSetNames)+1) GroupNames
1156//              GroupNames[numpnts(GroupNames)-1]=NI2_SelectedGroupPath(bd)
1157//              BrowserNameFldr = NI2_HDF5GetTopBrowserName()
1158//      elseif(stringmatch(ctrlName,"ClearDatasetList"))
1159//              browserName = NI2_HDF5GetTopBrowserName()       
1160//              SetNI2HDF5BrowserData(browserName, bd)         
1161//              Wave/T DataSetNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":DataSetNames")
1162//              Wave/T GroupNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":GroupNames")
1163//              SVAR BrowserNameFldr=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":BrowserNameFldr")
1164//              Redimension/N=(0) DataSetNames, GroupNames
1165////            DataSetNames[numpnts(DataSetNames)-1]=NI2_SelectedDatasetPath(bd)
1166//              BrowserNameFldr = NI2_HDF5GetTopBrowserName()           
1167//      else            //Old LoadDataset button...
1168//     
1169//              browserName = NI2_HDF5GetTopBrowserName()
1170//     
1171//              SetNI2HDF5BrowserData(browserName, bd)
1172//             
1173//              String datasetPath = NI2_SelectedDatasetPath(bd)
1174//     
1175//              String slabWaveStr = ""
1176//              ControlInfo /W=$bd.browserName UseHyperSelection
1177//              if (V_value)                                                            // Use Hyperselection is checked?
1178//                      slabWaveStr = bd.hyperSelectionWavePath
1179//              endif
1180//              WAVE/Z slabWave = $slabWaveStr                  // It is OK if wave does not exist and slabWave is NULL. HDF5LoadData will simply ignore /SLAB.
1181//             
1182//              Variable isCompound
1183//              String memberName
1184//              Variable compMode
1185//              NI2_HDF5GetCompLoadInfo(bd, isCompound, compMode, memberName)
1186//     
1187//              // If isFormalImage is true, we are loading an image written
1188//              // according to the HDF5 Image and Palette Specification.
1189//              Variable isFormalImage = 0
1190//              if (!isCompound)
1191//                      String savedDataFolder = NI2_SetBrowserDataFolder("")                   // tempClassAttribute goes in master HDF5Browser data folder
1192//                      HDF5LoadData /Z /O /N=tempClassAttribute /A="CLASS" /Q /VAR=1 bd.fileID, datasetPath
1193//                      if (V_flag == 0)
1194//                              WAVE/T tempClassAttribute                       // HDF5LoadData will have created this string
1195//                              if (CmpStr(tempClassAttribute[0],"IMAGE") == 0)
1196//                                      isFormalImage = 1
1197//                              endif   
1198//                              KillWaves/Z tempClassAttribute
1199//                      endif
1200//                      SetDataFolder savedDataFolder
1201//              endif
1202//             
1203//              Variable tableDisplayMode, graphDisplayMode             // 0=no; 1=display; 2=append
1204//              HDF5GetLoadDatasetOptions(bd.browserName, tableDisplayMode, graphDisplayMode)
1205//             
1206//              if (isFormalImage)
1207//                      HDF5LoadImage /O /GRPH=(graphDisplayMode) /T=(tableDisplayMode) bd.fileID, datasetPath
1208//              else
1209//                      Variable transpose2D = NI2_HDF5GetTranspose2DSetting(bd.browserName)
1210//                      HDF5LoadData /O /SLAB=slabWave /TRAN=(transpose2D) /COMP={compMode,memberName} /GRPH=(graphDisplayMode) /T=(tableDisplayMode) bd.fileID, datasetPath
1211//              endif
1212//      endif
1213//#else
1214//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
1215//#endif
1216//End
1217//
1218//static Function LoadGroupButtonProc(ctrlName) : ButtonControl
1219//      String ctrlName
1220//
1221//#if Exists("HDF5OpenFile")   
1222//      String browserName = NI2_HDF5GetTopBrowserName()
1223//
1224//      STRUCT NI2HDF5BrowserData bd
1225//      SetNI2HDF5BrowserData(browserName, bd)
1226//     
1227//      String groupPath = NI2_SelectedGroupPath(bd)
1228//
1229//      ControlInfo /W=$bd.browserName LoadGroupsRecursively
1230//      if (V_value)                                                                    // Use LoadGroupsRecursively is checked?
1231//              HDF5LoadGroup /O /R /T /IMAG=1 :, bd.fileID, groupPath
1232//      else
1233//              HDF5LoadGroup /O /T /IMAG=1 :, bd.fileID, groupPath
1234//      endif
1235//
1236//      // For debugging
1237//      Variable numItems
1238//      Variable debug = 1
1239//      if (debug)
1240//              Wave/Z/T groupPaths = root:groupPaths
1241//              if (WaveExists(groupPaths))
1242//                      numItems = ItemsInList(S_groupPaths)
1243//                      Redimension/N=(numItems) groupPaths
1244//                      groupPaths = StringFromList(p, S_groupPaths)
1245//              endif
1246//
1247//              Wave/Z/T dataFolderPaths = root:dataFolderPaths
1248//              if (WaveExists(dataFolderPaths))
1249//                      numItems = ItemsInList(S_dataFolderPaths)
1250//                      Redimension/N=(numItems) dataFolderPaths
1251//                      dataFolderPaths = StringFromList(p, S_dataFolderPaths)
1252//              endif
1253//
1254//              Wave/Z/T wavePaths = root:wavePaths
1255//              if (WaveExists(wavePaths))
1256//                      numItems = ItemsInList(S_objectPaths)
1257//                      Redimension/N=(numItems) wavePaths
1258//                      wavePaths = StringFromList(p, S_objectPaths)
1259//              endif
1260//      endif
1261//#else
1262//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
1263//#endif
1264//End
1265//
1266Function NI2_AttachListWaves(bd)
1267        STRUCT HDF5BrowserData &bd
1268       
1269        ListBox GroupsList win=$bd.browserName, listWave=bd.groupsList
1270        ListBox GroupAttributesList win=$bd.browserName, listWave=bd.groupAttributesList
1271        ListBox DatasetsList win=$bd.browserName, listWave=bd.datasetsList
1272        ListBox DatasetAttributesList win=$bd.browserName, listWave=bd.datasetAttributesList
1273End
1274//
1275//Function NI2_HDF5BrowserPanelHook(infoStr)
1276//      String infoStr
1277//
1278//#if Exists("HDF5OpenFile")   
1279//      String browserName= StringByKey("WINDOW",infoStr)
1280//      String event= StringByKey("EVENT",infoStr)
1281//
1282//      STRUCT NI2HDF5BrowserData bd
1283//      SetNI2HDF5BrowserData(browserName, bd)
1284//
1285//      strswitch(event)
1286//              case "activate":                                // We do not get this on Windows when the panel is first created.
1287//                      // This detects if the file is no longer open, such as if you save the experiment, quit Igor and then reopen the experiment.
1288//                      if (NI2_FileWasUnexpectedlyClosed(bd))
1289//                              Printf "The file \"%s\" is no longer open.\r", bd.fileName
1290//                              FileWasClosed(bd)
1291//                      endif
1292//                     
1293//                      SetGraphButtonTitle(browserName)
1294//                      SetTableButtonTitle(browserName)
1295//                      SetDumpButtonTitle(browserName)
1296//                      break
1297//
1298//              case "resize":
1299//                      NI2_HDF5ResizeBrowser(browserName)
1300//                      break
1301//                     
1302//              case "moved":                   // This message was added in Igor Pro 5.04B07.
1303//                      // If this is the last HDF5 browser, save the browser window size and position.
1304//                      if (strlen(NI2_HDF5GetIndxBrowserName(1)) == 0)
1305//                              SetPrefWindowCoords(browserName)
1306//                      endif
1307//                      break
1308//                     
1309//              case "kill":
1310//                      if (bd.fileID != 0)
1311//                              HDF5CloseFile bd.fileID
1312//                              bd.fileID = 0
1313//                              CloseSavePanels()
1314//                      endif
1315//                      KillDataFolder root:Packages:HDF5Browser:$browserName
1316//                      break
1317//      endswitch
1318//     
1319//      return 0
1320//#else
1321//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
1322//#endif
1323//End
1324//
1325//Function NI2_SelectDataset(bd, datasetName)
1326//      STRUCT NI2HDF5BrowserData &bd
1327//      String datasetName
1328//
1329//#if Exists("HDF5OpenFile")   
1330//      String info
1331//
1332//      if (strlen(datasetName) == 0)
1333//              info = ""
1334//      else
1335//              String fullPath
1336//              fullPath = NI2_HDF5GetObjectFullPath(bd.groupPath, datasetName)
1337//              STRUCT NI2_HDF5DataInfo di
1338//              NI2_InitHDF5DataInfo(di)                        // Set input fields.
1339//              HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
1340//              // Print s
1341//              sprintf info, "%s, class=%s", datasetName, di.datatype_class_str
1342//      endif
1343//      bd.datasetInfo = info
1344//      DrawDatasetInfo(bd)
1345//      SetButtonStates(bd)
1346//      FillDatasetAttributesList(bd)
1347//#else
1348//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
1349//#endif
1350//End
1351//
1352//Function NI2_UpdateAfterGroupSelected(bd, fullGroupPath)
1353//      STRUCT NI2HDF5BrowserData &bd
1354//      String fullGroupPath
1355//     
1356//      Variable selectedGroupChanged = CmpStr(bd.groupPath, fullGroupPath) != 0
1357//
1358//      bd.groupPath = fullGroupPath
1359//      DrawGroupPath(bd)
1360//      FillGroupAttributesList(bd)
1361//      FillDatasetsList(bd)
1362//
1363//      if (selectedGroupChanged)
1364//              ResetListSelections(bd, 0, 1, 1, 1)
1365//              String datasetName = ""
1366//              if (numpnts(bd.datasetsList) > 0)
1367//                      datasetName = bd.datasetsList[0][0]
1368//              endif
1369//              NI2_SelectDataset(bd, datasetName)
1370//      endif
1371//      SetButtonStates(bd)
1372//End
1373//
1374//static Function GroupsListActionProc(s, bd) : ListboxControl
1375//      STRUCT WMListboxAction &s
1376//      STRUCT NI2HDF5BrowserData &bd
1377//     
1378//      String browserName = s.win
1379//      Variable result = 0                                                                     // As of now, the return value must always be zero.
1380//     
1381//      switch(s.eventCode)
1382//              case 4:                                         // Cell selection
1383//                      String fullGroupPath = bd.groupFullPaths[s.row]
1384//                      NI2_UpdateAfterGroupSelected(bd, fullGroupPath)
1385//                      // Printf "Row=%d, column=%d, path=%s\r", s.row, s.col, fullGroupPath
1386//                      if (NI2_HDF5BrowserDumpIsVisible())
1387//                              NI2_HDF5DisplayDumpOfSelGroup(bd)
1388//                      endif
1389//                      break   
1390//      endswitch
1391//
1392//      return result
1393//End
1394//
1395//static Function GroupAttributesListActionProc(s, bd) : ListboxControl
1396//      STRUCT WMListboxAction &s
1397//      STRUCT NI2HDF5BrowserData &bd
1398//     
1399//      String browserName = s.win
1400//      Variable result = 0                                                                     // As of now, the return value must always be zero.
1401//     
1402//      switch(s.eventCode)
1403//              case 3:                                         // Double-click
1404//                      break;
1405//                     
1406//              case 4:                                         // Cell selection
1407//                      // Printf "Row=%d, column=%d\r", s.row, s.col
1408//                      NI2_HDF5DisplaySelAttribute(bd,  1)                             // Update various windows if they are displayed
1409//                      break   
1410//      endswitch
1411//
1412//      return result
1413//End
1414//
1415//Function NI2_HandleDatasetDoubleClick(s, bd)
1416//      STRUCT WMListboxAction &s
1417//      STRUCT NI2HDF5BrowserData &bd
1418//
1419//#if Exists("HDF5OpenFile")   
1420//      String datasetPath = NI2_SelectedDatasetPath(bd)
1421//      if (strlen(datasetPath) == 0)
1422//              return -1
1423//      endif
1424//     
1425//      STRUCT NI2_HDF5DataInfo di
1426//      NI2_InitHDF5DataInfo(di)
1427//      HDF5DatasetInfo(bd.fileID, datasetPath, 0, di)
1428//      switch(di.datatype_class)
1429//              default:
1430//                      // Load dataset here.
1431//                      break   
1432//      endswitch
1433//#else
1434//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
1435//#endif
1436//End
1437//
1438//static Function DatasetsListActionProc(s, bd) : ListboxControl
1439//      STRUCT WMListboxAction &s
1440//      STRUCT NI2HDF5BrowserData &bd
1441//     
1442//      String browserName = s.win
1443//      Variable result = 0                                                                     // As of now, the return value must always be zero.
1444//     
1445//      switch(s.eventCode)
1446//              case 3:                                         // Double-click
1447//                      NI2_HandleDatasetDoubleClick(s, bd)
1448//                      break;
1449//                     
1450//              case 4:                                         // Cell selection
1451//                      String name = bd.datasetsList[s.row][0]
1452//                      NI2_SelectDataset(bd, name)
1453//                      // Printf "Row=%d, column=%d, name=%s\r", s.row, s.col, name
1454//                      NI2_HDF5DisplaySelectedDataset(bd)                                      // Update various windows if they are displayed
1455//                      break   
1456//      endswitch
1457//     
1458//      return result
1459//End
1460//
1461//static Function DatasetAttributesListActionProc(s, bd) : ListboxControl
1462//      STRUCT WMListboxAction &s
1463//      STRUCT NI2HDF5BrowserData &bd
1464//     
1465//      String browserName = s.win
1466//      Variable result = 0                                                                     // As of now, the return value must always be zero.
1467//     
1468//      switch(s.eventCode)
1469//              case 3:                                         // Double-click
1470//                      break;
1471//                     
1472//              case 4:                                         // Cell selection
1473//                      // Printf "Row=%d, column=%d\r", s.row, s.col
1474//                      NI2_HDF5DisplaySelAttribute(bd,  0)                             // Update various windows if they are displayed
1475//                      break   
1476//      endswitch
1477//     
1478//      return result
1479//End
1480//
1481//static Function ListBoxActionProc(s) : ListboxControl
1482//      STRUCT WMListboxAction &s
1483//
1484//      String browserName = s.win
1485//
1486//      STRUCT NI2HDF5BrowserData bd
1487//      SetNI2HDF5BrowserData(browserName, bd)
1488//     
1489//      Variable result = 0                                                     // As of now, the return value must always be zero.
1490//     
1491//      strswitch(s.ctrlName)
1492//              case "GroupsList":
1493//                      result = GroupsListActionProc(s, bd)
1494//                      break
1495//                     
1496//              case "GroupAttributesList":
1497//                      result = GroupAttributesListActionProc(s, bd)
1498//                      break
1499//                     
1500//              case "DatasetsList":
1501//                      result = DatasetsListActionProc(s, bd)
1502//                      break
1503//             
1504//              case "DatasetAttributesList":
1505//                      result = DatasetAttributesListActionProc(s, bd)
1506//                      break
1507//      endswitch
1508//     
1509//      return result
1510//End
1511//
1512//static Function SetGraphButtonTitle(browserName)
1513//      String browserName
1514//     
1515//      if (NI2_HDF5BrowserGraphIsVisible())
1516//              Button Graph, win=$browserName, title="Hide Graph"
1517//      else
1518//              Button Graph, win=$browserName, title="Show Graph"
1519//      endif   
1520//End
1521//
1522//static Function GraphButtonProc(ctrlName) : ButtonControl
1523//      String ctrlName
1524//
1525//      String browserName = NI2_HDF5GetTopBrowserName()
1526//     
1527//      if (NI2_HDF5BrowserGraphIsVisible())
1528//              KillWIndow/Z HDF5BrowserGraph
1529//      else
1530//              NI2_HDF5CreateBrowserGraph()                            // Create if it does not exist.
1531//      endif
1532//      SetGraphButtonTitle(browserName)
1533//End
1534//
1535//static Function SetTableButtonTitle(browserName)
1536//      String browserName
1537//     
1538//      if (NI2_HDF5BrowserTableIsVisible())
1539//              Button Table, win=$browserName, title="Hide Table"
1540//      else
1541//              Button Table, win=$browserName, title="Show Table"
1542//      endif   
1543//End
1544//
1545//static Function TableButtonProc(ctrlName) : ButtonControl
1546//      String ctrlName
1547//
1548//      String browserName = NI2_HDF5GetTopBrowserName()
1549//     
1550//      if (NI2_HDF5BrowserTableIsVisible())
1551//              KillWIndow/Z HDF5BrowserTable
1552//      else
1553//              NI2_HDF5CreateBrowserTable()                            // Create if it does not exist.
1554//      endif
1555//      SetTableButtonTitle(browserName)
1556//End
1557//
1558//static Function SetDumpButtonTitle(browserName)
1559//      String browserName
1560//     
1561//      if (NI2_HDF5BrowserDumpIsVisible())
1562//              Button Dump, win=$browserName, title="Hide Dump"
1563//      else
1564//              Button Dump, win=$browserName, title="Show Dump"
1565//      endif   
1566//End
1567//
1568//static Function DumpButtonProc(ctrlName) : ButtonControl
1569//      String ctrlName
1570//
1571//      String browserName = NI2_HDF5GetTopBrowserName()
1572//     
1573//      if (NI2_HDF5BrowserDumpIsVisible())
1574//              Notebook HDF5DumpNotebook, visible=0
1575//      else
1576//              NI2_HDF5CreateDumpWindow()                                              // Create if it does not exist.
1577//              DoWindow/F HDF5DumpNotebook                     // Show it.
1578//      endif
1579//      SetDumpButtonTitle(browserName)
1580//End
1581//
1582//static Function HelpButtonProc(ctrlName) : ButtonControl
1583//      String ctrlName
1584//
1585//      DisplayHelpTopic "The HDF5 Browser"
1586//End
1587//
1588//static Function CreateHDF5BrowserPanel(browserName)
1589//      String browserName
1590//     
1591//      Variable isMacintosh = 0
1592//      if (CmpStr(IgorInfo(2),"Macintosh") == 0)
1593//              isMacintosh = 1
1594//      endif
1595//
1596//      // Determine panel size and position
1597//      Variable left, top, right, bottom
1598//      GetPrefWindowCoords("HDF5Browser", left, top, right, bottom)    // See if prefs set.
1599//      if (right-left<200 || bottom-top<200)
1600//              // These values are calculated to fill a typical 17 inch screen (832x624) on Macintosh.
1601//              left = 5
1602//              top = 50
1603//              right = 1020
1604//              bottom = 625
1605//      endif
1606//     
1607//      Variable readOnly, loadGroupsRecursively, transpose2DDatasets
1608//      GetPrefBrowserSettings(readOnly, loadGroupsRecursively, transpose2DDatasets)
1609//
1610//      NewPanel /W=(left, top, right, bottom)/K=1 as "HDF5 Browser"
1611//     
1612//      DoWindow/C $browserName
1613//      DoWindow/T $browserName, browserName
1614//     
1615//      // This marks this control panel as an HDF5 browser.
1616//      SetWindow kwTopWin, userdata(HDF5BrowserName)=browserName
1617//     
1618//      SetDrawLayer ProgBack
1619//
1620//      SetDrawEnv fstyle= 1
1621//      DrawText 18,75,"File:"
1622//
1623//      SetDrawEnv fstyle= 1
1624//      DrawText 18,103,"Selected Group:"
1625//
1626//      SetDrawEnv fstyle= 1
1627//      DrawText 18,130,"Selected Dataset:"
1628//
1629//      TitleBox FilePath,pos={55,57},size={706,21}
1630//
1631//      left = isMacintosh ? 150 : 125
1632//      TitleBox GroupPath,pos={left,86},size={658,20}
1633//      TitleBox Dataset,pos={left,113},size={13,21}
1634//
1635//      CheckBox UseHyperSelection,pos={15,155},size={110,14},title="Use Hyperselection",value= 0
1636//      CheckBox UseHyperSelection,help={"For experts only. Allows loading a subset of a dataset."}
1637//
1638//      SetVariable HyperSelectionWave,pos={140,155},size={340,16},title="Hyper Selection Wave:"
1639//      SetVariable HyperSelectionWave,help={"Enter full path to wave containing hyperselection information. See HDF5LoadData /SLAB keyword help."}
1640//
1641//      CheckBox LoadGroupsRecursively,pos={15,181},size={137,14},title="Load Groups Recursively",value=loadGroupsRecursively
1642//      CheckBox LoadGroupsRecursively,proc=HDF5BrowserPrefCheckboxProc,help={"When checked, the Load Group button loads subgroups."}
1643//     
1644//      Button CreateFile,pos={15,8},size={125,20},proc=NikaHDF5Browser#CreateFileButtonProc,title="Create HDF5 File", disable=1
1645//      Button OpenFile,pos={159,8},size={125,20},proc=NikaHDF5Browser#OpenFileButtonProc,title="Open HDF5 File"
1646//      Button CloseFile,pos={296,8},size={125,20},proc=NikaHDF5Browser#CloseFileButtonProc,title="Close HDF5 File"
1647//      Button Help,pos={435,8},size={50,20},proc=NikaHDF5Browser#HelpButtonProc,title="Help"
1648//      CheckBox ReadOnly,pos={186,32},size={68,14},title="Read Only",proc=HDF5BrowserPrefCheckboxProc,value=readOnly
1649//
1650//      // Start Preview
1651//
1652//      Button Graph,pos={556,27},size={90,20},proc=NikaHDF5Browser#GraphButtonProc,title="Show Graph"
1653//      Button Graph help={"Shows or hides a graph which displays the last dataset or attribute that you selected."}
1654//
1655//      Button Table,pos={672,27},size={90,20},proc=NikaHDF5Browser#TableButtonProc,title="Show Table"
1656//      Button Table help={"Shows or hides a table which displays the last dataset or attribute that you selected."}
1657//
1658//      Button Dump,pos={556,59},size={90,20},proc=NikaHDF5Browser#DumpButtonProc,title="Show Dump"
1659//      Button Dump help={"Shows or hides a window which displays a dump of the last dataset or attribute that you selected."}
1660//
1661//      CheckBox ShowAttributesInDump,pos={653,71},size={100,14},title="Show Attributes In Dump"
1662//      CheckBox ShowAttributesInDump help={"Check to display the dataset's attributes in the dump window."}
1663//
1664//      CheckBox ShowDataInDump,pos={653,56},size={114,14},title="Show Data In Dump"
1665//      CheckBox ShowDataInDump,help={"Check to display data in the dump window. For large datasets this can take a long time."}
1666//
1667//      GroupBox PreviewOptions,pos={543,5},size={258,87},title="Preview Options"
1668//
1669//      // End Preview
1670//
1671//      TitleBox GroupsTitle,pos={15,230},size={50,16},disable=2,title="Groups",fSize=14
1672//      TitleBox GroupsTitle,frame=0,fStyle=1
1673//
1674//      ListBox GroupsList,pos={15,250},size={306,170}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
1675//      ListBox GroupsList,fSize=14
1676//
1677//      Button LoadGroup,pos={80,224},size={100,20},proc=NikaHDF5Browser#LoadGroupButtonProc,title="Load Group"
1678//      Button LoadGroup,help={"Loads the currently selected group into the current data folder."}
1679//
1680//      Button SaveDataFolder,pos={194,224},size={120,20},proc=NikaHDF5Browser#SaveDataFolderButtonProc,title="Save Data Folder"
1681//      Button SaveDataFolder,help={"Saves a data folder in the currently selected group. Available if the current HDF5 file is open for read/write."}
1682//
1683//      TitleBox GroupAttributesTitle,pos={15,435},size={111,16},disable=2,title="Group Attributes"
1684//      TitleBox GroupAttributesTitle,fSize=14,frame=0,fStyle=1
1685//
1686//      ListBox GroupAttributesList,pos={15,455},size={306,109}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
1687//      ListBox GroupAttributesList, widths={175,40,80,120,1000}, userColumnResize= 1   // userColumnResize requires Igor Pro 5.02.
1688//      ListBox GroupAttributesList,fSize=14
1689//
1690//      TitleBox DatasetsTitle,pos={341,230},size={62,16},disable=2,title="Datasets"
1691//      TitleBox DatasetsTitle,fSize=14,frame=0,fStyle=1
1692//
1693//      ListBox DatasetsList,pos={341,250},size={459,170}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
1694//      ListBox DatasetsList, widths={175,40,80,120,1000}, userColumnResize= 1  // userColumnResize requires Igor Pro 5.02.
1695//      ListBox DatasetsList,fSize=14
1696//
1697//      TitleBox DatasetAttributesTitle,pos={341,435},size={123,16},disable=2,title="Dataset Attributes"
1698//      TitleBox DatasetAttributesTitle,fSize=14,frame=0,fStyle=1
1699//
1700//      ListBox DatasetAttributesList,pos={341,455},size={459,109}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
1701//      ListBox DatasetAttributesList, widths={175,40,80,120,1000}, userColumnResize= 1 // userColumnResize requires Igor Pro 5.02.
1702//      ListBox DatasetAttributesList,fSize=14
1703//
1704//
1705//      Button LoadDataset,pos={415,224},size={100,20},proc=NikaHDF5Browser#LoadDatasetButtonProc,title="Load Dataset"
1706//      Button LoadDataset,help={"Loads the currently selected dataset into the current data folder."}
1707//
1708//      Button SaveWaves,pos={529,224},size={100,20},proc=NikaHDF5Browser#SaveWavesButtonProc,title="Save Waves"
1709//      Button SaveWaves,help={"Saves waves in the currently selected group. Available if the current HDF5 file is open for read/write."}
1710//
1711//      CheckBox Transpose2DDatasets,pos={189,181},size={130,14},title="Transpose 2D Datasets",value=transpose2DDatasets
1712//      CheckBox Transpose2DDatasets,proc=HDF5BrowserPrefCheckboxProc,help={"When checked, 2D datasets are transposed so that Igor image plots will match HDFView."}
1713//
1714//      PopupMenu Members,pos={342,194},size={216,24},title="Members"
1715//      PopupMenu Members,mode=1,value= #"\"Load All Members\""
1716//      PopupMenu Members proc=HDF5Browser#MembersPopupProc
1717//      PopupMenu Members,help={"Choose the compound member to preview or load."}
1718//      //Nika stuff
1719////    Wave/O/N=0/T DataSetNames, GroupNames           //these are pointes to waht user wants to get into Igor...
1720//      TitleBox NikaDataSetsTitle,pos={801,10},size={62,16},disable=2,title="Selected Datasets"
1721//      TitleBox NikaDataSetsTitle,fSize=14,frame=0,fStyle=1
1722//
1723//      string tempWvName="root:Packages:"+NI2_GetHDF5LoaderLocString()+":GroupNames"
1724//      ListBox NikaGroupList,pos={755,35},size={220,200}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
1725//      ListBox NikaGroupList, widths={175,40,80,120,1000}, userColumnResize= 1 // userColumnResize requires Igor Pro 5.02.
1726//      ListBox NikaGroupList,fSize=14, listwave=$(tempWvName)
1727//
1728//      Button AddGrouptoList,pos={600,200},size={150,20},proc=NikaHDF5Browser#LoadDatasetButtonProc,title="Add Group to Nika List"
1729//      Button AddGrouptoList,help={"Loads the currently selected Group into the current data folder."}
1730//      Button ClearDatasetList,pos={600,200},size={150,20},proc=NikaHDF5Browser#LoadDatasetButtonProc,title="Clear Nika List"
1731//      Button ClearDatasetList,help={"Clears Nika list of selected datasets"}
1732//
1733//
1734//      // Load Dataset Options
1735//      PopupMenu DisplayInTable,pos={565,123},size={200,24},title="Table:"
1736//      PopupMenu DisplayInTable,mode=2,value= #"\"No Table;Display in New Table;Append to Top Table\""
1737//      PopupMenu DisplayInGraph,pos={563,154},size={203,24},title="Graph:"
1738//      PopupMenu DisplayInGraph,mode=2,value= #"\"No Graph;Display in New Graph;Append to Top Graph\""
1739//      GroupBox LoadDatasetOptions,pos={542,100},size={258,87},title="Load Dataset Options"
1740//     
1741//      NI2_HDF5ResizeBrowser(browserName)              // Needed because we used preferred browser size.
1742//     
1743//      SetWindow kwTopWin,hook=NI2_HDF5BrowserPanelHook
1744//EndMacro
1745//
1746//
1747//static Function/S NI2_GetHDF5LoaderLocString()
1748//     
1749//      string CurPanelName = WinName(0,64)
1750//      if(stringmatch(CurPanelName[0,3],"Nika"))
1751//              return "NikaHDF5Loader"
1752//      elseif(stringmatch(CurPanelName[0,4],"Irena"))
1753//              return "IrenaHDF5Loader"
1754//      else
1755//              return ""
1756//      endif
1757//end
1758//
1759//Function NI2_HDF5BrowserPrefCheckboxProc(ctrlName,checked) : CheckBoxControl
1760//      String ctrlName
1761//      Variable checked
1762//     
1763//      STRUCT NI2_HDF5BrowserPrefs prefs
1764//     
1765//      NI2_HDF5BrowserLoadPackagePrefs(prefs)
1766//      strswitch(ctrlName)
1767//              case "ReadOnly":
1768//                      prefs.readOnly = checked
1769//                      break
1770//             
1771//              case "LoadGroupsRecursively":
1772//                      prefs.loadGroupsRecursively = checked
1773//                      break
1774//             
1775//              case "Transpose2DDatasets":
1776//                      prefs.transpose2DDatasets = checked
1777//                      break
1778//                     
1779//              case "SaveGroupsRecursively":
1780//                      prefs.saveGroupsRecursively = checked
1781//                      break
1782//                     
1783//              case "IncludeIgorAttributes":
1784//                      prefs.includeIgorAttributes = checked
1785//                      break
1786//             
1787//      endswitch
1788//      NI2_HDF5BrowserSavePackagePrefs(prefs)
1789//End
1790//
1791Function NI2_CreateNewHDF5Browser(WhereFrom)
1792        string WhereFrom                        //Nika or Irena
1793        if (Exists("HDF5LoadData") != 4)
1794                String message
1795                message = "The HDF5XOP is not activated. Please see the HDF5XOP Help file for instructions."
1796                DoAlert 0, message
1797                DisplayHelpTopic "HDF5XOP"
1798                return -1       
1799        endif
1800
1801        SetDataFolder root:
1802        NewDataFolder/O/S root:Packages
1803        NewDataFolder/O/S $(WhereFrom+"HDF5Loader")
1804        //Init here the Nika part...
1805        make/O/N=0/T DataSetNames, GroupNames           //these are pointes to waht user wants to get into Igor...
1806        String/g BrowserNameFldr
1807               
1808        String browserName = UniqueName(WhereFrom+"HDF5Browser", 9, 0)
1809        BrowserNameFldr = browserName           //thsi is where all teh otehr stuff will be....
1810       
1811        CreateHDF5BrowserGlobals(browserName)
1812       
1813        HDF5Browser#CreateHDF5BrowserPanel(browserName)
1814
1815        STRUCT HDF5BrowserData bd
1816
1817#if(IgorVersion()<9)
1818        //STRUCT NI2HDF5BrowserData bd
1819        HDF5Browser#SetHDF5BrowserData(browserName, bd)
1820        NI2_AttachListWaves(bd)
1821        HDF5Browser#SetButtonStates(bd)
1822#else
1823        HDF5Browser#SetHDF5BrowserData(browserName, bd)
1824        NI2_AttachListWaves(bd)
1825        HDF5Browser#SetButtonStates(bd)
1826#endif
1827
1828       
1829End
1830//
1831//Static Function IsHDF5Browser(name)
1832//      String name                     // Name of a window
1833//     
1834//      if (WinType(name) != 7)
1835//              return 0                                // Not a control panel window
1836//      endif
1837//     
1838//      String data = GetUserData(name, "", "HDF5BrowserName")  // HDF5BrowserName property is set by CreateHDF5BrowserPanel
1839//      if (CmpStr(data,name) == 0)                     // Is this an HDF5Browser?
1840//              return 1
1841//      endif
1842//     
1843//      return 0
1844//End
1845//
1846//Function/S NI2_HDF5GetIndxBrowserName(index)
1847//      Variable index
1848//     
1849//      if (index < 0)
1850//              return ""                               // Bad index
1851//      endif
1852//     
1853//      String panelName
1854//     
1855//      Variable i = 0
1856//      do
1857//              panelName = WinName(i, 64)
1858//              if (strlen(panelName) == 0)
1859//                      break
1860//              endif
1861//             
1862//              if (IsHDF5Browser(panelName))           // Is this an HDF5Browser?
1863//                      if (index == 0)
1864//                              return panelName
1865//                      endif
1866//                      index -= 1
1867//              endif
1868//             
1869//              i += 1
1870//      while(1)
1871//     
1872//      return ""               // No HDF5 browser with that index
1873//End
1874//
1875//Function/S NI2_HDF5GetTopBrowserName()
1876//      String browserName = NI2_HDF5GetIndxBrowserName(0)
1877//      return browserName
1878//End
1879//
1880//Function NI2_HDF5AreAnyBrowsersOpen()
1881//      String browserName = NI2_HDF5GetIndxBrowserName(0)
1882//      if (strlen(browserName) > 0)
1883//              return 1
1884//      endif
1885//      return 0
1886//End
1887//
1888//// FixCloseHDF5FileButtons()
1889//// If experiment was saved with an HDF5 file open, it is no longer open but the panel's Open
1890//// and Close buttons will be out-of-sync. This fixes that.
1891//static Function FixCloseHDF5FileButtons()
1892//
1893//      STRUCT NI2HDF5BrowserData bd
1894//      String browserName
1895//     
1896//      Variable index = 0
1897//      do
1898//              browserName = NI2_HDF5GetIndxBrowserName(index)
1899//              if (strlen(browserName) == 0)
1900//                      break
1901//              endif
1902//             
1903//              SetNI2HDF5BrowserData(browserName, bd)
1904//              if (NI2_FileWasUnexpectedlyClosed(bd))
1905//                      FileWasClosed(bd)
1906//              endif
1907//             
1908//              index += 1
1909//      while(1)
1910//End
1911//
1912//static Function AfterFileOpenHook(refNum,file,pathName,type,creator,kind)
1913//      Variable refNum,kind
1914//      String file,pathName,type,creator
1915//
1916//      // DoAlert 0, "AfterFileOpenHook"               // For debugging
1917//     
1918//      switch (kind)
1919//              case 1:                                                                         // Packed experiment
1920//              case 2:                                                                         // Unpacked experiment
1921//                      FixCloseHDF5FileButtons()               // If experiment was saved with an HDF5 file open, it is no longer open
1922//              break
1923//      endswitch
1924//
1925//      return 0
1926//End
1927//
1928//// ************* Start of HDF5 Browser Display Routines ***************
1929//
1930//static Function WaveRank(w)
1931//      Wave w
1932//     
1933//      Variable dimension
1934//      for(dimension=3; dimension>=0; dimension-=1)
1935//              if (DimSize(w, dimension) > 0)
1936//                      return dimension+1
1937//              endif
1938//      endfor
1939//     
1940//      return 0
1941//End
1942//
1943//// *** DISPLAY IN DUMP WINDOW ***
1944//
1945//Function NI2_HDF5BrowserDumpIsVisible()       // Returns true if dump window exists and is visible.
1946//                                                                      // Returns false if it does not exist or is invisible.
1947//      DoWindow  HDF5DumpNotebook
1948//      if (V_flag == 0)
1949//              return 0                                        // Does not exist
1950//      endif
1951//     
1952//      String name
1953//      Variable index = 0
1954//      do
1955//              name = WinName(index, 16, 1)
1956//              if (strlen(name) == 0)
1957//                      return 0                                // Did not find HDF5DumpNotebook among visible notebooks.
1958//              endif
1959//              if (CmpStr(name, "HDF5DumpNotebook") == 0)
1960//                      return 1                                // Found HDF5DumpNotebook among visible notebooks
1961//              endif
1962//              index += 1
1963//      while(1)
1964//     
1965//      return 0                                                // This will never execute.                                                     
1966//End
1967//
1968//Function NI2_HDF5BrowserDumpHook(infoStr)
1969//      String infoStr
1970//
1971//      String event= StringByKey("EVENT",infoStr)
1972//
1973//      strswitch(event)
1974//              case "activate":                                // We do not get this on Windows when the panel is first created.
1975//                      break
1976//                     
1977//              case "resize":
1978//              case "moved":                                   // This message was added in Igor Pro 5.04B07.
1979//                      SetPrefWindowCoords("HDF5DumpNotebook")
1980//                      break
1981//      endswitch
1982//     
1983//      return 0
1984//End
1985//
1986//Function NI2_HDF5CreateDumpWindow()
1987//      DoWindow HDF5DumpNotebook
1988//      if (V_flag == 0)
1989//              Variable left, top, right, bottom
1990//              GetPrefWindowCoords("HDF5DumpNotebook", left, top, right, bottom)
1991//              if (right > left)                                                                                       // Were prefs ever set?
1992//                      NewNotebook /F=0 /N=HDF5DumpNotebook/K=1 /W=(left, top, right, bottom)
1993//              else
1994//                      NewNotebook/F=0/N=HDF5DumpNotebook/K=1
1995//              endif
1996//              SetWindow HDF5DumpNotebook,hook=HDF5BrowserDumpHook
1997//              if (NumType(FontSizeHeight("Courier New", 12, 0)) == 0)         // Courier New exists?
1998//                      Notebook HDF5DumpNotebook font="Courier New", fSize=12
1999//              endif
2000//              Notebook HDF5DumpNotebook text="A dump will appear here when you click a dataset.\r"
2001//      endif
2002//End
2003//
2004//// CleanupDump(dump)
2005//// Removes nulls, converts \n to CR, etc. Dump of NASA strings can contain lots of such "garbage".
2006//// For an example, see the attribute /StructMetadata.O_GLOSDS in the NASA sample file MISRAERO.h5.
2007//static Function/S CleanupDump(dump)
2008//      String dump
2009//     
2010//      // Convert literal string "\000" to "". Null characters are represented in dump by "\000"
2011//      dump = ReplaceString("\\000", dump, "", 1)
2012//     
2013//      // Convert literal string "\r\n" to CR
2014//      dump = ReplaceString("\\r\\n", dump, "\r", 1)
2015//     
2016//      // Convert literal string "\r" to CR
2017//      dump = ReplaceString("\\r", dump, "\r", 1)
2018//     
2019//      // Convert literal string "\n" to CR
2020//      dump = ReplaceString("\\n", dump, "\r", 1)
2021//     
2022//      // Convert literal string "\t" to tab
2023//      dump = ReplaceString("\\t", dump, "\t", 1)
2024//     
2025//      // Convert CRLF to CR
2026//      dump = ReplaceString("\r\n", dump, "\r", 1)
2027//     
2028//      // Convert LF to CR
2029//      dump = ReplaceString("\n", dump, "\r", 1)
2030//     
2031//      return dump
2032//End
2033//
2034//Function NI2_HDF5DisplayDumpOfSelGroup(bd)
2035//      STRUCT NI2HDF5BrowserData &bd
2036//     
2037//#if Exists("HDF5OpenFile")   
2038//      String path = NI2_SelectedGroupPath(bd)
2039//      if (strlen(path) == 0)
2040//              return -1
2041//      endif
2042//     
2043//      ControlInfo /W=$bd.browserName ShowAttributesInDump
2044//      Variable showAttributes = V_value
2045//      HDF5Dump /Q /H=1 /ATTR=(showAttributes) /G=path bd.fullPath                                     // This sets S_HDF5Dump.
2046//      S_HDF5Dump = CleanupDump(S_HDF5Dump)   
2047//     
2048//      NI2_HDF5CreateDumpWindow()
2049//     
2050//      Notebook HDF5DumpNotebook selection={startOfFile, endOfFile}
2051//      Notebook HDF5DumpNotebook text=S_HDF5Dump
2052//      Notebook HDF5DumpNotebook selection={startOfFile, startOfFile}, findText={"",1}
2053//#else
2054//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
2055//#endif
2056//End
2057//
2058//static Function DisplayDumpOfSelectedDataset(bd)
2059//      STRUCT NI2HDF5BrowserData &bd
2060//     
2061//#if Exists("HDF5OpenFile")   
2062//      String datasetPath = NI2_SelectedDatasetPath(bd)
2063//      if (strlen(datasetPath) == 0)
2064//              return -1
2065//      endif
2066//     
2067//      ControlInfo /W=$bd.browserName ShowAttributesInDump
2068//      Variable showAttributes = V_value
2069//      ControlInfo /W=$bd.browserName ShowDataInDump
2070//      Variable showData = V_value
2071//      HDF5Dump /Q /ATTR=(showAttributes) /H=(!showData) /D=datasetPath bd.fullPath                    // This sets S_HDF5Dump.
2072//      S_HDF5Dump = CleanupDump(S_HDF5Dump)   
2073//     
2074//      NI2_HDF5CreateDumpWindow()
2075//     
2076//      Notebook HDF5DumpNotebook selection={startOfFile, endOfFile}
2077//      Notebook HDF5DumpNotebook text=S_HDF5Dump
2078//      Notebook HDF5DumpNotebook selection={startOfFile, startOfFile}, findText={"",1}
2079//#else
2080//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
2081//#endif
2082//End
2083//
2084//static Function DisplayDumpOfSelectedAttribute(bd, isGroupAttribute)
2085//      STRUCT NI2HDF5BrowserData &bd
2086//      Variable isGroupAttribute
2087//     
2088//#if Exists("HDF5OpenFile")   
2089//      String path = NI2_SelectedAttributePath(bd, isGroupAttribute)
2090//      if (strlen(path) == 0)
2091//              return -1
2092//      endif
2093//     
2094//      HDF5Dump /Q /A=path bd.fullPath                                 // This sets S_HDF5Dump.
2095//      S_HDF5Dump = CleanupDump(S_HDF5Dump)   
2096//     
2097//      NI2_HDF5CreateDumpWindow()
2098//     
2099//      Notebook HDF5DumpNotebook selection={startOfFile, endOfFile}
2100//      Notebook HDF5DumpNotebook text=S_HDF5Dump
2101//      Notebook HDF5DumpNotebook selection={startOfFile, startOfFile}, findText={"",1}
2102//#else
2103//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
2104//#endif
2105//End
2106//
2107//// *** DISPLAY IN GRAPH ***
2108//
2109//Function NI2_HDF5BrowserGraphIsVisible()              // Returns true if dump window exists and is visible.
2110//                                                                              // Returns false if it does not exist or is invisible.
2111//      DoWindow  HDF5BrowserGraph
2112//      if (V_flag == 0)
2113//              return 0                                        // Does not exist
2114//      endif
2115//     
2116//      // Graphs are always visible so we don't need to check that.
2117//     
2118//      return 1                                                // This will never execute.                                                     
2119//End
2120//
2121//Function NI2_HDF5BrowserGraphHook(infoStr)
2122//      String infoStr
2123//
2124//      String event= StringByKey("EVENT",infoStr)
2125//
2126//      strswitch(event)
2127//              case "activate":                                // We do not get this on Windows when the panel is first created.
2128//                      break
2129//                     
2130//              case "resize":
2131//              case "moved":                                   // This message was added in Igor Pro 5.04B07.
2132//                      SetPrefWindowCoords("HDF5BrowserGraph")
2133//                      break
2134//      endswitch
2135//     
2136//      return 0
2137//End
2138//
2139//Function NI2_HDF5CreateBrowserGraph()
2140//      DoWindow HDF5BrowserGraph
2141//      if (V_flag == 0)
2142//              Variable left, top, right, bottom
2143//              GetPrefWindowCoords("HDF5BrowserGraph", left, top, right, bottom)
2144//              if (right > left)                                                                       // Were prefs ever set?
2145//                      Display /K=1 /W=(left, top, right, bottom)
2146//              else
2147//                      Display /K=1
2148//              endif
2149//              DoWindow/C HDF5BrowserGraph
2150//              SetWindow HDF5BrowserGraph,hook=HDF5BrowserGraphHook
2151//      endif
2152//End
2153//
2154//static Function SetImageLayer(ctrlName,varNum,varStr,varName) : SetVariableControl
2155//      String ctrlName
2156//      Variable varNum
2157//      String varStr
2158//      String varName
2159//
2160//      NVAR imageLayer = root:Packages:HDF5Browser:imageLayer
2161//
2162//      ModifyImage /W=HDF5BrowserGraph BrowserWave, plane=varNum
2163//End
2164//
2165//static Function DisplayGraphOfSelectedData(bd, isAttribute, objectType, listOfWavesLoaded)            // The data is already loaded into waves specified by listOfWavesLoaded
2166//      STRUCT NI2HDF5BrowserData &bd
2167//      Variable isAttribute
2168//      Variable objectType                             // Host object type of attribute. 1=group, 2=dataset
2169//      String listOfWavesLoaded
2170//
2171//      NI2_HDF5CreateBrowserGraph()
2172//
2173//      String firstWaveLoaded = StringFromList(0, listOfWavesLoaded)
2174//      Wave browserWave = root:Packages:HDF5Browser:$firstWaveLoaded
2175//      Variable newDataIsText = WaveType(browserWave) == 0
2176//
2177//      Variable oldRank = 0, newRank = 0
2178//      if (strlen(TraceNameList("HDF5BrowserGraph", ";", 1)) > 0)
2179//              oldRank = 1                                     
2180//      endif
2181//      if (strlen(ImageNameList("HDF5BrowserGraph", ";")) > 0)
2182//              oldRank = 2
2183//      endif
2184//      newRank = WaveRank(browserWave) // Will be zero for zero-point wave
2185//
2186//      String savedDataFolder = NI2_SetBrowserDataFolder("")                                   // browserWave goes in master HDF5Browser data folder
2187//
2188//      Variable displayedDimensionalityChanged = (oldRank <= 1) != (newRank <= 1)      // Switching between 1D and >1D ?
2189//      Variable index, browserWaveIsDisplayed
2190//      String waveLoaded, nameOfGraphWave
2191//     
2192//      // Remove any waves in graph not in listOfWavesLoaded or all waves if dimensionality changed
2193//      index = 0
2194//      do
2195//              if (oldRank == 1)
2196//                      Wave/Z graphWave = WaveRefIndexed("HDF5BrowserGraph", index, 1)
2197//                      if (!WaveExists(graphWave))
2198//                              break
2199//                      endif
2200//                      nameOfGraphWave = NameOfWave(graphWave)
2201//              else
2202//                      nameOfGraphWave = StringFromList(index, ImageNameList("HDF5BrowserGraph", ";" ))
2203//                      if (strlen(nameOfGraphWave) == 0)
2204//                              break
2205//                      endif
2206//              endif
2207//             
2208//              Variable waveIsInListOfLoadedWaves = WhichListItem(nameOfGraphWave, listOfWavesLoaded) >= 0
2209//              if (displayedDimensionalityChanged || !waveIsInListOfLoadedWaves)
2210//                      if (oldRank == 1)
2211//                              RemoveFromGraph /W=HDF5BrowserGraph $nameOfGraphWave
2212//                      endif
2213//                      if (oldRank > 1)
2214//                              RemoveImage /W=HDF5BrowserGraph $nameOfGraphWave
2215//                      endif
2216//                      index -= 1
2217//              endif
2218//              if (!waveIsInListOfLoadedWaves)
2219//                      KillWaves/Z $nameOfGraphWave
2220//              endif
2221//             
2222//              index += 1
2223//      while(1)
2224//
2225//      // Append any waves to graph in listOfWavesLoaded
2226//      index = 0
2227//      do
2228//              waveLoaded = StringFromList(index, listOfWavesLoaded)
2229//              if (strlen(waveLoaded) == 0)
2230//                      break
2231//              endif
2232//              Wave browserWave = root:Packages:HDF5Browser:$waveLoaded
2233//              Variable browserWaveType = WaveType(browserWave)
2234//              nameOfGraphWave = waveLoaded
2235//
2236//              CheckDisplayed /W=HDF5BrowserGraph browserWave
2237//              browserWaveIsDisplayed = V_flag
2238//             
2239//              if (!newDataIsText)
2240//                      if (browserWaveType != 0)                               // When loading compound data we can get a mix of numeric and non-numeric.
2241//                              if (browserWaveIsDisplayed == 0)
2242//                                      if (newRank <= 1)
2243//                                              AppendToGraph /W=HDF5BrowserGraph browserWave
2244//                                              if (displayedDimensionalityChanged)
2245//                                                      SetAxis/A left
2246//                                              endif
2247//                                      else
2248//                                              AppendImage /W=HDF5BrowserGraph browserWave
2249//                                              if (displayedDimensionalityChanged)
2250//                                                      SetAxis/A/R left                                                                        // Reverse left axis like NewImage does.
2251//                                              endif
2252//                                      endif
2253//                              endif
2254//     
2255//                              if (newRank >= 2)
2256//                                      NVAR formalImageType = root:Packages:HDF5Browser:formalImageType
2257//                                      switch (formalImageType)                                                        // browserPalette would be created by HDF5LoadImage
2258//                                              case 0:                                                                                         // Not a formal image.
2259//                                              case 1:                                                                                         // No palette wave loaded.
2260//                                                      ModifyImage /W=HDF5BrowserGraph $nameOfGraphWave ctab= {*,*,Grays,0}
2261//                                                      break
2262//                                                     
2263//                                              case 2:                                                                                         // Palette wave was loaded.
2264//                                                      Wave browserPalette = root:Packages:HDF5Browser:browserPalette
2265//                                                      ModifyImage /W=HDF5BrowserGraph $nameOfGraphWave, cindex=browserPalette
2266//                                                      break
2267//                                      endswitch
2268//                              endif
2269//                      endif
2270//              endif
2271//
2272//              if (newDataIsText)                                              // Display a snippet of the text wave.
2273//                      if (browserWaveType == 0)               // When loading compound data we can get a mix of numeric and non-numeric.
2274//                              String text
2275//                              Wave/T w = root:Packages:HDF5Browser:$nameOfGraphWave
2276//                              if (numpnts(w) > 0)
2277//                                      text = CleanupDump(w[0])
2278//                              else
2279//                                      text = ""
2280//                              endif
2281//                              if ( (strlen(text) > 256) || (numpnts(w)>1) )
2282//                                      text = "A snippet of the text:\r\r" + text[0,255]                       
2283//                              endif                   
2284//                              TextBox/C/N=browserTextbox/W=HDF5BrowserGraph/A=LT text
2285//                      endif
2286//              else
2287//                      TextBox/K/N=browserTextbox/W=HDF5BrowserGraph
2288//              endif
2289//             
2290//              index += 1
2291//      while(1)
2292//     
2293//      // Show Image Layer control if displaying a stack of images
2294//      Variable numDims = WaveDims(browserWave)
2295//      Variable isStack = 0
2296//      if (!newDataIsText && newRank>2)
2297//              if (DimSize(browserWave,2) == 3)
2298//                      // Igor assumes that this is an RGB wave using direct color.
2299//                      if (numDims > 3)
2300//                              isStack = 1                     // This is a stack of RGB images.
2301//                      endif
2302//              else
2303//                      isStack = 1                     // This is a stack of indexed color images.
2304//              endif
2305//      endif
2306//     
2307//      if (isStack)
2308//              Variable/G root:Packages:HDF5Browser:imageLayer = 0
2309//              Variable dim, numLayers
2310//             
2311//              numLayers = 1
2312//              for(dim=2; dim<numDims; dim+=1)
2313//                      numLayers *= DimSize(browserWave, dim)
2314//              endfor
2315//             
2316//              ControlBar/W=HDF5BrowserGraph 25
2317//              SetVariable ImageLayer win=HDF5BrowserGraph, title="Layer",size={100,20},format="%d"
2318//              SetVariable ImageLayer win=HDF5BrowserGraph, proc=HDF5Browser#SetImageLayer
2319//              SetVariable ImageLayer win=HDF5BrowserGraph, value=imageLayer, limits={0,numLayers-1,1}
2320//      else
2321//              KillControl/W=HDF5BrowserGraph ImageLayer
2322//              ControlBar/W=HDF5BrowserGraph 0
2323//      endif
2324//             
2325//      String title = "HDF5 Preview - "
2326//      if (isAttribute)
2327//              title += NI2_SelectedAttributeName(bd, objectType==1)
2328//      else
2329//              title += NI2_SelectedDatasetName(bd)
2330//      endif
2331//      title = title[0,39]                             // Unfortunately titles are limited to 40 characters.
2332//      DoWindow /T HDF5BrowserGraph, title
2333//     
2334//      SetDataFolder savedDataFolder
2335//End
2336//
2337//// *** DISPLAY IN TABLE ***
2338//
2339//Function NI2_HDF5BrowserTableIsVisible()              // Returns true if dump window exists and is visible.
2340//                                                                              // Returns false if it does not exist or is invisible.
2341//      DoWindow  HDF5BrowserTable
2342//      if (V_flag == 0)
2343//              return 0                                        // Does not exist
2344//      endif
2345//     
2346//      // Tables are always visible so we don't need to check that.
2347//     
2348//      return 1                                                // This will never execute.                                                     
2349//End
2350//
2351//Function NI2_HDF5BrowserTableHook(infoStr)
2352//      String infoStr
2353//
2354//      String event= StringByKey("EVENT",infoStr)
2355//
2356//      strswitch(event)
2357//              case "activate":                                // We do not get this on Windows when the panel is first created.
2358//                      break
2359//                     
2360//              case "resize":
2361//              case "moved":                                   // This message was added in Igor Pro 5.04B07.
2362//                      SetPrefWindowCoords("HDF5BrowserTable")
2363//                      break
2364//      endswitch
2365//     
2366//      return 0
2367//End
2368//
2369//Function NI2_HDF5CreateBrowserTable()
2370//      DoWindow HDF5BrowserTable
2371//      if (V_flag == 0)
2372//              Variable left, top, right, bottom
2373//              GetPrefWindowCoords("HDF5BrowserTable", left, top, right, bottom)
2374//              if (right > left)                                                                       // Were prefs ever set?
2375//                      Edit /K=1 /W=(left, top, right, bottom)
2376//              else
2377//                      Edit /K=1
2378//              endif
2379//              DoWindow/C HDF5BrowserTable
2380//              SetWindow HDF5BrowserTable,hook=HDF5BrowserTableHook
2381//      endif
2382//End
2383//
2384//static Function DisplayTableOfSelectedData(bd, isAttribute, objectType, listOfWavesLoaded)            // The data is already loaded into waves listed by listOfWavesLoaded
2385//      STRUCT NI2HDF5BrowserData &bd
2386//      Variable isAttribute
2387//      Variable objectType                             // Host object type of attribute. 1=group, 2=dataset
2388//      String listOfWavesLoaded
2389//     
2390//      NI2_HDF5CreateBrowserTable()
2391//
2392//      String waveLoaded
2393//      Variable index
2394//     
2395//      // Remove any waves in table not in listOfWavesLoaded
2396//      index = 0
2397//      do
2398//              Wave/Z tableWave = WaveRefIndexed("HDF5BrowserTable", index, 3)
2399//              if (!WaveExists(tableWave))
2400//                      break
2401//              endif
2402//             
2403//              String nameOfTableWave = NameOfWave(tableWave)
2404//              if (WhichListItem(nameOfTableWave, listOfWavesLoaded) < 0)
2405//                      RemoveFromTable /W=HDF5BrowserTable tableWave
2406//                      KillWaves/Z tableWave
2407//                      index -= 1
2408//              endif
2409//             
2410//              index += 1
2411//      while(1)
2412//
2413//      // Append any waves to table in listOfWavesLoaded
2414//      index = 0
2415//      do
2416//              waveLoaded = StringFromList(index, listOfWavesLoaded)
2417//              if (strlen(waveLoaded) == 0)
2418//                      break
2419//              endif
2420//              Wave browserWave = root:Packages:HDF5Browser:$waveLoaded
2421//     
2422//              CheckDisplayed /W=HDF5BrowserTable browserWave
2423//              if (V_flag == 0)
2424//                      AppendToTable /W=HDF5BrowserTable browserWave
2425//              endif
2426//             
2427//              index += 1
2428//      while(1)
2429//
2430//      String title = "HDF5 Preview - "
2431//      if (isAttribute)
2432//              title += NI2_SelectedAttributeName(bd, objectType==1)
2433//      else
2434//              title += NI2_SelectedDatasetName(bd)
2435//      endif
2436//      title = title[0,39]                             // Unfortunately titles are limited to 40 characters.
2437//      DoWindow /T HDF5BrowserTable, title
2438//End
2439//
2440//static Function RemoveFromGraphAndTable(w)
2441//      Wave w
2442//     
2443//      String name = NameOfWave(w)
2444//     
2445//      if (NI2_HDF5BrowserGraphIsVisible())
2446//              CheckDisplayed /W=HDF5BrowserGraph w
2447//              if (V_flag != 0)
2448//                      Variable isImage = strlen(ImageNameList("HDF5BrowserGraph", ";")) > 0
2449//                      if (isImage)
2450//                              RemoveImage /W=HDF5BrowserGraph $name
2451//                      else
2452//                              RemoveFromGraph /W=HDF5BrowserGraph $name
2453//                      endif
2454//              endif
2455//      endif
2456//     
2457//      if (NI2_HDF5BrowserTableIsVisible())
2458//              CheckDisplayed /W=HDF5BrowserTable w
2459//              if (V_flag != 0)
2460//                      RemoveFromTable /W=HDF5BrowserTable w
2461//              endif
2462//      endif
2463//End
2464//
2465////    KillConflictingBrowserWaves(new_class_str, enumMode)
2466////    "Conflicting" means that a wave is text and we are going
2467//// to use the same name to load a numeric wave or vice versa.
2468//// This function removes conflicting waves from the browser graph
2469//// and table and then kills them.
2470//static Function KillConflictingBrowserWaves(new_class_str, enumMode)
2471//      String new_class_str                            // Class of data we are about to load.
2472//      Variable enumMode
2473//
2474//      String browserDF = "root:Packages:HDF5Browser"
2475//      Variable numWaves = CountObjects(browserDF, 1)
2476//      Variable i
2477//
2478//      for(i=0; i<numWaves; i+=1)
2479//              String name = GetIndexedObjName(browserDF, 1, i)
2480//              if (strlen(name)>=11 && CmpStr(name[0,11],"browserWave")==0)    // Is this a browser display wave?
2481//                      Wave w = $(browserDF + ":" + name)
2482//
2483//                      Variable oldDataIsText
2484//                      oldDataIsText = WaveType(w) == 0
2485//     
2486//                      Variable newDataIsText
2487//                     
2488//                      newDataIsText = 0
2489//                      strswitch(new_class_str)
2490//                              case "H5T_STRING":
2491//                              case "H5T_REFERENCE":
2492//                                      newDataIsText = 1
2493//                                      break
2494//                                     
2495//                              case "H5T_ENUM":
2496//                                      if (enumMode == 1)
2497//                                              newDataIsText = 1
2498//                                      endif
2499//                                      break
2500//                                     
2501//                              case "H5T_COMPOUND":
2502//                                      // If we are loading all members of a compound dataset
2503//                                      // at this point we need to know the class of the compound
2504//                                      // member corresponding to the current wave. However, this
2505//                                      // is very complicated to do and I decided not to attempt it.
2506//                                      // The result is that, if we have an existing brower_<member>
2507//                                      // wave whose type is string and we try to load a numeric wave
2508//                                      // with the same name, HDF5LoadWave will get a "Can't overwrite
2509//                                      // text with numeric and vice versa" error.
2510//                                      break
2511//                      endswitch
2512//                     
2513//                      if (newDataIsText != oldDataIsText)
2514//                              RemoveFromGraphAndTable(w)
2515//                              KillWaves w
2516//                              // Printf "Killed %s\r", name
2517//                      endif
2518//              endif
2519//      endfor
2520//End
2521//
2522//static Function LoadSelectedDataForDisplay(bd, isAttribute, objectType, listOfWavesLoaded, errorMessage)
2523//      STRUCT NI2HDF5BrowserData &bd
2524//      Variable isAttribute
2525//      Variable objectType                                     // Host object type of attribute. 1=group, 2=dataset
2526//      String &listOfWavesLoaded               // Output: List of waves loaded.
2527//      String &errorMessage                            // Output: Error message or ""
2528//     
2529//#if Exists("HDF5OpenFile")   
2530//      Variable err = 0
2531//      errorMessage = ""
2532//
2533//      Wave/Z browserWave = root:Packages:HDF5Browser:browserWave
2534//     
2535//      String path
2536//      if (isAttribute)
2537//              if (objectType == 1)
2538//                      path = NI2_SelectedGroupPath(bd)
2539//              else
2540//                      path = NI2_SelectedDatasetPath(bd)
2541//              endif
2542//      else
2543//              path = NI2_SelectedDatasetPath(bd)
2544//      endif
2545//      if (strlen(path) == 0)
2546//              return -1
2547//      endif
2548//     
2549//      String attributeName = ""
2550//      if (isAttribute)
2551//              attributeName = NI2_SelectedAttributeName(bd, objectType==1)
2552//              if (strlen(attributeName) == 0)
2553//                      return -1
2554//              endif
2555//      endif
2556//
2557//      STRUCT NI2_HDF5DataInfo di
2558//      NI2_InitHDF5DataInfo(di)
2559//      if (isAttribute)
2560//              HDF5AttributeInfo(bd.fileID, path, objectType, attributeName, 0, di)
2561//      else
2562//              HDF5DatasetInfo(bd.fileID, path, 0, di)
2563//      endif
2564//     
2565//      String datatype_class_str = di.datatype_class_str
2566//
2567//      STRUCT NI2_HDF5DatatypeInfo dti
2568//      NI2_InitHDF5DatatypeInfo(dti)                                   // Sets input fields.
2569//
2570//      Variable isCompound = 0
2571//      Variable compMode = 0
2572//      String memberName = ""
2573//      if (!isAttribute)                       // We support viewing members only for datasets, not for attributes.
2574//              NI2_HDF5GetCompLoadInfo(bd, isCompound, compMode, memberName)
2575//      endif
2576//     
2577//      if (compMode != 0)                      // Are we loading a member of a compound datatype?
2578//              err = HDF5TypeInfo(bd.fileID, path, "", memberName, 1, dti)
2579//              if (err != 0)
2580//                      return err
2581//              endif
2582//              datatype_class_str = dti.type_class_str
2583//      else
2584//              // If array, we need to know about the base datatype of the array
2585//              if (CmpStr(datatype_class_str, "H5T_ARRAY") == 0)
2586//                      if (isAttribute)
2587//                              HDF5AttributeInfo(bd.fileID, path, objectType, attributeName, 2, di)            // 2 means get info on base datatype of array
2588//                      else
2589//                              HDF5DatasetInfo(bd.fileID, path, 2, di) // 2 means get info on base datatype of array
2590//                      endif
2591//              endif
2592//              datatype_class_str = di.datatype_class_str
2593//      endif
2594//
2595//      err = NI2_HDF5CheckDataClass(datatype_class_str, errorMessage)
2596//      if (err != 0)
2597//              if (WaveExists(browserWave))
2598//                      Redimension/N=(0) browserWave           // Don't leave browserWave around which a user might
2599//              endif                                                                                           // think goes with the selected item in the control panel
2600//              return err
2601//      endif
2602//     
2603//      String savedDataFolder = NI2_SetBrowserDataFolder("")                                   // tempClassAttribute goes in master HDF5Browser data folder
2604//     
2605//      // If isFormalImage is true, we are loading an image written
2606//      // according to the HDF5 Image and Palette Specification.
2607//      Variable isFormalImage = 0
2608//      if (!isAttribute && !isCompound)
2609//              HDF5LoadData /Z /O /N=tempClassAttribute /A="CLASS" /Q /VAR=1 bd.fileID, path
2610//              if (V_flag == 0)
2611//                      WAVE/T tempClassAttribute                       // HDF5LoadData will have created this string
2612//                      if (CmpStr(tempClassAttribute[0],"IMAGE") == 0)
2613//                              isFormalImage = 1
2614//                      endif   
2615//                      KillWaves/Z tempClassAttribute
2616//              endif
2617//      endif
2618//
2619//      SetDataFolder savedDataFolder
2620//     
2621//      Variable enumMode = 1                                           // 0: Load enum into numeric wave; 1: load enum into text wave.
2622//     
2623//      // If browserWave exists and we are switching from a text wave to a numeric wave
2624//      // or vice-versa then we must remove browserWave from the graph and table and
2625//      // kill it. Otherwise we will get an error when HDF5LoadData tries to overwrite
2626//      // a text wave with numeric or vice versa.
2627//      KillConflictingBrowserWaves(datatype_class_str, enumMode)       // Also removes them from graph and table.
2628//     
2629//      savedDataFolder = NI2_SetBrowserDataFolder("")                                  // browser waves go in master HDF5Browser data folder
2630//
2631//      String slabWaveStr = ""
2632//      ControlInfo /W=$bd.browserName UseHyperSelection
2633//      if (V_value)                                                            // Use Hyperselection is checked?
2634//              slabWaveStr = bd.hyperSelectionWavePath
2635//      endif
2636//      WAVE/Z slabWave = $slabWaveStr                  // It is OK if wave does not exist and slabWave is NULL. HDF5LoadData will simply ignore /SLAB.
2637//
2638//      if (isFormalImage)
2639//              String browserPaletteName = "browserPalette"
2640//              HDF5LoadImage /O /N=browserWave /PALN=browserPaletteName /Q bd.fileID, path
2641//              Variable/G formalImageType = 1          // Means formal image with no palette
2642//              listOfWavesLoaded = StringFromList(0, S_waveNames)      // We count only the image as loaded, not the palette.
2643//              if (WhichListItem(browserPaletteName, S_waveNames) >= 0)
2644//                      formalImageType = 2                                     // Means formal image with palette
2645//              endif
2646//      else
2647//              KillWaves/Z browserPalette
2648//
2649//              Variable transpose2D = NI2_HDF5GetTranspose2DSetting(bd.browserName)
2650//
2651//              // Note that when loading all members of a compound dataset this
2652//              // will create a family of waves named browserWave_<member>.
2653//              // Also when loading a VLEN dataset it will create a family of
2654//              // waves named browserWave<digit>. Otherwise it just creates
2655//              // one wave named browserWave.
2656//              HDF5LoadData /O /IGOR=-1 /N=browserWave /COMP={compMode,memberName} /TRAN=(transpose2D) /A=attributeName /TYPE=(objectType) /ENUM=(enumMode) /SLAB=slabWave /Q /VAR=0 bd.fileID, path
2657//
2658//              Variable/G formalImageType = 0          // Not a formal image
2659//              listOfWavesLoaded = S_waveNames
2660//      endif
2661//     
2662//      errorMessage = GetRTErrMessage()
2663//      err = GetRTError(1)
2664//
2665//      SetDataFolder savedDataFolder
2666//      return err
2667//#else
2668//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
2669//#endif
2670//End
2671//
2672//Function NI2_HDF5DisplaySelectedDataset(bd)
2673//      STRUCT NI2HDF5BrowserData &bd
2674//
2675//      if (NI2_HDF5BrowserDumpIsVisible())
2676//              DisplayDumpOfSelectedDataset(bd)
2677//      endif
2678//
2679//      String listOfWavesLoaded = ""   
2680//     
2681//      Variable needToLoadData = NI2_HDF5BrowserGraphIsVisible() || NI2_HDF5BrowserTableIsVisible()
2682//      if (needToLoadData)
2683//              String errorMessage
2684//              if (LoadSelectedDataForDisplay(bd, 0, 2, listOfWavesLoaded, errorMessage) != 0)
2685//                      DoAlert 0, errorMessage
2686//                      return -1
2687//              endif
2688//      endif
2689//
2690//      if (NI2_HDF5BrowserGraphIsVisible())
2691//              DisplayGraphOfSelectedData(bd, 0, 1, listOfWavesLoaded)
2692//      endif
2693//
2694//      if (NI2_HDF5BrowserTableIsVisible())
2695//              DisplayTableOfSelectedData(bd, 0, 1, listOfWavesLoaded)
2696//      endif
2697//End
2698//
2699//Function NI2_HDF5DisplaySelAttribute(bd,  isGroupAttribute)
2700//      STRUCT NI2HDF5BrowserData &bd
2701//      Variable isGroupAttribute
2702//     
2703//      if (NI2_HDF5BrowserDumpIsVisible())
2704//              DisplayDumpOfSelectedAttribute(bd, isGroupAttribute)
2705//      endif
2706//     
2707//      Variable objectType = isGroupAttribute ? 1:2
2708//     
2709//      String listOfWavesLoaded = ""
2710//     
2711//      Variable needToLoadData = NI2_HDF5BrowserGraphIsVisible() || NI2_HDF5BrowserTableIsVisible()
2712//      if (needToLoadData)
2713//              String errorMessage
2714//              if (LoadSelectedDataForDisplay(bd, 1, objectType, listOfWavesLoaded, errorMessage))
2715//                      DoAlert 0, errorMessage
2716//                      return -1
2717//              endif
2718//      endif
2719//
2720//      if (NI2_HDF5BrowserGraphIsVisible())
2721//              DisplayGraphOfSelectedData(bd, 1, objectType, listOfWavesLoaded)
2722//      endif
2723//
2724//      if (NI2_HDF5BrowserTableIsVisible())
2725//              DisplayTableOfSelectedData(bd, 1, objectType, listOfWavesLoaded)
2726//      endif
2727//End
2728//
2729//// ************* End of HDF5 Browser Display Routines ***************
2730//
2731//// ************* Start of HDF5 Browser Resize Routines ***************
2732//
2733//static Function MinWindowSize(winName,minwidth,minheight)
2734//      String winName
2735//      Variable minwidth,minheight
2736//
2737//      GetWindow $winName wsize
2738//      Variable width= max(V_right-V_left,minwidth)
2739//      Variable height= max(V_bottom-V_top,minheight)
2740//      MoveWindow/W=$winName V_left, V_top, V_left+width, V_top+height
2741//End
2742//
2743//Function NI2_PositionControlRelative(panelName, control, masterControl, xMode, yMode, dx, dy)
2744//      String panelName
2745//      String control, masterControl           // Positions control relative to masterControl.
2746//      Variable xMode          // 0 = relative to master left, 1 = relative to master right, 2 = do not set x position.
2747//      Variable yMode          // 0 = relative to master top, 1 = relative to master bottom, 2 = do not set y position.
2748//      Variable dx, dy
2749//     
2750//      ControlInfo/W=$panelName $masterControl
2751//      Variable masterLeft = V_left, masterTop = V_top
2752//      Variable masterRight = masterLeft+V_width, masterBottom=masterTop+V_height
2753//     
2754//      ControlInfo/W=$panelName $control
2755//      Variable controlLeft = V_left, controlTop = V_top
2756//     
2757//      Variable left, top
2758//     
2759//      switch(xMode)
2760//              case 0:
2761//                      left = masterLeft + dx
2762//                      break
2763//     
2764//              case 1:
2765//                      left = masterRight + dx
2766//                      break
2767//             
2768//              case 2:
2769//                      left = controlLeft
2770//                      break
2771//      endswitch
2772//     
2773//      switch(yMode)
2774//              case 0:
2775//                      top = masterTop + dy
2776//                      break
2777//     
2778//              case 1:
2779//                      top = masterBottom + dy
2780//                      break
2781//             
2782//              case 2:
2783//                      top = controlTop
2784//                      break
2785//      endswitch
2786//
2787//      ModifyControl $control, win=$panelName, pos={left, top}
2788//End
2789//
2790//Function NI2_OffsetControls(panelName, controlList, dx, dy)
2791//      String panelName
2792//      String controlList      // Semicolon-separated list of control names
2793//      Variable dx, dy
2794//     
2795//      String name
2796//      Variable index = 0
2797//      do
2798//              name = StringFromList(index, controlList)
2799//              if (strlen(name) == 0)
2800//                      break
2801//              endif
2802//             
2803//              ControlInfo/W=$panelName $name
2804//              ModifyControl $name, win=$panelName, pos={V_left+dx,V_top+dy}
2805//
2806//              index += 1
2807//      while(1)
2808//End
2809//
2810//Function NI2_HDF5ResizeBrowser(browserName)
2811//      String browserName
2812//
2813//      Variable statusCode= 0
2814//
2815//      String win = browserName
2816//
2817//      GetWindow $browserName wsizeDC
2818//      Variable winLeft=V_left, winTop=V_top, winRight=V_right, winBottom=V_bottom
2819//      Variable winWidth = winRight - winLeft, winHeight = winBottom - winTop
2820//
2821//      if (winWidth<800 || winHeight<500)
2822//              return 0                                                // Too small.
2823//      endif
2824//     
2825//      // Set preferred browser window size. We would like to also do this
2826//      // when the browser is moved without resizing but we get no message
2827//      // from Igor when a window is moved.
2828//      SetPrefWindowCoords(browserName)
2829//     
2830//      Variable leftBorder=15, hSpaceBetweenLists=20, rightBorder=15
2831//      Variable listsTop, vSpaceBetweenLists = 30, bottomBorder = 10
2832//     
2833//      ControlInfo/W=$browserName GroupsList
2834//      listsTop = V_top
2835//     
2836//      Variable hSpaceForLists = winRight - winLeft - leftBorder - hSpaceBetweenLists - rightBorder
2837//      Variable vSpaceForLists = winBottom - listsTop - vSpaceBetweenLists - bottomBorder
2838//     
2839//      Variable groupListsWidth = .3 * hSpaceForLists
2840//      Variable datasetListsWidth = .45 * hSpaceForLists
2841//      Variable NikaListsWidth = .23 * hSpaceForLists
2842//     
2843//      Variable groupListsHeight = .65 * vSpaceForLists
2844//      Variable attributeListsHeight = .35 * vSpaceForLists
2845//     
2846//      Variable left, top
2847//     
2848//      // Set Groups list coordinates
2849//      left = leftBorder
2850//      top = listsTop
2851//      ListBox GroupsList, win=$browserName, pos={left, top}, size={groupListsWidth, groupListsHeight}
2852//     
2853//      // Set Group Attributes list coordinates
2854//      left = leftBorder
2855//      top = listsTop + groupListsHeight + vSpaceBetweenLists
2856//      ListBox GroupAttributesList, win=$browserName, pos={left, top}, size={groupListsWidth, attributeListsHeight}
2857//     
2858//      top -= 20
2859//      TitleBox GroupAttributesTitle, win=$browserName, pos={left, top}
2860//
2861//      // Remember where DatasetsList is. it is used to position other control.
2862//      ControlInfo/W=$browserName DatasetsList
2863//      Variable oldDatasetsListRight = V_Left + V_Width
2864//     
2865//      // Set Datasets list coordinates
2866//      left = leftBorder + groupListsWidth + hSpaceBetweenLists
2867//      top = listsTop
2868//      ListBox DatasetsList, win=$browserName, pos={left, top}, size={datasetListsWidth, groupListsHeight}
2869//     
2870//      // Determine how DatasetsList right edge changed. This is used to position other control.
2871//      ControlInfo/W=$browserName DatasetsList
2872//      Variable changeInDatsetsListRight = (V_Left + V_Width) - oldDatasetsListRight
2873//     
2874//      // Set Datasets Title
2875//      top -= 20
2876//      TitleBox DatasetsTitle, win=$browserName, pos={left, top}
2877//     
2878//      // Set Load Dataset Button
2879//      NI2_PositionControlRelative(browserName, "LoadDataset", "DatasetsTitle", 1, 2, 20, 0)
2880////    NI2_PositionControlRelative(browserName, "AddGrouptoList", "DatasetsTitle", 1, 2, 0, -20)
2881//
2882//
2883//      // Set Save Waves Button
2884//      NI2_PositionControlRelative(browserName, "SaveWaves", "LoadDataset", 1, 2, 20, 0)
2885//
2886//      // Set Members popup menu
2887//      NI2_PositionControlRelative(browserName, "Members", "DatasetsTitle", 0, 2, 0, 0)
2888//     
2889//      // Set Dataset Attributes list coordinates
2890//      left = leftBorder + groupListsWidth + hSpaceBetweenLists
2891//      top = listsTop + groupListsHeight + vSpaceBetweenLists
2892//      ListBox DatasetAttributesList, win=$browserName, pos={left, top}, size={datasetListsWidth, attributeListsHeight}
2893//     
2894//      top -= 20
2895//      TitleBox DatasetAttributesTitle, win=$browserName, pos={left, top}
2896//
2897//      // Set Preview Options
2898//      String list = "PreviewOptions;Graph;Table;Dump;ShowAttributesInDump;ShowDataInDump;"
2899//      NI2_OffsetControls(browserName, list, changeInDatsetsListRight, 0)
2900//
2901//      // Set Load Dataset Options
2902//      list = "LoadDatasetOptions;DisplayInTable;DisplayInGraph;"
2903//      NI2_OffsetControls(browserName, list, changeInDatsetsListRight, 0)
2904//
2905//      //Set Nika controls
2906//      // Set Datasets list coordinates
2907//      left = leftBorder + groupListsWidth + hSpaceBetweenLists+datasetListsWidth+hSpaceBetweenLists
2908//      top = listsTop
2909//
2910//      ListBox NikaGroupList, win=$browserName, pos={left, top}, size={NikaListsWidth, groupListsHeight}
2911//      // Set Load Dataset Button
2912//      NI2_PositionControlRelative(browserName, "NikaDataSetsTitle", "NikaGroupList", 0, 0, 30, -20)
2913//      Button AddGrouptoList,win=$browserName, pos={left, top-150}, size={NikaListsWidth, 20}
2914//      Button ClearDatasetList,win=$browserName, pos={left, top-100}, size={NikaListsWidth, 20}
2915//
2916////    NI2_PositionControlRelative(browserName, "NikaDataSetsTitle", "NikaGroupList", 0, 0, 30, -20)
2917//
2918////    Wave/O/N=0/T DataSetNames, GroupNames           //these are pointes to waht user wants to get into Igor...
2919////    TitleBox NikaDataSetsTitle,pos={801,10},size={62,16},disable=2,title="Selected Datasets"
2920//     
2921//     
2922//      statusCode=1
2923//
2924//      return statusCode       // 0 if nothing done, else 1 or 2
2925//End
2926//
2927//// ************* End of HDF5 Browser Resize Routines ***************
2928//
2929//// ************* Start of HDF5 Browser Prefs Routines ***************
2930//
2931//// HDF5 Browser preferences are stored on disk in the Packages directory
2932//// in Igor's preferences directory. They are temporarily loaded into an
2933//// HDF5BrowserPrefs data structure but are not stored permanently in memory.
2934//
2935//// When a preference value has to be changed, the prefs data structure
2936//// is loaded into memory, the value is changed and the data structure is
2937//// immediately written back out to disk.
2938//// To see where prefs data is changed, search for HDF5BrowserSavePackagePrefs.
2939//
2940//static StrConstant kPackageName = "NikaHDF5Browser"   // NOTE: Package name must be distinctive!
2941//static Constant kCurrentPrefsVersion = 100                    // Changes to hundreds digit means incompatible prefs
2942//static StrConstant kPrefFileName = "Preferences.bin"
2943//static Constant kPrefRecordID = 0
2944//
2945//Structure NI2_HDF5BrowserPrefs
2946//      uint32 prefsVersion                     // Preferences structure version number. 100 means 1.00.
2947//
2948//      // Preview graph location in points. 0 means default.
2949//      float graphLeft
2950//      float graphTop
2951//      float graphRight
2952//      float graphBottom
2953//             
2954//      // Preview table location in points. 0 means default.
2955//      float tableLeft
2956//      float tableTop
2957//      float tableRight
2958//      float tableBottom
2959//             
2960//      // Dump notebook location in points. 0 means default.
2961//      float dumpLeft
2962//      float dumpTop
2963//      float dumpRight
2964//      float dumpBottom
2965//                     
2966//      // Save Waves and Save Data Folder panel location in pixels. 0 means default.
2967//      float savePanelLeft
2968//      float savePanelTop
2969//      float savePanelRight
2970//      float savePanelBottom
2971//
2972//      // HDF5 browser location in points. 0 means default.
2973//      float browserLeft
2974//      float browserTop
2975//      float browserRight
2976//      float browserBottom
2977//
2978//      // Overall prefs
2979//      uchar readOnly                                          // Open file read only
2980//      uchar reservedOverall[15]
2981//     
2982//      // Load prefs
2983//      uchar loadGroupsRecursively             // Controls Load Group button
2984//      uchar transpose2DDatasets               // Controls Load Dataset and Load Group buttons
2985//      uchar reservedLoad[14]
2986//     
2987//      // Save prefs
2988//      uchar saveGroupsRecursively             // Affects Save Data Folder
2989//      uchar includeIgorAttributes             // Affects Save Waves and Save Data Folder
2990//      uchar reservedSave[14]
2991//
2992//      uint32 reserved[100]    // Reserved for future use
2993//EndStructure
2994//
2995//Function NI2_HDF5BrowserLoadPackagePrefs(prefs)
2996//      STRUCT NI2_HDF5BrowserPrefs &prefs
2997//
2998//      Variable i
2999//
3000//      // This loads preferences from disk if they exist on disk.
3001//      LoadPackagePreferences kPackageName, kPrefFileName, kPrefRecordID, prefs
3002//
3003//      // If prefs not loaded or not valid, initialize them.
3004//      if (V_flag!=0 || prefs.prefsVersion!=kCurrentPrefsVersion)
3005//              prefs.prefsVersion = kCurrentPrefsVersion
3006//             
3007//              prefs.graphLeft = 0
3008//              prefs.graphTop = 0
3009//              prefs.graphRight = 0
3010//              prefs.graphBottom = 0
3011//                     
3012//              // Preview table location in points. 0 means default.
3013//              prefs.tableLeft = 0
3014//              prefs.tableTop = 0
3015//              prefs.tableRight = 0
3016//              prefs.tableBottom = 0
3017//                     
3018//              // Dump notebook location in points. 0 means default.
3019//              prefs.dumpLeft = 0
3020//              prefs.dumpTop = 0
3021//              prefs.dumpRight = 0
3022//              prefs.dumpBottom = 0
3023//                             
3024//              // Save Waves and Save Data Folder panel location in pixels. 0 means default.
3025//              prefs.savePanelLeft = 0
3026//              prefs.savePanelTop = 0
3027//              prefs.savePanelRight = 0
3028//              prefs.savePanelBottom = 0
3029//     
3030//              // HDF5 browser location in points. 0 means default.
3031//              prefs.browserLeft = 0
3032//              prefs.browserTop = 0
3033//              prefs.browserRight = 0
3034//              prefs.browserBottom = 0
3035//     
3036//              // Overall prefs
3037//              prefs.readOnly = 1
3038//              for(i=0; i<15; i+=1)
3039//                      prefs.reservedOverall[i] = 0
3040//              endfor
3041//             
3042//              // Load prefs
3043//              prefs.loadGroupsRecursively = 1
3044//              prefs.transpose2DDatasets = 0
3045//              for(i=0; i<14; i+=1)
3046//                      prefs.reservedLoad[i] = 0
3047//              endfor
3048//             
3049//              // Save prefs
3050//              prefs.saveGroupsRecursively = 1
3051//              prefs.includeIgorAttributes = 1
3052//              for(i=0; i<14; i+=1)
3053//                      prefs.reservedSave[i] = 0
3054//              endfor
3055//     
3056//              for(i=0; i<100; i+=1)
3057//                      prefs.reserved[i] = 0
3058//              endfor
3059//             
3060//              NI2_HDF5BrowserSavePackagePrefs(prefs)          // Create default prefs file.
3061//      endif
3062//End
3063//
3064//Function NI2_HDF5BrowserSavePackagePrefs(prefs)
3065//      STRUCT NI2_HDF5BrowserPrefs &prefs
3066//
3067//      SavePackagePreferences kPackageName, kPrefFileName, kPrefRecordID, prefs
3068//End
3069//
3070//static Function GetPrefWindowCoords(windowName, left, top, right, bottom)
3071//      String windowName
3072//      Variable &left, &top, &right, &bottom
3073//
3074//      STRUCT NI2_HDF5BrowserPrefs prefs
3075//     
3076//      NI2_HDF5BrowserLoadPackagePrefs(prefs)
3077//     
3078//      strswitch(windowName)
3079//              case "HDF5BrowserGraph":
3080//                      left = prefs.graphLeft
3081//                      top = prefs.graphTop
3082//                      right = prefs.graphRight
3083//                      bottom = prefs.graphBottom
3084//                      break
3085//             
3086//              case "HDF5BrowserTable":
3087//                      left = prefs.tableLeft
3088//                      top = prefs.tableTop
3089//                      right = prefs.tableRight
3090//                      bottom = prefs.tableBottom
3091//                      break
3092//             
3093//              case "HDF5DumpNotebook":
3094//                      left = prefs.dumpLeft
3095//                      top = prefs.dumpTop
3096//                      right = prefs.dumpRight
3097//                      bottom = prefs.dumpBottom
3098//                      break
3099//             
3100//              case "HDF5SaveWavesPanel":
3101//              case "HDF5SaveDataFolderPanel":
3102//                      left = prefs.savePanelLeft
3103//                      top = prefs.savePanelTop
3104//                      right = prefs.savePanelRight
3105//                      bottom = prefs.savePanelBottom
3106//                      break
3107//
3108//              default:                // We want to get preferred coords for a new HDF5 browser.
3109//                      left = prefs.browserLeft
3110//                      top = prefs.browserTop
3111//                      right = prefs.browserRight
3112//                      bottom = prefs.browserBottom
3113//                      break
3114//      endswitch
3115//End
3116//
3117//static Function SetPrefWindowCoords(windowName)
3118//      String windowName
3119//     
3120//      STRUCT NI2_HDF5BrowserPrefs prefs
3121//     
3122//      NI2_HDF5BrowserLoadPackagePrefs(prefs)
3123//     
3124//      GetWindow $windowName wSize
3125//
3126//      // NewPanel uses device coordinates. We therefore need to scale from
3127//      // points (returned by GetWindow) to device units for windows created
3128//      // by NewPanel.
3129//      Variable scale = ScreenResolution / 72
3130//     
3131//      strswitch(windowName)
3132//              case "HDF5BrowserGraph":
3133//                      prefs.graphLeft = V_Left
3134//                      prefs.graphTop = V_Top
3135//                      prefs.graphRight = V_Right
3136//                      prefs.graphBottom = V_Bottom
3137//                      break
3138//             
3139//              case "HDF5BrowserTable":
3140//                      prefs.tableLeft = V_left
3141//                      prefs.tableTop = V_top
3142//                      prefs.tableRight = V_Right
3143//                      prefs.tableBottom = V_Bottom
3144//                      break
3145//             
3146//              case "HDF5DumpNotebook":
3147//                      prefs.dumpLeft = V_left
3148//                      prefs.dumpTop = V_top
3149//                      prefs.dumpRight = V_Right
3150//                      prefs.dumpBottom = V_Bottom
3151//                      break
3152//                     
3153//              case "HDF5SaveWavesPanel":
3154//              case "HDF5SaveDataFolderPanel":
3155//                      prefs.savePanelLeft = V_left * scale
3156//                      prefs.savePanelTop = V_top * scale
3157//                      prefs.savePanelRight = V_Right * scale
3158//                      prefs.savePanelBottom = V_Bottom * scale
3159//                      break
3160//
3161//              default:                // We want to set preferred coords for a new HDF5 browser.
3162//                      prefs.browserLeft = V_left * scale
3163//                      prefs.browserTop = V_top * scale
3164//                      prefs.browserRight = V_Right * scale
3165//                      prefs.browserBottom = V_Bottom * scale
3166//                      break
3167//      endswitch
3168//
3169//      NI2_HDF5BrowserSavePackagePrefs(prefs)
3170//End
3171//
3172//static Function GetPrefBrowserSettings(readOnly, loadGroupsRecursively, transpose2DDatasets)
3173//      Variable &readOnly
3174//      Variable &loadGroupsRecursively
3175//      Variable &transpose2DDatasets
3176//
3177//      STRUCT NI2_HDF5BrowserPrefs prefs
3178//     
3179//      NI2_HDF5BrowserLoadPackagePrefs(prefs)
3180//
3181//      readOnly = prefs.readOnly
3182//      loadGroupsRecursively = prefs.loadGroupsRecursively
3183//      transpose2DDatasets = prefs.transpose2DDatasets
3184//End
3185//
3186//// ************* End of HDF5 Browser Prefs Routines ***************
3187//
3188//// ************* Start of HDF5 Utility Routines ***************
3189//
3190//Function NI2_HDF5CheckDataClass(dataClassStr, errorMessage)
3191//      String dataClassStr
3192//      String &errorMessage
3193//     
3194//      Variable err = 0
3195//      errorMessage = ""
3196//
3197//      strswitch(dataClassStr)
3198//              case "H5T_TIME":
3199//                      errorMessage = "HDF5XOP does not support data of class H5T_TIME."
3200//                      err = -1
3201//                      break
3202//      endswitch
3203//
3204//      return err
3205//End
3206//
3207//Function NI2_HDF5MakeHyperslabWave(path, numRows)
3208//      String path                     // Path to wave. e.g., "root:slab"
3209//      Variable numRows
3210//     
3211//      Make /O /N=(numRows,4) $path
3212//      Wave slab = $path
3213//      slab = 1                                                                // Set all elements to 1.
3214//
3215//      Variable row
3216//      String dimLabel
3217//      for(row=0; row<numRows; row+=1)
3218//              sprintf dimLabel, "Dimension %d", row           // HR, 060206: Fixed setting of row dimension labels.
3219//              SetDimLabel 0, row, $dimLabel, slab
3220//      endfor
3221//      SetDimLabel 1, 0, Start, slab
3222//      SetDimLabel 1, 1, Stride, slab
3223//      SetDimLabel 1, 2, Count, slab
3224//      SetDimLabel 1, 3, Block, slab
3225//End
3226//
3227//Constant NI2_H5S_MAX_RANK = 32
3228//
3229//Constant NI2_kHDF5DataInfoVersion = 1000              // 1000 means 1.000.
3230//
3231//Structure NI2_HDF5DataInfo                                    // Use with HDF5DatasetInfo and HDF5AttributeInfo functions
3232//      // Input fields (inputs to HDF5 XOP)
3233//      uint32 version                                                  // Must be set to kHDF5DataInfoVersion
3234//      char structName[16]                                             // Must be "HDF5DataInfo".
3235//
3236//      // Output fields (outputs from HDF5 XOP)
3237//      double datatype_class;                          // e.g., H5T_INTEGER, H5T_FLOAT.
3238//      char datatype_class_str[32];            // String with class spelled out. e.g., "H5T_INTEGER", "H5T_FLOAT".
3239//      double datatype_size;                                   // Size in bytes of one element.
3240//      double datatype_sign;                                   // H5T_SGN_NONE (unsigned), H5T_SGN_2 (signed), H5T_SGN_ERROR (this type does not have a sign, i.e., it is not an integer type).
3241//      double datatype_order;                          // H5T_ORDER_LE, H5T_ORDER_BE, H5T_ORDER_VAX
3242//      char datatype_str[64];                          // Human-readable string, e.g., "16-bit unsigned integer"
3243//      double dataspace_type;                          // H5S_NO_CLASS (-1), H5S_SCALAR (0), H5S_SIMPLE (1), H5S_COMPLEX (2).
3244//      double ndims;                                                           // Zero for H5S_SCALAR. Number of dimensions in the dataset for H5S_SIMPLE.
3245//      double dims[NI2_H5S_MAX_RANK];                  // Size of each dimension.
3246//      double maxdims[NI2_H5S_MAX_RANK];               // Maximum size of each dimension.
3247//EndStructure
3248//
3249//Function NI2_InitHDF5DataInfo(di)                             // Sets input fields.
3250//      STRUCT NI2_HDF5DataInfo &di
3251//     
3252//      // HDF5XOP uses these fields to make sure the structure passed in to it is compatible.
3253//      di.version = NI2_kHDF5DataInfoVersion
3254//      di.structName = "HDF5DataInfo"
3255//End
3256//
3257////    HDF5DatasetRank(locationID, name)
3258////    Returns rank or zero in event of error.
3259//Function NI2_HDF5DatasetRank(locationID, name)
3260//      Variable locationID
3261//      String name
3262//
3263//#if Exists("HDF5OpenFile")   
3264//      STRUCT NI2_HDF5DataInfo di
3265//      NI2_InitHDF5DataInfo(di)                        // Set input fields.
3266//
3267//      Variable err = HDF5DatasetInfo(locationID, name, 1, di)
3268//      if (err != 0)
3269//              return 0
3270//      endif
3271//      Variable rank = di.ndims
3272//      return rank
3273//#else
3274//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
3275//#endif
3276//End
3277//
3278////    HDF5AttributeRank(locationID, name)
3279////    Returns rank or zero in event of error.
3280//Function NI2_HDF5AttributeRank(locationID, objectName, objectType, attributeName)
3281//      Variable locationID
3282//      String objectName
3283//      Variable objectType
3284//      String attributeName
3285//
3286//#if Exists("HDF5OpenFile")   
3287//      STRUCT NI2_HDF5DataInfo di
3288//      NI2_InitHDF5DataInfo(di)                        // Set input fields.
3289//
3290//      Variable err = HDF5AttributeInfo(locationID, objectName, objectType, attributeName, 1, di)
3291//      if (err != 0)
3292//              return 0
3293//      endif
3294//      Variable rank = di.ndims
3295//      return rank
3296//#else
3297//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
3298//#endif
3299//End
3300//
3301//Constant NI2_kHDF5DatatypeInfoVersion = 1000          // 1000 means 1.000.
3302//Structure  NI2_HDF5DatatypeInfo                                                       // Use with HDF5TypeInfo functions
3303//      // Input fields (inputs to HDF5 XOP)
3304//      uint32 version                                  // Structure version. Used for backward compatibility.
3305//      char structName[32]                             // Must be "HDF5DatatypeInfo". Used to prevent passing wrong structure to XFUNC.
3306//     
3307//      // Output fields (outputs from HDF5 XOP)
3308//      double type_class                               // e.g., H5T_INTEGER, H5T_FLOAT.
3309//      char type_class_str[32]         // String with class spelled out. e.g., "H5T_INTEGER", "H5T_FLOAT".
3310//      double size                                             // Size in bytes of one element.
3311//      double sign                                             // H5T_SGN_NONE (unsigned), H5T_SGN_2 (signed), H5T_SGN_ERROR (this type does not have a sign, i.e., it is not an integer type).
3312//      double order                                            // H5T_ORDER_LE, H5T_ORDER_BE, H5T_ORDER_VAX, H5T_ORDER_ERROR (this type does not have an order).
3313//      double cset                                             // Currently must be H5T_CSET_ASCII (0).
3314//      double strpad                                           // H5T_str_t: H5T_STR_ERROR (-1), H5T_STR_NULLTERM (0), H5T_STR_NULLPAD (1), H5T_STR_SPACEPAD (2)
3315//      double nmembers                                 // For enum or compound datatypes only, number of members.
3316//      String names                                            // For enum or compound datatypes only, semicolon-separated list of enum names.
3317//      int32 values[100]                               // For enum datatype only, list of enum values. For compound datatype, list of classes.
3318//      String opaque_tag                               // For opaque datatypes only, tag name.
3319//EndStructure
3320//
3321//Function NI2_InitHDF5DatatypeInfo(dti)                        // Sets input fields.
3322//      STRUCT NI2_HDF5DatatypeInfo &dti
3323//     
3324//      // HDF5XOP uses these fields to make sure the structure passed in to it is compatible.
3325//      dti.version = NI2_kHDF5DatatypeInfoVersion
3326//      dti.structName = "NI2_HDF5DatatypeInfo"
3327//End
3328//
3329//// ************* End of HDF5 Utility Routines ***************
3330//
3331//// ************* Start of HDF5 Save Routines ***************
3332//
3333//static Function StringsAreEqual(str1, str2)   // Case sensitive
3334//      String str1, str2
3335//     
3336//      Variable len1=strlen(str1), len2=strlen(str2)
3337//      if (len1 != len2)
3338//              return 0
3339//      endif
3340//     
3341//      Variable i
3342//      for(i=0; i<len1; i+=1)
3343//              if (char2num(str1[i]) != char2num(str2[i]))
3344//                      return 0
3345//              endif
3346//      endfor
3347//     
3348//      return 1
3349//End
3350//
3351//static Function/S GetUnquotedLeafName(path)
3352//      String path                     // Path to data folder or wave
3353//     
3354//      String name
3355//      name = ParseFilePath(0, path, ":", 1, 0)                // Just the name without path.
3356//     
3357//      // Remove single quotes if present
3358//      if (CmpStr(name[0],"'") == 0)
3359//              Variable len = strlen(name)
3360//              name = name[1,len-2]   
3361//      endif
3362//     
3363//      return name
3364//End
3365//
3366//static Function HaveObjectNameConflict(listOfObjectsInGroup, listOfObjectsToBeSaved, conflictingObjectName)
3367//      String listOfObjectsInGroup                     // Semicolon-separated list of all types of objects in selected group or list of datasets in selected group.
3368//      String listOfObjectsToBeSaved           // Semicolon-separated list of names of objects about to be saved in the HDF5 file.
3369//      String &conflictingObjectName
3370//     
3371//      conflictingObjectName = ""
3372//     
3373//      Variable i, j
3374//      Variable numObjectsInList, numObjectsToBeSaved
3375//     
3376//      numObjectsInList = ItemsInList(listOfObjectsInGroup)
3377//      numObjectsToBeSaved = ItemsInList(listOfObjectsToBeSaved)
3378//      for(i=0; i<numObjectsToBeSaved; i+=1)
3379//              String objectToBeSavedName = StringFromList(i, listOfObjectsToBeSaved)
3380//              objectToBeSavedName = GetUnquotedLeafName(objectToBeSavedName)          // Just the name without path.
3381//              if (CmpStr(objectToBeSavedName, "root") == 0)
3382//                      objectToBeSavedName = IgorInfo(1)               // Use name of current experiment instead of "root".
3383//              endif
3384//              for(j=0; j<numObjectsInList; j+=1)
3385//                      String groupObjectName = StringFromList(j, listOfObjectsInGroup)
3386//                      if (StringsAreEqual(groupObjectName,objectToBeSavedName))
3387//                              conflictingObjectName = groupObjectName
3388//                              return 1
3389//                      endif
3390//              endfor
3391//      endfor
3392//
3393//      return 0
3394//End
3395//
3396//static Function SaveButtonProc(ctrlName) : ButtonControl
3397//      String ctrlName
3398//     
3399//#if Exists("HDF5OpenFile")   
3400//      String panelName = WinName(0, 64)
3401//      String message
3402//     
3403//      String list = WS_SelectedObjectsList(panelName, "SelectorList")
3404//      if (strlen(list) == 0)
3405//              strswitch(panelName)
3406//                      case "HDF5SaveWavesPanel":
3407//                              DoAlert 0, "You must select one or more waves to save first."
3408//                              break
3409//                             
3410//                      case "HDF5SaveDataFolderPanel":
3411//                              DoAlert 0, "You must select a data folder to save first."
3412//                              break
3413//              endswitch
3414//              return -1
3415//      endif
3416//     
3417//      String browserName = NI2_HDF5GetTopBrowserName()
3418//      if (strlen(browserName) == 0)
3419//              return -1                                                               // HDF5 Browser was killed.
3420//      endif
3421//
3422//      STRUCT NI2HDF5BrowserData bd
3423//      SetNI2HDF5BrowserData(browserName, bd)
3424//     
3425//      // Get list of all types of objects in the selected group (including named datasets and links)
3426//      HDF5ListGroup /TYPE=15 bd.fileID, bd.groupPath
3427//      String listOfObjectsInSelectedGroup = S_HDF5ListGroup
3428//
3429//      Variable haveConflict
3430//      String conflictingObjectName
3431//      haveConflict = HaveObjectNameConflict(listOfObjectsInSelectedGroup,list,conflictingObjectName)
3432//      if (haveConflict)
3433//              sprintf message, "The name '%s' is in use.\r\rOverwrite objects with conflicting names?", conflictingObjectName
3434//              DoAlert 1, message
3435//              if (V_flag != 1)
3436//                      return -1
3437//              endif
3438//      endif
3439//
3440//      ControlInfo /W=$panelName IncludeIgorAttributes
3441//      Variable igorAttributesMask = V_value ? -1 : 0
3442//      Variable varMode = V_value ? 1 : 0
3443//     
3444//      String groupPath = NI2_SelectedGroupPath(bd)    // Currently selected group
3445//      String newGroupPath = ""                                                        // Name of group we created, if any.
3446//     
3447//      Variable index = 0
3448//      do
3449//              String item = StringFromList(index, list)
3450//              if (strlen(item) == 0)
3451//                      break                                                                   // No more waves
3452//              endif
3453//             
3454//              strswitch(panelName)
3455//                      case "HDF5SaveWavesPanel":
3456//                              Wave w = $item
3457//                              String datasetPath = NI2_HDF5GetObjectFullPath(groupPath, NameOfWave(w))
3458//                              HDF5SaveData /IGOR=(igorAttributesMask) /O w, bd.fileID, datasetPath
3459//                              break
3460//                             
3461//                      case "HDF5SaveDataFolderPanel":
3462//                              String dfName = ParseFilePath(0, item, ":", 1, 0)               // Just the data folder name without path.
3463//                              if (CmpStr(item, "root") == 0)
3464//                                      dfName = IgorInfo(1)            // Use name of current experiment instead of "root".
3465//                              endif
3466//                              newGroupPath = NI2_HDF5GetObjectFullPath(groupPath, dfName)
3467//
3468//                              ControlInfo/W=$panelName SaveGroupsRecursively
3469//                              if (V_value)
3470//                                      HDF5SaveGroup /IGOR=(igorAttributesMask) /VAR=(varMode) /O /R /T=dfName $item, bd.fileID, groupPath
3471//                              else
3472//                                      HDF5SaveGroup /IGOR=(igorAttributesMask) /VAR=(varMode) /O /T=dfName $item, bd.fileID, groupPath
3473//                              endif
3474//                              break
3475//              endswitch
3476//             
3477//              if (V_flag != 0)
3478//                      break                                                                   // Save error.
3479//              endif
3480//             
3481//              index += 1
3482//      while(1)
3483//     
3484//      strswitch(panelName)
3485//              case "HDF5SaveWavesPanel":
3486//                      FillDatasetsList(bd)
3487//                      FillDatasetAttributesList(bd)
3488//                      SetButtonStates(bd)                             // Needed to set Load Dataset button if we go from 0 datasets to >0 datasets.
3489//                      break
3490//                     
3491//              case "HDF5SaveDataFolderPanel":
3492//                      if (strlen(newGroupPath) > 0)
3493//                              FillLists(bd)
3494//                      endif
3495//                      break
3496//      endswitch
3497//#else
3498//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
3499//#endif
3500//End
3501//
3502//static Function DoneButtonProc(ctrlName) : ButtonControl
3503//      String ctrlName
3504//
3505//      String panelName = WinName(0, 64)
3506//      KillWIndow/Z $panelName
3507//End
3508//
3509//static Function GetPrefSavePanelSettings(saveGroupsRecursively, includeIgorAttributes)
3510//      Variable &saveGroupsRecursively
3511//      Variable &includeIgorAttributes
3512//
3513//      STRUCT NI2_HDF5BrowserPrefs prefs
3514//     
3515//      NI2_HDF5BrowserLoadPackagePrefs(prefs)
3516//
3517//      saveGroupsRecursively = prefs.saveGroupsRecursively
3518//      includeIgorAttributes = prefs.includeIgorAttributes
3519//End
3520//
3521//static Function SetPrefSavePanelSettings(panelName)
3522//      String panelName
3523//     
3524//      STRUCT NI2_HDF5BrowserPrefs prefs
3525//     
3526//      NI2_HDF5BrowserLoadPackagePrefs(prefs)
3527//     
3528//      strswitch(panelName)
3529//              case "HDF5SaveWavesPanel":
3530//                      ControlInfo/W=$panelName IncludeIgorAttributes
3531//                      prefs.includeIgorAttributes = V_value
3532//                      break
3533//     
3534//              case "HDF5SaveDataFolderPanel":
3535//                      ControlInfo/W=$panelName SaveGroupsRecursively
3536//                      prefs.saveGroupsRecursively = V_value
3537//                      ControlInfo/W=$panelName IncludeIgorAttributes
3538//                      prefs.includeIgorAttributes = V_value
3539//                      break
3540//      endswitch
3541//
3542//      NI2_HDF5BrowserSavePackagePrefs(prefs)
3543//End
3544//
3545//static Function SetSaveButtonState(panelName)
3546//      String panelName
3547//     
3548//      String selection = WS_SelectedObjectsList(panelName, "SelectorList")
3549//      Variable code = strlen(selection) > 0 ? 0:2
3550//      Button Save, win=$panelName, disable=code       
3551//End
3552//
3553//Function NI2_HDF5SaveWavesPanelHook(infoStr)
3554//      String infoStr
3555//     
3556//      String panelName = "NI2_HDF5SaveWavesPanel"
3557//
3558//      String event= StringByKey("EVENT",infoStr)
3559//
3560//      strswitch(event)
3561//              case "activate":                                // We do not get this on Windows when the panel is first created.
3562//                      SetSaveButtonState(panelName)
3563//                      break
3564//                     
3565//              case "resize":
3566//              case "moved":                                   // This message was added in Igor Pro 5.04B07.
3567//                      SetPrefWindowCoords(panelName)
3568//                      break
3569//      endswitch
3570//     
3571//      return 0
3572//End
3573//
3574//Function NI2_HDF5SaveDataFolderPanelHook(infoStr)
3575//      String infoStr
3576//     
3577//      String panelName = "NI2_HDF5SaveDataFolderPanel"
3578//
3579//      String event= StringByKey("EVENT",infoStr)
3580//
3581//      strswitch(event)
3582//              case "activate":                                // We do not get this on Windows when the panel is first created.
3583//                      SetSaveButtonState(panelName)
3584//                      break
3585//                     
3586//              case "resize":
3587//              case "moved":                                   // This message was added in Igor Pro 5.04B07.
3588//                      SetPrefWindowCoords(panelName)
3589//                      break
3590//      endswitch
3591//     
3592//      return 0
3593//End
3594//
3595//
3596//
3597//static Function DisplaySaveWavesPanel()
3598//      String panelName = "NI2_HDF5SaveWavesPanel"
3599//
3600//      DoWindow/F $panelName
3601//      if (V_flag == 0)
3602//              Variable left, top, right, bottom
3603//              GetPrefWindowCoords(panelName, left, top, right, bottom)        // See if prefs set.
3604//              if (right-left<200 || bottom-top<200)
3605//                      left = 200
3606//                      top = 100
3607//                      right = 584
3608//                      bottom = 632
3609//              endif
3610//             
3611//              Variable recursive, includeIgorAttributes
3612//              GetPrefSavePanelSettings(recursive, includeIgorAttributes)
3613//
3614//              Variable showWhat = WMWS_Waves
3615//              NewPanel /W=(left,top,right,bottom) /N=$panelName /K=1 as "Save Waves as HDF5 Datasets"
3616//              TitleBox ListTitle,pos={20,16},size={163,16},title="Select Wave(s) to Save as Datasets"
3617//              TitleBox ListTitle,fSize=14,frame=0,fStyle=1
3618//              ListBox SelectorList,pos={16,48},size={350,390},mode=4  // Multiple disjoint selection allowed.
3619//              MakeListIntoWaveSelector(panelName, "SelectorList", content=showWhat)
3620//              WS_SetNotificationProc(panelName, "SelectorList", "SelectorNotification", isExtendedProc=1)
3621//              Button Save,pos={46,457},size={100,20},proc=HDF5Browser#SaveButtonProc,title="Save"
3622//              Button Done,pos={226,457},size={100,20},proc=HDF5Browser#DoneButtonProc,title="Done"
3623//              CheckBox IncludeIgorAttributes,pos={36,488},size={121,14},title="Include Igor Attributes"
3624//              CheckBox IncludeIgorAttributes,proc=HDF5BrowserPrefCheckboxProc,help={"When checked, attributes are written so that wave properties can be recreated when loading back into Igor."}
3625//              CheckBox IncludeIgorAttributes,value=includeIgorAttributes
3626//              SetSaveButtonState(panelName)
3627//              SetWindow kwTopWin,hook=NI2_HDF5SaveWavesPanelHook
3628//      endif
3629//End
3630//
3631//static Function DisplaySaveDataFolderPanel()
3632//      String panelName = "HDF5SaveDataFolderPanel"
3633//
3634//      DoWindow/F $panelName
3635//      if (V_flag == 0)
3636//              Variable left, top, right, bottom
3637//              GetPrefWindowCoords(panelName, left, top, right, bottom)        // See if prefs set.
3638//              if (right-left<200 || bottom-top<200)
3639//                      left = 200
3640//                      top = 100
3641//                      right = 584
3642//                      bottom = 632
3643//              endif
3644//             
3645//              Variable recursive, includeIgorAttributes
3646//              GetPrefSavePanelSettings(recursive, includeIgorAttributes)
3647//
3648//              Variable showWhat = WMWS_DataFolders
3649//              NewPanel /W=(left,top,right,bottom) /N=$panelName /K=1 as "Save Data Folder as HDF5 Group"
3650//              TitleBox ListTitle,pos={20,16},size={163,16},title="Select Data Folder to Save as Group"
3651//              TitleBox ListTitle,fSize=14,frame=0,fStyle=1
3652//              ListBox SelectorList,pos={16,48},size={350,390},mode=1          // Single selection only.
3653//              MakeListIntoWaveSelector(panelName, "SelectorList", content=showWhat)
3654//              WS_SetNotificationProc(panelName, "SelectorList", "SelectorNotification", isExtendedProc=1)
3655//              Button Save,pos={46,457},size={100,20},proc=HDF5Browser#SaveButtonProc,title="Save"
3656//              Button Done,pos={226,457},size={100,20},proc=HDF5Browser#DoneButtonProc,title="Done"
3657//              CheckBox SaveGroupsRecursively,pos={44,485},size={66,14},title="Save Groups Recursive",value=recursive
3658//              CheckBox SaveGroupsRecursively,proc=HDF5BrowserPrefCheckboxProc,help={"When checked, sub-data folders are recursively saved."}
3659//              CheckBox IncludeIgorAttributes,pos={44,507},size={121,14},title="Include Igor Attributes"
3660//              CheckBox IncludeIgorAttributes,proc=HDF5BrowserPrefCheckboxProc,help={"When checked, attributes are written so that wave properties can be recreated when loading back into Igor."}
3661//              CheckBox IncludeIgorAttributes,value=includeIgorAttributes
3662//              SetSaveButtonState(panelName)
3663//              SetWindow kwTopWin,hook=NI2_HDF5SaveDataFolderPanelHook
3664//      endif
3665//End
3666//
3667//Function NI2_SelectorNotification(SelectedItem, EventCode, panelName, controlName)
3668//      String SelectedItem
3669//      Variable EventCode
3670//      String panelName
3671//      String controlName
3672//     
3673//      // Printf "Panel=%s, Control=%s, Event code=%d, selection=\"%s\"\r", panelName, controlName, eventCode, selectedItem
3674//
3675//      switch(eventCode)
3676//              case WMWS_DoubleClick:
3677//                              break
3678//     
3679//              case WMWS_FolderOpened:                         // Selection is emptied when folder is opened.
3680//              case WMWS_FolderClosed:                         // Selection is emptied when folder is opened.
3681//              case WMWS_SelectionChanged:
3682//              case WMWS_SelectionChangedShift:
3683//                      SetSaveButtonState(panelName)
3684//                      break
3685//      endswitch
3686//End
3687//
3688//static Function SaveWavesButtonProc(ctrlName) : ButtonControl
3689//      String ctrlName
3690//     
3691//      KillWIndow/Z HDF5SaveDataFolderPanel    // One save panel open at a time.
3692//      DisplaySaveWavesPanel()
3693//     
3694//      return 0
3695//End
3696//
3697//static Function SaveDataFolderButtonProc(ctrlName) : ButtonControl
3698//      String ctrlName
3699//     
3700//      KillWIndow/Z HDF5SaveWavesPanel // One save panel open at a time.
3701//      DisplaySaveDataFolderPanel()
3702//     
3703//      return 0
3704//End
3705//
3706//static Function CloseSavePanels()
3707//      KillWIndow/Z HDF5SaveWavesPanel
3708//      KillWIndow/Z HDF5SaveDataFolderPanel
3709//End
3710//
3711//static Function HDF5SaveWavesPanelIsVisible()
3712//      DoWindow HDF5SaveWavesPanel
3713//      return V_flag
3714//End
3715//
3716//static Function HDF5SaveDFPanelIsVisible()
3717//      DoWindow HDF5SaveDataFolderPanel
3718//      return V_flag
3719//End
3720//
3721//// ************* End of HDF5 Save Routines ***************
3722//
Note: See TracBrowser for help on using the repository browser.