#
# export-data.tcl: Main Tcl script data export tool
#
# ------------------------------------------------
# Mumit Khan <khan@xraylith.wisc.edu>
# Center for X-ray Lithography
# University of Wisconsin-Madison
# 3731 Schneider Dr., Stoughton, WI, 53589
# ------------------------------------------------
#
# Copyright (c) 1996 Mumit Khan
#

######################### Initialize options ##############################

#
# dataexp:init:env is really executed ONLY once per interpreter. It has
# checks to avoid reinventing the wheel if we get here by "New Window"
# command.
#

proc dataexp:init:env {rwin} {
    global dataexp shadow_library
    if [info exists dataexp(initialized)] {
        incr dataexp(instances)
        incr dataexp(total_instances)
	dataexp:vputs "instance # $dataexp(instances)"
        return
    } else {
        set dataexp(instances) 1
        set dataexp(total_instances) 1
	dataexp:vputs "first instance"
    }
    #
    # make all the globals available here.
    #
    eval global [uplevel \#0 info vars]
    # Handle Tcl library environment variables
    if ![info exists env(SHADOW_GUI_ROOT)] {
        puts stderr "Warning: env(SHADOW_GUI_ROOT) does not exist."
	set env(SHADOW_GUI_ROOT) [pwd]
    }

    if [catch {set env(SHADOW_GUI_ROOT)} dataexp(shadow_gui_root)] {
	set dataexp(shadow_gui_root) $dataexp(shadow_root)
    }

    if ![info exists shadow_library] {
        puts stderr "Warning: shadow_library variable is not set."
	set shadow_library [pwd]
    }
    set dataexp(shadow_tcl_library) $shadow_library

    set tcl_precision 17

    # Set-up various paths
    lappend auto_path $dataexp(shadow_tcl_library) 
    if [catch {file join x y}] {
	lappend auto_path $dataexp(shadow_tcl_library)/dataexp
    } else {
	lappend auto_path [file join $dataexp(shadow_tcl_library) dataexp]
    }
    lappend auto_path [pwd]
    lappend auto_path [pwd]/../tcl

    # Check for correct Tcl version
    if {[info tclversion] < 7.5} {
	error "dataexp: Tcl version < 7.5 cannot be used with dataexp"
    }

    #
    # Win32 lacks a few standard variables, so fix those here.
    #
    set platform $tcl_platform(platform)
    if {$platform == "windows"} {
	if [catch {set env(HOME)} dataexp(homedir)] {
	    if [catch {set env(windir)} dataexp(homedir)] {
		set dataexp(homedir) [pwd]
	    }
	}
	if [catch {set env(USER)} dataexp(username)] {set dataexp(username) ""}
	if [catch {set env(TEMP)} dataexp(tmpdir)] {
	    if [file isdir c:/temp] {
		set dataexp(tmpdir) c:/temp
	    } elseif [file isdir c:/tmp] {
		set dataexp(tmpdir) c:/tmp
	    } else {
		set dataexp(tmpdir) .
	    }
	    # cygwin32 likes TMPDIR env variable; this way we avoid having to
	    # have a /tmp (per P_tmpdir in <stdio.h>
	    if ![info exists env(TMPDIR)] {set env(TMPDIR) $dataexp(tmpdir)}
	}
	# sanitize pathnames for C strings.
	set dataexp(homedir) [cvt_filename_to_tcl $dataexp(homedir)]
	set dataexp(tmpdir) [cvt_filename_to_tcl $dataexp(tmpdir)]
    } elseif {$platform == "unix"} {
	if [catch {set env(HOME)} dataexp(homedir)] {
	    set dataexp(homedir) [pwd]
	}
	if [catch {set env(USER)} dataexp(username)] {
	    set dataexp(username) "unknown"
	}
	if [catch {set env(TMPDIR)} dataexp(tmpdir)] {
	    set dataexp(tmpdir) "/tmp"
	}
    } else {
	error "Only works on Unix and Windows platforms for now. Sorry"
    }
}

######################### Initialize globals ##############################

# initialization that only happen once per interpreter, like the 
# dataexp:init:env, but only for dataexp specific globals.

proc dataexp:init:_once_globals {} {
    global env dataexp

    if [info exists dataexp(initialized)] {return}

    # datasets and files
    #
    set dataexp(datasets)	""	;#   and list of active datasets

    # multiple toplevels?
    set dataexp(toplevels)	""

    #
    # general SHADOW related names.
    #
    set dataexp(col_names,1)	X
    set dataexp(col_names,2)	Y
    set dataexp(col_names,3)	Z
    set dataexp(col_names,4)	X'
    set dataexp(col_names,5)	Y'
    set dataexp(col_names,6)	Z'

    set dataexp(verbose)	0
}

proc dataexp:init:globals {rwin} {
    global env dataexp

    dataexp:init:_once_globals

    # datasets and files
    #
    set dataexp($rwin,curfile)		""	;# current datafile name
    set dataexp($rwin,curdataset) 	""	;#  ... dataset being viewed
    set dataexp($rwin,instance)		$dataexp(total_instances)

    # interface globals (various window paths typically)
    if {$dataexp(total_instances) == 1} {
        set inst ""
    } else {
        set inst "#$dataexp(total_instances)"
    }
    set dataexp($rwin,win_title)		"SHADOW Plot$inst"
}

######################### Initialize preferences, startup etc 

#
# initialize user preferences
#
proc dataexp:init:preferences {rwin} { }

#
# initialize fonts. Should be called *after* init:preferences
# We should really use "tix resetoptions" and change the scheme used by
# Tix, but Tix only has 12 and 14 point font schemes and we need smaller
# ones esp on laptops.
#
proc dataexp:init:fonts {rwin} {
    global dataexp dataexp_prefs
}

#
# initialize the image to be loaded and such. Called after all other
# intialization is done.
#
proc dataexp:init:startup {rwin} {
    global dataexp dataexp_prefs

    #
    # now do the initial GUI loading if specified.
    #
    if {$dataexp($rwin,curfile) != ""} {
	set file $dataexp($rwin,curfile)
	if [catch {dataexp:_load_image $rwin $file} msg] {
	    dialog .load_error "Load Error" \
		"Error loading SHADOW ray file $file. ($msg)" \
		error 0 Dismiss
	    return
	}
    } else {
	dataexp:misc:add_file_to_title $rwin ""
    }
    return 0
}

######################### Utilities #######################################


#----------------------------------------------------------------------#
# Misc front-end Routines 
#----------------------------------------------------------------------#

proc dataexp:cleanup_and_exit {{status 0}} {
    global dataexp
    # REMOVE any temp files ...
    exit $status
}

# effects - Print usage message and exist
proc dataexp:usage {{status 1}} {
    puts stderr {
Usage: dataexp [-hv] [SHADOW_IMAGE_FILE]
 
    -v:         turn on verbose mode (default: off)
    -h:         print this info
    SHADOW_IMAGE:  Loads the shadow image file and display data info
 
Examples:

    % dataexp                  ;# Start up SHADOW workspace with def options.
    % dataexp star.02          ;# Start up and load star.02 (OE 2)

    }
    exit $status
}


# verbose mode puts
proc dataexp:vputs {args} {
    global dataexp
    if {[info exists dataexp(verbose)] && $dataexp(verbose)} {
	puts stderr "dataexp: [join $args]"
    }
}

# parse the command line arguments and fill up the dataexp array elements.
proc dataexp:parse_args {rwin} {
    global argv dataexp
    dataexp:vputs "parsing argv: $argv"
    while {[llength $argv] != 0} {
	set arg [lindex $argv 0]
	set argv [lrange $argv 1 end]
	dataexp:vputs "arg = $arg, argv = $argv"

	case $arg in {
	    -h* {
		# don't exit with an error status - not an error
		dataexp:usage 0
	    }
	    -v* {
		set dataexp(verbose) 1
		dataexp:vputs "setting verbose mode to on"
	    }
	    -* {
		puts stderr "dataexp: bad option \"$arg\"."
		dataexp:usage
	    }
	    * {
		if {$dataexp($rwin,curfile) != ""} {
		    puts stderr "dataexp: Can only load one image at a time."
		    dataexp:usage 
		} else {
		    set dataexp($rwin,curfile) "$arg"
		}
	    }
	}
    }

    dataexp:vputs "current image file:       $dataexp($rwin,curfile)"
}

####################### Plotting routines ################################

proc dataexp:graph:show_info {rwin} {
    global dataexp
    set dataset $dataexp($rwin,curdataset)

    set ray_info   [$dataset info rays]
    set total_rays [lindex $ray_info 0]
    set good_rays  [lindex $ray_info 1]
    set lost_rays  [expr $total_rays - $good_rays]

    set horiz_min    [lindex $dataexp($rwin,cur_limits) 0]
    set horiz_max    [lindex $dataexp($rwin,cur_limits) 1]
    set horiz_length [expr $horiz_max - $horiz_min]
    set horiz_center [expr $horiz_max - $horiz_length/2.0]

    set vert_min     [lindex $dataexp($rwin,cur_limits) 2]
    set vert_max     [lindex $dataexp($rwin,cur_limits) 3]
    set vert_length  [expr $vert_max - $vert_min]
    set vert_center  [expr $vert_max - $vert_length/2.0]

    set horiz_col [set dataexp(col_names,$dataexp($rwin,col_x))]
    set vert_col  [set dataexp(col_names,$dataexp($rwin,col_y))]

    set text ""
    append text "H Length: $horiz_length\n"
    append text "H Center: $horiz_center\n"
    append text "V Length: $vert_length\n"
    append text "V Center: $vert_center\n\n"

    append text "Limits:   $dataexp($rwin,scale)\n\n"

    append text "Rays:     $dataexp($rwin,rays)\n\n"

    append text "Total:    $total_rays\n"
    append text "Lost:     $lost_rays\n\n"

    append text "Horiz:    $dataexp(col_names,$dataexp($rwin,col_x))\n"
    append text "Vert:     $dataexp(col_names,$dataexp($rwin,col_y))\n"

    set w $dataexp($rwin,plot_master_w)
    set llx $dataexp(info_llx)
    set lly $dataexp(info_lly)
    set urx [expr $llx + $dataexp(info_width)]
    set ury [expr $lly - $dataexp(info_height)]
    $w create rectangle $llx $lly $urx $ury -width 2 ;#-outline red
    set x [expr $llx + 10]
    set y [expr $ury + 10]

    set font -*-fixed-bold-r-normal-*-14-*-*-*-*-*-*-*
    set font -*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*
    set font -*-courier-medium-r-normal-*-*-120-*-*-*-*-*-*

    $w create text $x $y -text $text -anchor nw -font $font
}

####################### Command callbacks ################################

proc dataexp:close_cmd {rwin} {
    global dataexp
    # release resources. CHECK
    catch {shdata delete $dataexp($rwin,curdataset)}
    destroy $rwin
}

proc dataexp:exit_cmd {rwin {status 0}} {
    dataexp:cleanup_and_exit $status
}

proc dataexp:new_window_cmd {} {
    for {set cnt 1} {$cnt <= 50} {incr cnt} {
	set toplevel .dataexp#$cnt
	if ![winfo exists $toplevel] {
	    dataexp:main $toplevel
	    return
	}
    }
    error "Too many (50) Shadow plot windows open. Please close some"
}

####################### Export helpers ################################

proc dataexp:_export_histogram {rwin histo_which file} {
    dataexp:vputs "_export_histogram: rwin = $rwin, histo = $histo_which"
    if [catch {open $file "w"} fid] {
	dialog .export "Export Error" \
	    "Error opening output file \"$file\"\n\t(Message: $msg)" \
	    error 0 Dismiss 
	return
    }
    global dataexp
    global  ${histo_which}_xvector_$rwin ${histo_which}_vector_$rwin
    set npoints [${histo_which}_xvector_$rwin length]
    for {set i 0} {$i < $npoints} {incr i} {
	set var ${histo_which}_xvector_${rwin}($i)
	set xval [set $var]
	set var ${histo_which}_vector_${rwin}($i)
	set yval [set $var]
	puts $fid [format "%12.5E    %12.5E" $xval $yval]
    }
    close $fid
}

proc dataexp:export_histogram_cmd {rwin histo_which {file {}}} {
    global dataexp
    if {$dataexp($rwin,curdataset) == ""} {
	dialog .export "Export Error" \
	    "Must load a dataset before you can export data from it" \
	    error 0 Dismiss 
	return
    }
    if {$file == ""} {
	set types {
	    {{Misc Data Files}		{.dat}}
	    {{SHADOW Workspace Files}	{.ws}}
	    {{SHADOW Namelist Files}	{start.*}}
	    {{SHADOW Source Image}	{begin.dat}}
	    {{SHADOW Image Files}	{star.*}}
	    {{SHADOW Image Files}	{mirr.*}}
	    {{All Files}		*}
	}
        set file [tk_getSaveFile \
	    -parent $rwin \
	    -title "Export SHADOW histogram data to file" \
	    -initialfile "${histo_which}.dat" \
	    -defaultextension ".dat" \
	    -filetypes $types \
        ]
	set file [string trim $file]
	if {[string length $file] != 0} {
	    dataexp:_export_histogram $rwin $histo_which $file
	}
    }
}

proc dataexp:_export_scatter {rwin file} {
    if [catch {open $file "w"} fid] {
	dialog .export "Export Error" \
	    "Error opening output file \"$file\"\n\t(Message: $msg)" \
	    error 0 Dismiss 
	return
    }
    global dataexp
    catch {busy hold $rwin}
    if {$dataexp($rwin,rays) == "all" || $dataexp($rwin,rays) == "good"} {
	global Xgood_vector_${rwin} Ygood_vector_${rwin}
	set npoints [Xgood_vector_${rwin} length]
	dataexp:vputs "_export_scatter: npoints = $npoints"
	for {set i 0} {$i < $npoints} {incr i} {
	    set var Xgood_vector_${rwin}($i)
	    set xval [set $var]
	    set var Ygood_vector_${rwin}($i)
	    set yval [set $var]
	    puts $fid [format "%12.5E    %12.5E" $xval $yval]
	}
    } 
    if {$dataexp($rwin,rays) == "all" || $dataexp($rwin,rays) == "lost"} {
	global Xlost_vector_${rwin} Ylost_vector_${rwin}
	set npoints [Xlost_vector_${rwin} length]
	dataexp:vputs "_export_scatter: npoints = $npoints"
	for {set i 0} {$i < $npoints} {incr i} {
	    set var Xlost_vector_${rwin}($i)
	    set xval [set $var]
	    set var Ylost_vector_${rwin}($i)
	    set yval [set $var]
	    puts $fid [format "%12.5E    %12.5E" $xval $yval]
	}
    } 
    close $fid
    catch {busy release $rwin}
}

proc dataexp:export_scatter_cmd {rwin {file {}}} {
    global dataexp
    if {$dataexp($rwin,curdataset) == ""} {
	dialog .export "Export Error" \
	    "Must load a dataset before you can export data from it" \
	    error 0 Dismiss 
	return
    }
    if {$file == ""} {
	set types {
	    {{Misc Data Files}		{.dat}}
	    {{SHADOW Workspace Files}	{.ws}}
	    {{SHADOW Namelist Files}	{start.*}}
	    {{SHADOW Source Image}	{begin.dat}}
	    {{SHADOW Image Files}	{star.*}}
	    {{SHADOW Image Files}	{mirr.*}}
	    {{All Files}		*}
	}
        set file [tk_getSaveFile \
	    -parent $rwin \
	    -title "Export SHADOW scatter data to file" \
	    -initialfile "scatter.dat" \
	    -defaultextension ".dat" \
	    -filetypes $types \
        ]
	set file [string trim $file]
	if {[string length $file] != 0} {
	    dataexp:_export_scatter $rwin $file
	}
    }
}

####################### Menubar callbacks ################################

proc dataexp:info:make {w dataset which_rays} {
    set headers {
	"NpCol"
	"Parameter"
	"Minimum"
	"Maximum"
	"Center"
	"Std. Dev."
    }

    global dataexp
    set data ""
    foreach column "1 2 3 4 5 6 11 20" {
        set coldata [$dataset info column $column $which_rays]
	lappend data $coldata
    }

    # Create the grid
    #
    tixScrolledGrid $w.g -bd 0
    pack $w.g -expand yes -fill both -padx 3 -pady 3

    set grid [$w.g subwidget grid]
    $grid config -formatcmd "dataexp:info:gformat $grid"

    # Set the size of the columns
    #
    $grid size col 0 -size auto
    $grid size col 1 -size auto
    $grid size col 2 -size auto
    $grid size col 3 -size auto
    $grid size col 4 -size auto
    $grid size col 5 -size auto
    $grid size col 6 -size auto

    # set the default size of the column and rows. these sizes will be used
    # if the size of a row or column has not be set via the "size col ?"
    # command
    $grid size col default -size 5char
    $grid size row default -size 1.1char -pad0 3

    set margin [tixDisplayStyle text -refwindow $grid   \
	-anchor c -padx 3 -font [tix option get bold_font]]
    set name [tixDisplayStyle text  -refwindow $grid  \
	-anchor w]
    set number [tixDisplayStyle text  -refwindow $grid  \
	-anchor e]

    # Create the headers
    #
    set x 1
    foreach h $headers {
	$grid set $x 0 -itemtype text -text $h -style $margin
	incr x
    }

    set i         1
    foreach line $data {
	set col    [lindex $line 0]
	set npcol  [lindex $line 1]
	set par    [lindex $line 2]
	set min    [lindex $line 3]
	set max    [lindex $line 4]
	set center [lindex $line 5]
	set stddev [lindex $line 6]

	$grid set 0 $i -itemtype text -style $margin -text $col
	$grid set 1 $i -itemtype text -style $number -text $npcol
	$grid set 2 $i -itemtype text -style $name -text $par
	$grid set 3 $i -itemtype text -style $number -text $min
	$grid set 4 $i -itemtype text -style $number -text $max
	$grid set 5 $i -itemtype text -style $number -text $center
	$grid set 6 $i -itemtype text -style $number -text $stddev

	incr i
    }
}

proc dataexp:show_info {rwin {dataset {}}} {
    global dataexp
    set w $dataexp($rwin,info_w)
    catch {destroy $w}
    set dataset [string trim $dataset]
    if {[string length $dataset] == 0} {
        set dataset $dataexp($rwin,curdataset)
    }
    set dataset [string trim $dataset]
    if {[string length $dataset] == 0} {
	set info "No dataset loaded."
	dialog .image_info "Image Info" "$info" {} 0 Dismiss
	return
    }

    toplevel $w -class Info
    wm title $w "Image Info"
    dataexp:info:make $w $dataset $dataexp($rwin,rays)
}

proc dataexp:load {rwin file} {
    global dataexp

    # for now assume that we only have one dataset loaded.
    # set cnt [expr [llength $dataexp(datasets)]]
    # set dataset dataset#${cnt}
    catch {shdata delete $dataexp($rwin,curdataset)}
    set dataset dataset,$rwin
    shdata create $dataset -load $file
    $dataset compute minmax
    $dataset select $dataexp($rwin,rays)
    set dataexp($rwin,curdataset) $dataset
    lappend dataexp(datasets) $dataset
    dataexp:show_info $rwin $dataset
}

proc dataexp:_load_image {rwin file} {
    global dataexp
    if [catch {dataexp:load $rwin [cvt_filename_to_tcl $file]} msg] {
	error "Error reading SHADOW data file \"$file\" ($msg)?"
    }
    dataexp:misc:add_file_to_title $rwin $file
    set dataexp($rwin,curfile) $file
    catch {dataexp:graph:plot $rwin}
}

proc dataexp:load_image_cmd {rwin} {
    global dataexp
    # globbing does not work on windows as on Unix
    global tcl_platform
    set platform $tcl_platform(platform)
    if {$platform == "unix"} {
	set types {
	    {{SHADOW Source Image}	{begin.dat}}
	    {{SHADOW Image Files}	{star.\[0-9\]\[0-9\]}}
	    {{SHADOW Image Files}	{mirr.\[0-9\]\[0-9\]}}
	    {{SHADOW Workspace Files}	{.ws}}
	    {{SHADOW Namelist Files}	{start.\[0-9\]\[0-9\]}}
	    {{Misc Data Files}		{.dat}}
	    {{All Files}		*}
	}
    } else {
	set types {
	    {{SHADOW Source Image}	{begin.dat}}
	    {{SHADOW Image Files}	{star.*}}
	    {{SHADOW Image Files}	{mirr.*}}
	    {{SHADOW Workspace Files}	{.ws}}
	    {{SHADOW Namelist Files}	{start.*}}
	    {{Misc Data Files}		{.dat}}
	    {{All Files}		*}
	}
    }
    set file [tk_getOpenFile \
	-parent $rwin \
	-title "Load SHADOW Image Data From File" \
	-initialfile "" \
	-filetypes $types \
    ]
    if {$file != ""} {
	dataexp:_load_image $rwin $file
    }
}

####################### PlotOpts callbacks ###############################

proc dataexp:choose_axis {rwin axis value} {
    global dataexp
    dataexp:vputs "dataexp:choose_axis: $rwin,$axis ==> $value"
    set dataexp($rwin,$axis) $value
    dataexp:vputs "dataexp($rwin,$axis) ==> $value"
}

proc dataexp:choose_rays {rwin ray value} {
    global dataexp
    if {$value == 1} {
	dataexp:vputs "dataexp:choose_rays: ==> $rwin,$ray $value"
	set dataexp($rwin,rays) $ray
	dataexp:graph:replot $rwin
    }
}

proc dataexp:choose_plots {rwin plot show} {
    global dataexp
    dataexp:vputs "dataexp:choose_plots: ==> $rwin,$plot $show"
    set dataexp($rwin,plot_${plot}) $show
    dataexp:graph:replot $rwin
}

proc dataexp:choose_scale {rwin scale value} {
    global dataexp
    if {$value == 1} {
	dataexp:vputs "dataexp:choose_scale: ==> $rwin,$scale $value"
	set dataexp($rwin,scale) $scale
	dataexp:graph:replot $rwin
    }
}

######################## GUI routines ####################################

proc dataexp:GUI:topmenu {rwin menu_name} {
    global dataexp dataexp_prefs

    lappend menu_names $menu_name.mFile
    # build widget $menu_name.mFile
    menubutton $menu_name.mFile \
	-background {LightGray} \
	-foreground {black} \
	-menu "$menu_name.mFile.m" \
	-text {File} \
	-underline {0}

    # build widget $menu_name.mFile.m
    menu $menu_name.mFile.m \
	-background {LightGrey} \
	-foreground {black} \
	-tearoff 0

    $menu_name.mFile.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-command "dataexp:load_image_cmd $rwin" \
	-label {Load ...} \
	-underline {-1}

    $menu_name.mFile.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-command "dataexp:export_data_cmd $rwin" \
	-label {Export ...} \
	-underline {-1}

    $menu_name.mFile.m add separator

    # ============================================== 

    # build cascade menu for importing/export shadow namelist files
    $menu_name.mFile.m add cascade \
	-menu "$menu_name.mFile.m.mImport" \
	-label {Import Data} \
	-underline {-1}

    # build widget $menu_name.mFile.m.mImport
    menu $menu_name.mFile.m.mImport \
	-background {LightGrey} \
	-foreground {black} \
	-tearoff 0

    $menu_name.mFile.m.mImport add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Scatter ...} \
	-state disabled \
	-underline {-1}

    $menu_name.mFile.m.mImport add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Histogram ...} \
	-state disabled \
	-underline {-1}

    # build cascade menu for importing/export shadow namelist files
    $menu_name.mFile.m add cascade \
	-menu "$menu_name.mFile.m.mExport" \
	-label {Export Data} \
	-underline {-1}

    # build widget $menu_name.mFile.m.mExport
    menu $menu_name.mFile.m.mExport \
	-background {LightGrey} \
	-foreground {black} \
	-tearoff 0

    $menu_name.mFile.m.mExport add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Scatter ...} \
	-command "dataexp:export_scatter_cmd $rwin" \
	-underline {-1}

    $menu_name.mFile.m.mExport add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Side Histogram ...} \
	-command "dataexp:export_histogram_cmd $rwin histo_s" \
	-underline {-1}

    $menu_name.mFile.m.mExport add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Top Histogram ...} \
	-command "dataexp:export_histogram_cmd $rwin histo_t" \
	-underline {-1}

    $menu_name.mFile.m add separator

    $menu_name.mFile.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-command "dataexp:new_window_cmd" \
	-label {New Window} \

    $menu_name.mFile.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-command "dataexp:close_cmd $rwin" \
	-label {Close Window} \
	-underline {1}

    # only toplevel "." gets the exit command. this makes sure that if
    # we're running under SHADOW GUI, we don't exit the entire GUI when
    # closing the Plot window.
    if ![string compare $rwin "."] {
	$menu_name.mFile.m add separator
	$menu_name.mFile.m add command \
	    -activebackground {SteelBlue2} \
	    -background {LightGray} \
	    -command "dataexp:exit_cmd $rwin" \
	    -label {Exit} \
	    -underline {1} \
	    -accelerator {Ctrl-x}
    }

    lappend menu_names $menu_name.mPlot
    # build widget $menu_name.mPlot
    menubutton $menu_name.mPlot \
	-background {LightGray} \
	-foreground {black} \
	-menu "$menu_name.mPlot.m" \
	-text {Plot} \
	-underline {0}

    # build widget $menu_name.mPlot.m
    menu $menu_name.mPlot.m \
	-background {LightGrey} \
	-foreground {black} \
	-tearoff 0

    $menu_name.mPlot.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Plot} \
	-command "dataexp:plot_cmd $rwin" \
	-underline {-1}

    $menu_name.mPlot.m add separator

    $menu_name.mPlot.m add checkbutton \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Scatter plot} \
	-variable dataexp(plot_scatter) \
	-command "dataexp:show_plot_cmd $rwin scatter" \
	-underline {-1}

    $menu_name.mPlot.m add checkbutton \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Top Histogram} \
	-variable dataexp(plot_histo_t) \
	-command "dataexp:show_plot_cmd $rwin histo_t" \
	-underline {-1}

    $menu_name.mPlot.m add checkbutton \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Side Histogram} \
	-variable dataexp(plot_histo_s) \
	-command "dataexp:show_plot_cmd $rwin histo_s" \
	-underline {-1}

    $menu_name.mPlot.m add checkbutton \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Text Information} \
	-variable dataexp(plot_info) \
	-command "dataexp:show_plot_cmd $rwin info" \
	-underline {-1}

    lappend menu_names $menu_name.mOptions
    # build widget $menu_name.mOptions
    menubutton $menu_name.mOptions \
	-background {LightGray} \
	-foreground {black} \
	-menu "$menu_name.mOptions.m" \
	-text {Options} \
	-underline {0}

    # build widget $menu_name.mOptions.m
    menu $menu_name.mOptions.m \
	-background {LightGrey} \
	-foreground {black} \
	-tearoff 0

    $menu_name.mOptions.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Refresh Plots} \
	-command "dataexp:plot_cmd $rwin" \
	-underline {-1}

    $menu_name.mOptions.m add checkbutton \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Verbose Mode} \
	-variable dataexp(verbose) \
	-underline {-1}

    global tcl_platform
    if ![string compare $tcl_platform(platform) unix] {
	$menu_name.mOptions.m add checkbutton \
	    -activebackground {SteelBlue2} \
	    -background {LightGray} \
	    -label {Strict Motif} \
	    -variable tk_strictMotif \
	    -onvalue 1 -offvalue 0 \
	    -underline {-1}
    }

    $menu_name.mOptions.m add checkbutton \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Show Grid} \
	-variable dataexp(plot_grid) \
	-command "dataexp:plot_grid_cmd $rwin" \
	-underline {-1}

    $menu_name.mOptions.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Change directory} \
	-state disabled \
	-command "dataexp:chdir_cmd $rwin" \
	-underline {-1}

    $menu_name.mOptions.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Reread Data} \
	-state disabled \
	-command "dataexp:reread_plots $rwin" \
	-underline {-1}

    $menu_name.mOptions.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Show Info} \
	-command "dataexp:show_info $rwin" \
	-underline {-1}

    $menu_name.mOptions.m add separator

    # build cascade menu for Preferences
    $menu_name.mOptions.m add cascade \
	-menu "$menu_name.mOptions.m.mPreferences" \
	-label {Preferences} \
	-underline {-1}

    # build cascaded menu for $menu_name.mDelete
    menu $menu_name.mOptions.m.mPreferences \
	-background {LightGrey} \
	-foreground {black} \
	-tearoff 0

    $menu_name.mOptions.m.mPreferences add checkbutton \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Show Plot at Startup} \
	-state disabled \
	-variable dataexp_prefs(show_plot_at_startup) \
	-underline {-1}

    $menu_name.mOptions.m.mPreferences add checkbutton \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Show Info at Startup} \
	-state disabled \
	-variable dataexp_prefs(show_info_at_startup) \
	-underline {-1}

    $menu_name.mOptions.m.mPreferences add checkbutton \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Show Console Window} \
	-variable dataexp_prefs(show_console) \
	-command "dataexp:show_console_cmd" \
	-underline {-1}

    $menu_name.mOptions.m.mPreferences add separator

    $menu_name.mOptions.m.mPreferences add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Reload preferences} \
	-state disabled \
	-command "dataexp:load_prefs_cmd $rwin" \
	-underline {-1}

    $menu_name.mOptions.m.mPreferences add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Save preferences} \
	-state disabled \
	-command "dataexp:save_prefs_cmd $rwin" \
	-underline {-1}

    $menu_name.mOptions.m.mPreferences add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-label {Reset to defaults} \
	-state disabled \
	-command "dataexp:reset_prefs_cmd $rwin" \
	-underline {-1}

    lappend menu_names $menu_name.mHelp
    # build widget $menu_name.mHelp
    menubutton $menu_name.mHelp \
	-background {LightGray} \
	-foreground {black} \
	-menu "$menu_name.mHelp.m" \
	-text {Help} \
	-underline {0}

    # build widget $menu_name.mHelp.m
    menu $menu_name.mHelp.m \
	-background {LightGrey} \
	-foreground {black} \
	-tearoff 0

    $menu_name.mHelp.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-command "dataexp:about_cmd $rwin" \
	-label {About} \
	-state disabled \
	-underline {0}

    $menu_name.mHelp.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-command "dataexp:about_author_cmd $rwin" \
	-label {Author} \
	-state disabled \
	-underline {0}

    $menu_name.mHelp.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-command "dataexp:help_on_topmenu_cmd $rwin" \
	-label {On pulldown menu} \
	-state disabled \
	-underline {3}

    $menu_name.mHelp.m add command \
	-activebackground {SteelBlue2} \
	-background {LightGray} \
	-command "dataexp:help_on_commands_cmd $rwin" \
	-label {On Tcl commands} \
	-state disabled \
	-underline {7}

    # pack widget $menu_name
    pack append $menu_name \
	$menu_name.mFile {left frame center} \
	$menu_name.mOptions {left frame center} \
	$menu_name.mHelp {right frame center}

    focus $menu_name

    #
    # install the global bindings (accelerators).
    #
    bind all	<Control-x>	"dataexp:exit_cmd $rwin"
    bind Entry	<Control-x>	"dataexp:exit_cmd $rwin"
    bind Text	<Control-x>	"dataexp:exit_cmd $rwin"

    return $menu_name
}

proc dataexp:GUI:make_console_window {rwin w} {
    global dataexp
    label $w.label -text "Console:: "
    entry $w.entry -relief sunken
    bind $w.entry <Return> {dataexp:exec_tcl_command %W}
    pack $w.label -side left -anchor w -expand 0 
    pack $w.entry -side left -anchor w -expand 1 -fill x
    return $w
}

proc dataexp:GUI:axis_choices {rwin w} {
    global dataexp
    set name [tixOptionName $w]
    option add *$name*TixOptionMenu*label.anchor e

    tixOptionMenu $w.xmenu -label "X axis: "  \
	-disablecallback true -command [list dataexp:choose_axis $rwin col_x]

    tixOptionMenu $w.ymenu -label "Y axis: " \
	-disablecallback true -command [list dataexp:choose_axis $rwin col_y]

    foreach menu "xmenu ymenu" {
	set cnt 1
        foreach axis "X Y Z X' Y' Z'" {
	    $w.${menu} add command $cnt -label "$axis  "
	    incr cnt
	}
    }

    $w.xmenu config -value $dataexp($rwin,col_x)
    $w.ymenu config -value $dataexp($rwin,col_y)
    $w.xmenu config -disablecallback false
    $w.ymenu config -disablecallback false

    pack $w.xmenu -padx 5 -pady 3 -fill y -side top
    pack $w.ymenu -padx 5 -pady 3 -fill y -side top

    button $w.apply -text "Apply" -command "dataexp:graph:plot $rwin"
    pack $w.apply -padx 5 -pady 3 -fill x -side bottom
}

proc dataexp:GUI:ray_choices {rwin w} {
    global dataexp
    set name [tixOptionName $w]
    option add *$name*TixSelect*label.anchor c
    option add *$name*TixSelect*orientation vertical
    option add *$name*TixSelect*labelSide top

    tixSelect $w.rays -label "" -radio true \
	-disablecallback true -command [list dataexp:choose_rays $rwin]

    $w.rays add good -text Good
    $w.rays add lost -text Lost
    $w.rays add all  -text All

    $w.rays config -value $dataexp($rwin,rays)
    $w.rays config -disablecallback false

    set dataexp($rwin,ray_choices_cmd) "$w.rays config -value"

    pack $w.rays -side left -padx 5 -pady 3 -fill x
}

proc dataexp:GUI:plot_choices {rwin w} {
    global dataexp
    set name [tixOptionName $w]
    option add *$name*TixSelect*label.anchor c
    option add *$name*TixSelect*orientation vertical
    option add *$name*TixSelect*labelSide top

    tixSelect $w.plots -label "" -allowzero true -radio false \
	-disablecallback true -command [list dataexp:choose_plots $rwin]

    $w.plots add scatter -text "Scatter Plot"
    $w.plots add histo_t -text "Top Histogram"
    $w.plots add histo_s -text "Side Histogram"
    $w.plots add info    -text "Image Info"

    set plots ""
    foreach plot "scatter histo_t histo_s info" {
	if $dataexp($rwin,plot_$plot) {lappend plots $plot}
    }
    $w.plots config -value $plots
    $w.plots config -disablecallback false

    set dataexp($rwin,plot_choices_cmd) "$w.plots config -value"

    pack $w.plots -side left -padx 5 -pady 3 -fill x
}

proc dataexp:GUI:scale_choices {rwin w} {
    global dataexp
    set name [tixOptionName $w]
    option add *$name*TixSelect*label.anchor c
    option add *$name*TixSelect*orientation vertical
    option add *$name*TixSelect*labelSide top

    tixSelect $w.scale -label "" -radio true \
	-disablecallback true -command [list dataexp:choose_scale $rwin]

    $w.scale add auto  -text "Automatic"
    $w.scale add cart  -text "Cartesian"
    $w.scale add fill  -text "Fill"
    $w.scale add user  -text "User-defined" -state disabled

    $w.scale config -value $dataexp($rwin,scale)
    $w.scale config -disablecallback false

    set dataexp($rwin,scale_choices_cmd) "$w.scale config -value"

    pack $w.scale -side left -padx 5 -pady 3 -fill x
}

proc dataexp:GUI:plotopts {rwin w} {

    tixLabelFrame $w.axis  -label "Columns"
    tixLabelFrame $w.rays  -label "Rays"
    tixLabelFrame $w.plots -label "Plots"
    tixLabelFrame $w.scale -label "Scaling"

    dataexp:GUI:axis_choices  $rwin [$w.axis subwidget frame]
    dataexp:GUI:ray_choices   $rwin [$w.rays subwidget frame]
    dataexp:GUI:plot_choices  $rwin [$w.plots subwidget frame]
    dataexp:GUI:scale_choices $rwin [$w.scale subwidget frame]

    #pack $w.axis  -side top -padx 5 -pady 3 -fill x
    #pack $w.rays  -side top -padx 5 -pady 3 -fill x
    #pack $w.plots -side top -padx 5 -pady 3 -fill x
    #pack $w.scale -side top -padx 5 -pady 3 -fill x

    #grid columnconfig $w 0 -weight 1 -minsize 0
    #grid rowconfig $w 0 -weight 1 -minsize 0

    grid $w.axis -row 0 -column 0 -columnspan 1 -rowspan 1 -sticky news
    grid $w.rays -row 1 -column 0 -columnspan 1 -rowspan 1 -sticky news
    grid $w.plots -row 2 -column 0 -columnspan 1 -rowspan 1 -sticky news
    grid $w.scale -row 3 -column 0 -columnspan 1 -rowspan 1 -sticky news
}

#
# The BLT graphs are placed into a canvas (so we can print multiple plots),
# and this canvas is then placed inside of tixScrolledWindow.
#
proc dataexp:GUI:old_plotbody {w} {
    global dataexp dataexp_prefs

    set scrolled [tixScrolledWindow ${w}.scrolled \
        -width $dataexp(plot_body_width) \
	-height $dataexp(plot_body_height) \
	-relief sunken -bd 2 \
	-expand 1]

    set wparent [$scrolled subwidget window]
    set dataexp(plot_master_w) [canvas ${wparent}.c \
        -width $dataexp(plot_body_width) -height $dataexp(plot_body_height)]

    pack $dataexp(plot_master_w)
    pack $scrolled
}

proc dataexp:GUI:plotbody {rwin w} {
    global dataexp dataexp_prefs

    scrollbar ${w}.hscroll -orient horizontal \
        -command "${w}.c xview"

    scrollbar ${w}.vscroll -orient vertical \
        -command "${w}.c yview"

    canvas ${w}.c \
        -xscrollcommand "${w}.hscroll set" \
        -yscrollcommand "${w}.vscroll set" \
        -width $dataexp(plot_body_width) \
	-height $dataexp(plot_body_height) \
        -scrollregion [list \
	    0 0 $dataexp(plot_body_width) $dataexp(plot_body_height)]
    
    set dataexp($rwin,plot_master_w) ${w}.c
    
    grid columnconfig $w 0 -weight 1 -minsize 0
    grid rowconfig $w 0 -weight 1 -minsize 0
    grid ${w}.c -column 0 -row 0 \
        -rowspan 1 -columnspan 1 -sticky news
    grid ${w}.vscroll -column 1 -row 0 \
        -rowspan 1 -columnspan 1 -sticky news
    grid ${w}.hscroll -column 0 -row 1 \
        -rowspan 1 -columnspan 1 -sticky news
}

proc dataexp:GUI:make {rwin} {
    global dataexp

    wm title $rwin $dataexp($rwin,win_title)
    wm protocol $rwin WM_SAVE_YOURSELF "dataexp:exit_cmd $rwin"
    wm protocol $rwin WM_DELETE_YOURSELF "dataexp:exit_cmd $rwin"

    set topmenu    [frame ${rwin}.topmenu -relief raised -bd 1]
    set consle_w_stub [frame ${rwin}.consle_w_stub]
    set body       [frame ${rwin}.body]
    set plotopts   [frame ${body}.plotopts -relief sunken -bd 1]
    set plotbody   [frame ${body}.plotbody -relief sunken -bd 1]

    set dataexp($rwin,consle_w_stub) $consle_w_stub
    set dataexp($rwin,consle_w) \
	[dataexp:GUI:make_console_window $rwin [frame ${rwin}.consle_w -bd 2]]

    dataexp:GUI:topmenu $rwin $topmenu
    dataexp:GUI:plotopts $rwin $plotopts
    dataexp:GUI:plotbody $rwin $plotbody

    grid $plotopts -row 0 -column 0 -sticky nw
    grid $plotbody -row 0 -column 1 -sticky news
    grid columnconfigure $body 1 -weight 1
    grid rowconfigure $body 0 -weight 1

    pack $topmenu -side top -fill x ;# -expand 1
    pack $consle_w_stub -side top -fill x ;# -expand 1
    pack $body -side top -expand 1 -fill both

    lappend dataexp(toplevels) $rwin

    dataexp:show_console_cmd
    update
}

################################ Misc #####################################

proc dataexp:misc:add_file_to_title {rwin file} {
    global dataexp
    if {$file == ""} {
	set filepart "\[No dataset loaded\]"
    } else {
	set filepart "\[$file\]"
    }
    wm title $rwin "$dataexp($rwin,win_title)   $filepart"
}

################################ Main #####################################

#
# parse the command line and initialize the interface etc
#
proc dataexp:main {{rwin .}} {
    global dataexp
    if [string compare $rwin "."] {		;# need toplevel
	toplevel $rwin -class ExportData
    }

    dataexp:init:env $rwin
    dataexp:init:globals $rwin
    dataexp:parse_args $rwin
    dataexp:init:preferences $rwin
    dataexp:init:fonts $rwin
    dataexp:GUI:make $rwin
    dataexp:graph:make $rwin
    dataexp:init:startup $rwin
    set dataexp(initialized) 1
}

######################## Start program ####################################
#

#
# DO NOT call dataexp:main if running under SHADOW GUI!
#
if ![info exists gvars] {
    dataexp:main
}
