
proc APSButtonHelp {} {
    return "Usage: APSButton widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-text <string>\]\t\n\[-textvariable <variable>\]]\t\n\[-font <string>\]\t\n\[-command <string>\]\t\n\[-highlight 1\]\t\n\[-size <string>\] where <string> is small or medium (default)\n\[-contextHelp <string>\]\t\n\n\[-contextHelpImage <filename>\]\t\n\[-highlightColor <color>\]\t\n\nCreates\t\$parent\$widget.\n\tbutton"
}

proc APSButton {widget args} {
    global apsContextHelp apsContextHelpImage tcl_platform apsttk
    set parent ""
    set noPack 0
    set packOption "-side left -padx 1 -pady 1"
    set text "notext"
    set textvariable ""
    set command ""
    set highlight 0
    set highlightColor black
    set size medium
    set contextHelp ""
    set contextHelpImage ""
    set fastClick 0
    set gridPack ""
    set application ""
    set logcomm 0
    set width 0
    set font ""
    #width of "" is the default for ttk.
    #This creates wider buttons if you have short labels. 
    #Also I coded it to have the use the default ttk border widths if you
    #set width to ""
    APSStrictParseArguments {parent noPack packOption text textvariable command highlight font \
                               size contextHelp contextHelpImage highlightColor fastClick gridPack application logcomm width}
    set borderwidth 2
    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
        set ttk 1
        if {($width == "") || ($packOption == "-side left -pady 1")} {
            if {$packOption == "-side left -padx 1 -pady 1"} {
                set packOption "-side left -pady 1"
            }
            set borderwidth ""
        }
    } else {
        set ttkPrefix ""
        set ttk 0
    }

    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }

    if {$parent == ""} {
        if {$highlight} {
            toplevel $widget -bd $borderwidth -bg $highlightColor
        } else {
            toplevel $widget -bd $borderwidth
        }
        wm title $widget $text
    } else {
        if {$highlight} {
            if {$ttk} {
                ttk::style configure ${highlightColor}Background.TFrame -background $highlightColor
                ttk::frame $parent$widget -borderwidth $borderwidth -style ${highlightColor}Background.TFrame
            } else {
                frame $parent$widget -borderwidth 2 -background $highlightColor
            }
        } else {
            ${ttkPrefix}frame $parent$widget -borderwidth $borderwidth
        }
        if {!$noPack} {
            if {[string length $gridPack]} {
                eval grid $parent$widget $gridPack
            } else {
                eval pack $parent$widget $packOption
            }
        }
    }
    if {$size == "small"} {
        if {$ttk} {
            if {[lsearch -exact [font names] smallFont] == -1} {
                eval font create smallFont [font actual TkDefaultFont]
                set fontsize [font configure TkDefaultFont -size]
                if {$fontsize < 0} {
                    incr fontsize 2
                } else {
                    incr fontsize -2
                }
                font configure smallFont -size $fontsize
            }
            ttk::style configure Small.TButton -padding 2 -shiftrelief 0 -focusthickness 0 -width $width -font smallFont
            if {$textvariable == ""} {
                ttk::button $parent$widget.button -text $text -style Small.TButton -command $command
            } else {
                ttk::button $parent$widget.button -textvariable $textvariable -style Small.TButton -command $command
            }
        } else {
            if {$tcl_platform(os) == "Darwin"} {
                if {$textvariable == ""} {
                    button $parent$widget.button -text $text -command $command \
                      -highlightthickness 0 -padx 8 -pady 1 -font \
                      -adobe-courier-medium-r-normal-*-10-*-*-*-*-*-*-*
                } else {
                    button $parent$widget.button -textvariable $textvariable -command $command \
                      -highlightthickness 0 -padx 8 -pady 1 -font \
                      -adobe-courier-medium-r-normal-*-10-*-*-*-*-*-*-*
                }
            } else {
               if {$textvariable == ""} {
                   button $parent$widget.button -text $text -command $command \
                     -highlightthickness 0 -padx 3 -pady 1 -font \
                     -adobe-courier-medium-r-normal-*-10-*-*-*-*-*-*-*
               } else {
                   button $parent$widget.button -textvariable $textvariable -command $command \
                     -highlightthickness 0 -padx 3 -pady 1 -font \
                     -adobe-courier-medium-r-normal-*-10-*-*-*-*-*-*-*
               }
            }
	}
    } else {
        if {$ttk} {
            if {$textvariable == ""} {
                ttk::button $parent$widget.button -text $text -command $command -width $width
            } else {
                ttk::button $parent$widget.button -textvariable $textvariable -command $command -width $width
            }
        } else {
            if {$tcl_platform(os) == "Darwin"} {
                if {$textvariable == ""} {
                    button $parent$widget.button -text $text -command $command \
                      -highlightthickness 0 -pady 3
                } else {
                    button $parent$widget.button -textvariable $textvariable -command $command \
                      -highlightthickness 0 -pady 3
                }
            } else {
                if {$textvariable == ""} {
                    button $parent$widget.button -text $text -command $command \
                      -highlightthickness 0 -padx 6 -pady 3
                } else {
                    button $parent$widget.button -textvariable $textvariable -command $command \
                      -highlightthickness 0 -padx 6 -pady 3
                }
            }
        }
    }
    if {!$fastClick} {
        bind $parent$widget.button <Double-Button-1> break
    }
    if [string length $font] {
	$parent$widget.button configure -font $font
    }
    pack $parent$widget.button -side top -fill x
    if $logcomm {
        global apsScriptCommand
        if ![string length $application] {
            set application $apsScriptCommand
        }
        set logCommand "APSLogButtonCommand -button $text -command \"$command\" -application $application"
        bind $parent$widget.button <Button-1> $logCommand
    }
}

proc APSLogButtonCommand {args} {
    set button ""
    set command ""
    set application ""
    set parameters ""
    APSStrictParseArguments {button command application parameters}
    
    global env
    set timeStamp [clock format [clock seconds] -format %H:%M:%S]
    set dir [APSGoToDailyDirectory]
    set logFile $dir/APSButtonCommand.log
    if ![file exist $logFile] {
        set fid [open $logFile "w"]
        puts $fid "SDDS1"
        puts $fid "&column name=TimeStamp type=string &end"
        puts $fid "&column name=ButtonName type=string &end"
        puts $fid "&column name=Application type=string &end"
        puts $fid "&column name=Command type=string &end"
        puts $fid "&column name=Arguments type=string &end"
        puts $fid "&data mode=ascii no_row_counts=1 &end"
    } else {
        set fid [open $logFile "a+"]
    }
    puts $fid "$timeStamp $button  \"$application\" \"$command\" \"$parameters\""
    flush $fid
    close $fid
}

proc APSEnableButtonHelp {} {
    return "Usage: APSEnableButton widget \n\tSets button widget state to normal."
}
proc APSEnableButton {widget} {
    $widget configure -state normal
}

proc APSDisableButtonHelp {} {
    return "Usage: APSDisableButton widget \n\tSets button widget state to disabled."
}
proc APSDisableButton {widget} {
    $widget configure -state disabled
}

proc APSChangeButtonHighlightHelp {} {
    return "Usage: APSChangeButtonHighlight widget\n\t\[-highlight {0 | 1}\]\n\t\[-highlightColor <color>\]\n\tSets and unsets highlight state of a button."
}

proc APSChangeButtonHighlight {widget args} {
    set highlight 0
    set highlightColor black
    APSStrictParseArguments {highlight highlightColor}
    if {!$highlight} {
        set bgColor [$widget cget -bg]
    } else {
        set bgColor $highlightColor
    }
    [winfo parent $widget] configure -bg $bgColor
}

proc APSSecureButtonAlert {args} {
    set problem "permission"
    set command "Unknown"
    set text "Unknown"
    set allowedUsers ""
    APSParseArguments {problem command text allowedUsers}
    switch $problem {
        permission {
            global env
            APSAlertBox [APSUniqueName .uniqueNameError] -errorMessage "You do not have permission to run that application.  Send email to soliday to be put on the permission list.  Button was ${text}\nYour username is $env(USER) while the current list of allowed users is: $allowedUsers"
        }
        subnet {
            APSAlertBox [APSUniqueName .uniqueNameError] -errorMessage "You can't run this application on the workstation you are using. It is on the wrong subnet.  Button was $text."
        }
    }
}

proc APSSecureButton {widget args} {
    global env
    set allowedUsers ""
    set allowedSubnets ""
    APSParseArguments {allowedUsers allowedSubnets}
    set userList [split $allowedUsers]
    if {[llength $userList]!=0}  {
        if {[lsearch -exact $userList $env(USER)]==-1} {
            eval APSButton $widget $args \
              -command {"APSSecureButtonAlert -problem permission -allowedUsers \"${allowedUsers}\" $args"}
            return
        }
    }
    set subnetList [split $allowedSubnets]
    if {[llength $allowedSubnets]} {
        global tcl_platform
        if {$tcl_platform(os) == "SunOS"} {
            if {[catch {exec ifconfig -a | grep 164 | token -n=2 \
                          | editstring -stream -edit=3s/./bdD} subnet]} {
                return -code error "APSSecureButton: $subnet"
            }
        } else {
            if {[catch {exec ip addr show | fgrep "inet "} ipinfo]} { 
                return -code error "APSSecureButton: $ipinfo"
            }
            set ipinfo [split $ipinfo \n]
            set subnets ""
            foreach s $ipinfo {
                set subnet [join [lrange [split [lindex $s 1] .] 0 2] .]
                lappend subnets $subnet
            }
#            if {[catch {exec ip addr show | fgrep inet | fgrep eth | head -1 | editstring -stream -edit=2K | token -n=1 | editstring -stream -edit=3s/./bdD} subnet]} { 
#                return -code error "APSSecureButton: $subnet"
#            }
#            if {[catch {exec /sbin/ifconfig | fgrep "inet addr" | head -1 | editstring -stream -edit=Z: | token -n=1 | editstring -stream -edit=3s/./bdD} subnet]} { 
#                return -code error "APSSecureButton: $subnet"
#            }
        }
        set found 0
        foreach subnet $subnets {
            if {[lsearch -exact $subnetList $subnet] != -1} {
                set found 1
                break
            }
        }
        if {!$found} {
            eval APSButton $widget $args \
              -command {"APSSecureButtonAlert -problem subnet $args"}
            return
        }
    }
    eval APSButton $widget $args
}

proc APSLabeledEntryHelp {} {
    return "\
Usage: APSLabeledEntry widget 
\[-parent <string>\]\t
\[-noPack 1\]\t
\[-packOption <list>\]\t
\[-gridPack <list>\]\t
\[-label <string>\]\t
\[-textVariable <string>\]\t
\[-width <string>\]\t
\[-contextHelp <string>\]\t
\[-contextHelpImage <filename>\]\t
\[-editButton 0\]\t
\[-editTextWidth <value>\]\t
\[-numberButtons 1\]\t
\[-commandButton 1\]\t
\[-enableVariable <string>\]\t
\[-type {integer|real|alpha}\]\t
\[-fileSelectButton 1\]\t
\[-fileSelectPattern <string>\]\t
\[-fileSelectDirectory 1\]\t
\[-fileSelectValidity 0\]\t
\[-buttonsOnLeft 1\]\t
Creates\t\$parent\$widget.
\tlabel
\tentry
\tfileSelectButton (optional)"
}
proc APSLabeledEntry {widget args} {
    global apsContextHelp apsContextHelpImage apsttk
    set parent ""
    set noPack 0
    set packOption "-side top -fill x"
    set label "NoLabel"
    set textVariable ""
    set width 20
    set contextHelp ""
    set contextHelpImage ""
    set editButton 0
    set editTextWidth 100
    set numberButtons 0
    set commandButton 0
    set buttonsOnLeft 0
    set fileSelectButton 0
    set fileSelectPattern *
    set fileSelectPath "[pwd]"
    set fileSelectDirectory 0
    set fileSelectValidity 1
    set fileSelectReverse 1
    set type ""
    set gridPack ""
    set enableVariable ""
    APSStrictParseArguments {parent noPack packOption label textVariable width \
                               contextHelp contextHelpImage numberButtons type gridPack fileSelectButton \
                               fileSelectPattern fileSelectPath fileSelectDirectory commandButton \
                               buttonsOnLeft enableVariable fileSelectValidity editButton fileSelectReverse}

    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
        set ttk 1
    } else {
        set ttkPrefix ""
        set ttk 0
    }
    if {$ttk} {
        if {[llength $textVariable]} {
            upvar \#0 $textVariable textVar
            if {![info exists textVar]} {
                set textVar ""
            }
        }
    }
    if {[string match "*-expand yes*" $packOption] || \
          [string match "*-expand true*" $packOption] || \
          [string match "*-expand 1*" $packOption] } {
        set expand 1
    } else {
        set expand 0
    }
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$parent == ""} {
        toplevel $widget -bd 1
        wm title $widget $label
    } else {
        ${ttkPrefix}frame $parent$widget -borderwidth 1
        if {!$noPack} {
            if {[string length $gridPack]} {
                eval grid $parent$widget $gridPack 
            } else {
                eval pack $parent$widget $packOption
                pack configure $parent$widget -expand false
            }
        }
    }
    ${ttkPrefix}label $parent$widget.label -text $label
    pack $parent$widget.label -side left -fill x
    if {($fileSelectButton) && ([llength $textVariable])} {
        APSButton .fileSelectButton -parent $parent$widget -text F -packOption "-side right" \
          -command "set apsTempVar \[APSFileSelectDialog [APSUniqueName .] -pattern $fileSelectPattern -path $fileSelectPath -reverseSort $fileSelectReverse -selectDir $fileSelectDirectory -checkValidity $fileSelectValidity \] ; if {\[string length \[set apsTempVar\]\]} \"set $textVariable \[set apsTempVar\]\"" \
          -size small
    }
    if {[string length $enableVariable]} {
        ${ttkPrefix}checkbutton $parent$widget.enable -variable $enableVariable -command \
          "APSEnableDisableWidget $parent$widget.entry -toggle 1"
        pack $parent$widget.enable -side right 
    }
    if {$editButton && ([llength $textVariable])} {
        APSButton .edit -parent $parent$widget -packOption "-side right" -size small \
            -text "Edit" -command "APSLargeStringEditor -textVariable $textVariable -noLineFeed 1 -width $editTextWidth"
    }
    if {($commandButton) && ([llength $textVariable])} {
        APSCommandButton .arrow \
          -parent $parent${widget} \
          -textVariable $textVariable \
          -packOption "-side right" \
          -fileSelectPattern $fileSelectPattern \
          -fileSelectDirectory $fileSelectDirectory \
          -fileSelectValidity $fileSelectValidity
    }
    
    if {$numberButtons} {
        ${ttkPrefix}frame $parent$widget.eframe
        pack $parent$widget.eframe -side right -fill x
        set w $parent$widget.eframe
        ${ttkPrefix}entry $parent$widget.entry -width $width \
          -textvariable $textVariable
        pack $parent$widget.entry -side right -fill x -in $parent$widget.eframe -expand $expand
        APSEntryIncrementButtons .eib -parent $w -variableList $textVariable
    } else {
        ${ttkPrefix}entry $parent$widget.entry -width $width \
          -textvariable $textVariable
        if {($buttonsOnLeft) && ([llength $textVariable]) && ($fileSelectButton)} {
            pack $parent$widget.entry -side right -fill x -expand $expand -before $parent$widget.fileSelectButton
        } elseif {($buttonsOnLeft) && ([llength $textVariable]) && ([string length $enableVariable])} {
            pack $parent$widget.entry -side right -fill x -expand $expand -before $parent$widget.enable
        } elseif {($buttonsOnLeft) && ([llength $textVariable]) && ($commandButton)} {
            pack $parent$widget.entry -side right -fill x -expand $expand -before $parent$widget.arrow
        } else {
            pack $parent$widget.entry -side right -fill x -expand $expand
        }
    }
    if {[llength $textVariable]} {
        APSEntryInfoBalloon_for $parent$widget.entry $textVariable
    }
    if {([llength $type]) && ([llength $textVariable])} {
        set index [string first "\(" $textVariable]
        if {([string index $textVariable [expr {[string length $textVariable] - 1}]] == "\)") && ($index > 0)} {
            global [string range $textVariable 0 [expr {$index - 1}]]
            global [string range $textVariable 0 [expr {$index - 1}]]_old
            set textVariableOld [string range $textVariable 0 [expr {$index - 1}]]_old[string range $textVariable $index end]
        } else {
            global $textVariable ${textVariable}_old
            set textVariableOld ${textVariable}_old
        }
        if {![info exists $textVariable]} { set $textVariable "" }
        if {![info exists $textVariableOld]} { set $textVariableOld [set $textVariable] }
        trace variable $textVariable w "APSForceType $type"
    }
    if {[string length $enableVariable]} {
        APSEnableDisableWidget $parent$widget.entry -enable [uplevel \#0 set $enableVariable]
    }
}

proc APSCommandButtonHelp {} {
    return "\
Usage: APSCommandButton widget
\[-parent <string>\]\t
\[-noPack 1\]\t
\[-packOption <list>\]\t
\[-gridPack <list>\]\t
\[-textVariable <string>\]\t
\[-fileSelect <1|0>\]\t
\[-selectRecent <1|0>\]\t
\[-fileSelectPattern <string>\]\t
\[-fileSelectDirectory <1|0>\]\t

Creates\t\$parent\$widget.
\tarrow
"
}

proc APSCommandButton {widget args} {
    global apsContextHelp apsContextHelpImage
    set parent ""
    set noPack 0
    set packOption "-side top"
    set contextHelp ""
    set contextHelpImage ""
    set gridPack ""
    set textVariable ""
    set fileSelectPattern *
    set fileSelectDirectory 0
    set fileSelect 1
    set fileSelectValidity 1
    set selectRecent 1
    APSStrictParseArguments {parent noPack packOption contextHelp contextHelpImage gridPack textVariable fileSelectPattern fileSelectDirectory fileSelect selectRecent fileSelectValidity}
    if {$textVariable == ""} {
        APSAlertBox .alert -errorMessage "APSCommandButton textVariable is an empty string" -type error
        return
    }
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$parent == ""} {
        toplevel $widget -bd 1
        wm title $widget ""
    } else {
        frame $parent$widget -bd 1
        if {!$noPack} {
            if {[string length $gridPack]} {
                eval grid $parent$widget $gridPack 
            } else {
                eval pack $parent$widget $packOption
                pack configure $parent$widget -expand false
            }
        }
    }
    if {[lsearch -exact [image names] "oag_downarrow"] == -1} {
        image create bitmap oag_downarrow -data {
            #define down_width 11
            #define down_height 11
            static unsigned char down_bits[] = {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 
                0xfe, 0x03, 0xfc, 0x01, 0xf8, 0x00, 0x70, 0x00, 
                0x20, 0x00, 0x00, 0x00, 0x00, 0x00
            };
        }
    }
    menubutton $parent${widget}.arrow \
      -indicatoron 0 \
      -image oag_downarrow \
      -menu $parent${widget}.arrow.m \
      -state normal \
      -takefocus 1 \
      -highlightthickness 2 \
      -relief raised \
      -bd 2
    menu $parent${widget}.arrow.m -tearoff 0
    pack $parent${widget}.arrow
    bind $parent${widget}.arrow <ButtonPress-1> "APSCommandButtonConfigure -W %W -commandButtonVar \"$textVariable\" -fileSelectPattern \"$fileSelectPattern\" -fileSelectDirectory \"$fileSelectDirectory\" -fileSelect $fileSelect -selectRecent $selectRecent -fileSelectValidity $fileSelectValidity"
}

proc APSCommandButtonConfigure {args} {
    APSStrictParseArguments {W commandButtonVar fileSelectPattern fileSelectDirectory fileSelect selectRecent fileSelectValidity}

    $W.m delete 0 end

    set j [string first "(" $commandButtonVar]
    if {$j == -1} {
        global $commandButtonVar
    } else {
        global [string range $commandButtonVar 0 [expr ($j - 1)]]
    }
    if {$fileSelect} {
        $W.m add command \
          -label "File Select..." \
          -command "set apsTempVar \[APSFileSelectDialog [APSUniqueName .] -pattern $fileSelectPattern -selectDir $fileSelectDirectory -checkValidity $fileSelectValidity \] ; if {\[string length \[set apsTempVar\]\]} \"set $commandButtonVar \[set apsTempVar\]\""
    }
    if {$selectRecent} {
        $W.m add command \
          -label "Select Recent..." \
          -command "set apsTempVar \[APSRecentFileSelectDialog [APSUniqueName .] \] ; if {\[string length \[set apsTempVar\]\]} \"set $commandButtonVar \[set apsTempVar\]\""
    }
    if {($fileSelect) || ($selectRecent)} {
        $W.m add separator
    }
    foreach program { "emacs" \
		       sddsedit \
		       "quickSDDSDataManip -filename " \
                       "quickSDDSDSP -filename " \
                       "quickSDDSFit -filename " \
                       "quickSDDSMath -filename " \
                       "quickSDDSplot -dataFileList " \
                       "quickSDDSStatistics -filename " \
                       "sddsExportData -dataFileList " \
                       "dtpad" "sddsquery" "sdds2stream -rows"} {
        $W.m add command \
          -label "$program [set $commandButtonVar]" \
          -command "APSCommandButtonExecute -command \"$program [set $commandButtonVar]\""
    }
    $W.m add command \
      -label "Custom command..." \
      -command "APSCommandButtonExecute -command \"Custom [set $commandButtonVar]\""

}

proc APSCommandButtonExecute {args} {
    set command ""
    APSStrictParseArguments {command}
    set executable [lindex $command 0]
    if {[winfo exists .commandButtonExecLog]} {
        update
        destroy .commandButtonExecLog
    }
    if {$executable == "Custom"} {
        global apsCommandButtonCustomCommand
        set apsCommandButtonCustomCommand " [lrange $command 1 end]"
        if {[winfo exists .commandButtonCustomCommandDialog]} {
            update
            destroy .commandButtonCustomCommandDialog
        }
        APSDialogBox .commandButtonCustomCommandDialog \
          -name "Entry Box Manipulator" \
          -okCommand {APSCommandButtonExecute -command $apsCommandButtonCustomCommand}
        APSLabeledEntry .entry \
          -parent .commandButtonCustomCommandDialog.userFrame \
          -label "Command:" \
          -width 80 \
          -textVariable apsCommandButtonCustomCommand
        return
    }
    if {($executable == "sddsedit") || \
          ($executable == "quickSDDSDataManip") || \
          ($executable == "quickSDDSDSP") || \
          ($executable == "quickSDDSFit") || \
          ($executable == "quickSDDSMath") || \
          ($executable == "quickSDDSplot") || \
          ($executable == "quickSDDSStatistics") || \
          ($executable == "sddsExportData") || \
          ($executable == "xemacs") || \
          ($executable == "dtpad")} {
        if {[catch {APSExec -unixCommand $command} results]} {
            APSSetVarAndUpdate status "Error: $results"
        }
    } else {
        if {[catch {APSExecLog .commandButtonExecLog -width 100 -unixCommand $command} results]} {
            APSSetVarAndUpdate status "Error: $results"
        }
    }
}

proc APSForceType {type name el op} {
    global $name ${name}_old
    if {[string comp {} $el]} {
	set old  ${name}_old\($el\)
	set name $name\($el\)
    } else { set old ${name}_old }
    case $type {
        integer {
	    set expression ![regexp {^[-+]?[0-9]*$} [set $name]]
        } real {
	    set expression ![regexp {^[-+]?[0-9]*\.?[0-9]*([0-9]\.?e[-+]?[0-9]*)?$} [set $name]]
        } alpha {
	    set expression ![regexp {^[a-zA-Z]*$} [set $name]]
        }
    }
    if $expression {
	set $name [set $old]
	bell; return
    }
    set $old [set $name]
}

proc APSEntryIncrementButtonsHelp {} {
    return "Usage: APSEntryIncrementButtons widget \n\[-parent <string>\]\t\n\[-variableList <list>\]\t\n\[-description <string>\]\t\n\[-label <string>\]\t\n\[-gridPack <list>\]\n"
}

proc APSEntryIncrementButtons {widget args} {
    set parent ""
    set variableList ""
    set description "above variables"
    set label ""
    set gridPack ""
    APSStrictParseArguments {parent variableList label description gridPack} 

    APSFrame $widget -parent $parent -label $label \
	-relief flat -gridPack $gridPack
    set w $parent$widget.frame

    set incrementVariable apsEntryIncrement[APSUniqueNumber]
    global $incrementVariable
    set $incrementVariable 1
    
    APSButton .pb -parent $w -text + -size small -command \
      "APSIncrementEntryVariable -variableList [list $variableList] -direction up -incrementVariable $incrementVariable" \
      -contextHelp "Increments the entry value for $description."
    APSButton .mb -parent $w -text - -size small -command \
      "APSIncrementEntryVariable -variableList [list $variableList] -direction down -incrementVariable $incrementVariable" \
      -contextHelp "Decrements the entry value for $description."
    APSFrame .incr -parent $w -label ""
    set w $w.incr.frame
    APSLabeledEntry .incr -parent $w -width 4 \
	-textVariable $incrementVariable -label "" \
	-packOption "-side left" -label Incr: -type real \
	-contextHelp "Increment for changing $description."
    APSButton .mib -parent $w -text "*10" -size small -command \
      "APSMultiplyEntryVariable -variableList $incrementVariable -factor 10" \
      -contextHelp "Multiplies the increment value for $description by 10."
    APSButton .dib -parent $w -text "/10" -size small -command \
      "APSMultiplyEntryVariable -variableList $incrementVariable -factor [expr 0.1]" \
      -contextHelp "Divides the entry value for $description by 10."

}

proc APSIncrementEntryVariable {args} {
    set direction up
    set variableList ""
    set incrementVariable ""
    APSStrictParseArguments {direction variableList incrementVariable}

    set factor [expr {[string compare $direction up]?-1:1}]
    eval global $incrementVariable $variableList
    foreach variable $variableList {
        set $variable [expr {[subst \$$variable]+[subst \$$incrementVariable]*$factor}]
    }
}

proc APSEntryMultiplicationButtonsHelp {} {
    return "Usage: APSEntryMultiplicationButtons widget \n\[-parent <string>\]\t\n\[-variableList <list>\]\t\n\[-description <string>\]\t\n\[-label <string>\]\t\n\[-factorList <list>\]\t\n\[-gridPack <list>\]\n"
}

proc APSEntryMultiplicationButtons {widget args} {
    set parent ""
    set variableList ""
    set description ""
    set label ""
    set factorList {2 5 10} 
    set gridPack ""
    APSStrictParseArguments {parent variableList label description factorList gridPack} 

    APSFrame $widget -parent $parent -label $label -gridPack $gridPack 
    set w $parent$widget.frame

    set index 0
    foreach factor $factorList {
        APSButton .pb$index -parent $w -text "*$factor" -size small -command \
          "APSMultiplyEntryVariable -variableList [list $variableList] -factor $factor" \
          -contextHelp "Multiplies the entry value for $description by $factor."
        APSButton .mb$index -parent $w -text "/$factor" -size small -command \
          "APSMultiplyEntryVariable -variableList [list $variableList] -factor [expr 1./$factor]" \
          -contextHelp "Divides the entry value for $description by $factor."
        incr index
    }
}

proc APSMultiplyEntryVariable {args} {
    set variableList ""
    set factor 1
    APSStrictParseArguments {variableList factor}
    foreach variable $variableList {
        global $variable
        set value [expr {[subst \$$variable]*$factor}]
        if {[expr {$value-int($value)}]==0} {
            set value [expr {int($value)}]
        }
        set $variable $value
    }
}

proc APSLabeledEntryFrameHelp {} {
    return "Usage: APSLabeledEntryFrame widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-label <string>\]\t\n\[-variableList <list>\]\t\n\[-width <string>\]\t\n\[-orientation <string>\] where <string> is horizontal or vertical (default)\n\[-contextHelp <string>\]\n\[-contextHelpImage <filename>\]\t\n\[-type \{integer|real|alpha\}\]\t\n\nCreates\t\$parent\$widget.\n\tlabel\n\tframe.entry1\n\tframe.entry2,...,frame.entry<n>\n"
}
proc APSLabeledEntryFrame {widget args} {
    global apsContextHelp apsContextHelpImage apsttk
    set parent ""
    set noPack 0
    set packOption "-side top -fill x -expand 1"
    set label ""
    set variableList ""
    set width 20
    set orientation vertical
    set contextHelp ""
    set contextHelpImage ""
    set type ""
    set gridPack ""
    set bg ""
    set fg ""
    set labelColor ""
    set font ""
    APSStrictParseArguments {parent noPack packOption label variableList bg labelColor fg font \
                               width orientation contextHelp contextHelpImage type gridPack}

    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
    } else {
        set ttkPrefix ""
    }
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$orientation == "vertical"} {
        set packside top
        set packside1 top
    } else {
        set packside right
        set packside1 left
    }
    
    if {$parent == ""} {
        toplevel $widget -bd 1
        wm title $widget $label
    } else {
        ${ttkPrefix}frame $parent$widget -borderwidth 1
        if {!$noPack} {
            if {[string length $gridPack]} {
                eval grid $parent$widget $gridPack 
            } else {
                eval pack $parent$widget $packOption
                pack configure $parent$widget -expand false
            }
        }
    }
    if [string length $labelColor] {
        ${ttkPrefix}label $parent$widget.label -text $label -fg $labelColor
    } else {
        ${ttkPrefix}label $parent$widget.label -text $label
    }
    pack $parent$widget.label -side $packside1 -fill x
    if [string length $bg] {
         ${ttkPrefix}frame $parent$widget.frame -relief flat -borderwidth 2 -bg $bg    
    } else {
        ${ttkPrefix}frame $parent$widget.frame -relief flat -borderwidth 2
    }
    pack $parent$widget.frame -fill both -side $packside
 
    set len [llength $variableList]
    for {set i $len} {$i>0} {incr i -1} {
        set var [lindex $variableList [expr $i -1]]
        if {[string length $fg] && [string length $font]} {
            ${ttkPrefix}entry $parent$widget.frame.entry$i -width $width -textvariable $var -fg $fg -font $font
        } elseif [string length $font] {
            ${ttkPrefix}entry $parent$widget.frame.entry$i -width $width -textvariable $var -font $font
        } elseif [string length $fg] {
            ${ttkPrefix}entry $parent$widget.frame.entry$i -width $width -textvariable $var -fg $fg
        } else {
            ${ttkPrefix}entry $parent$widget.frame.entry$i -width $width -textvariable $var
        }
        pack $parent$widget.frame.entry$i -side $packside
	if {[llength $var]} {
	    APSEntryInfoBalloon_for $parent$widget.frame.entry$i $var
	}
	if {([llength $type]) && ([llength $var])} {
	    set index [string first {(} $var]
		       if {([string index $var [expr {[string length $var] - 1}]] == {)}) && ($index > 0)} {
			   global [string range $var 0 [expr {$index - 1}]]
			   global [string range $var 0 [expr {$index - 1}]]_old
			   set varOld [string range $var 0 [expr {$index - 1}]]_old[string range $var $index end]
		       } else {
			   global $var ${var}_old
			   set varOld ${var}_old
		       }
	    if {![info exists $var]} { set $var "" }
	    if {![info exists $varOld]} { set $varOld [set $var] }
	    trace variable $var w "APSForceType $type"
	}
    }
}

proc APSLabeledOutputHelp {} {
    return "Usage: APSLabeledOutput widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-label <string>\]\t\n\[-textVariable <string>\\t\n\[-width <string>\]\t\n\[-backgroundcolor <color>\]\t\n\[-commandButton 1\]\t\n\[-contextHelp <string>\]\t\n\[-contextHelpImage <filename>\]\t\n\nCreates\t\$parent\$widget.\n\tlabel\n\tentry"
}

proc APSLabeledOutput {widget args} {
    global apsContextHelp apsContextHelpImage apsttk
    set parent ""
    set noPack 0
    set packOption "-side top -fill x"
    set label "NoLabel"
    set textVariable ""
    set width 20
    set contextHelp ""
    set contextHelpImage ""
    set gridPack ""
    set backgroundcolor ""
    set commandButton 0
    APSStrictParseArguments {parent noPack packOption label textVariable \
                               width contextHelp contextHelpImage gridPack backgroundcolor \
                               commandButton}
    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
        set ttk 1
    } else {
        set ttkPrefix ""
        set ttk 0
    }
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp    
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage    
    }
    if {$parent == ""} {
        toplevel $widget -bd 1
        wm title $widget $label
    } else {
        ${ttkPrefix}frame $parent$widget -borderwidth 1
        if {!$noPack} {
	    if {[string length $gridPack]} {
                eval grid $parent$widget $gridPack
            } else {
                eval pack $parent$widget $packOption
            }
        }
    }
    ${ttkPrefix}label $parent$widget.label -text $label
    pack $parent$widget.label -side left -fill x
    if {($commandButton) && ([llength $textVariable])} {
        APSCommandButton .arrow \
          -parent $parent${widget} \
          -textVariable $textVariable \
          -packOption "-side right" \
          -fileSelect 0 \
          -selectRecent 0
    }
    global tcl_version
    if {[string range $tcl_version 0 2] <= 8.3} {
	entry $parent$widget.entry -relief ridge -width $width \
	    -textvariable $textVariable -state disabled
	if {[llength $backgroundcolor]} {
	    $parent$widget.entry configure \
		-bg $backgroundcolor
	}
    } else {
	if {[llength $backgroundcolor]} {
            entry $parent$widget.entry -width $width \
	    -textvariable $textVariable -state readonly
	    $parent$widget.entry configure \
		-background $backgroundcolor \
		-readonlybackground $backgroundcolor
	} else {
            if {$ttk} {
                #This step of making the background grey is needed because 
                #OSX uses white for readonly by default
                ttk::style configure GreyReadonly.TEntry -fieldbackground white
                ttk::style map GreyReadonly.TEntry -fieldbackground [list readonly \#d9d9d9] -background [list readonly \#d9d9d9]
                ${ttkPrefix}entry $parent$widget.entry -width $width \
                  -textvariable $textVariable -state readonly -style GreyReadonly.TEntry
            } else {
                ${ttkPrefix}entry $parent$widget.entry -width $width \
                  -textvariable $textVariable -state readonly
            }
        }
    }
    pack $parent$widget.entry -side right -fill x
    if {[llength $textVariable]} {
	APSEntryInfoBalloon_for $parent$widget.entry $textVariable
    }
}

proc APSLabeledOutputFrameHelp {} {
    return "Usage: APSLabeledOutputFrame widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-label <string>\]\t\n\[-variableList <list>\]\t\n\[-width <string>\]\t\n\[-orientation <string>\] where <string> is horizontal or vertical (default)\n\[-contextHelp <string>\]\n\[-contextHelpImage <filename>\]\t\n\nCreates\t\$parent\$widget.\n\tlabel\n\tframe.entry1\n\tframe.entry2,...,frame.entry<n>\n"
}
proc APSLabeledOutputFrame {widget args} {
    global apsContextHelp apsContextHelpImage
    set parent ""
    set noPack 0
    set packOption "-side top -fill x"
    set label ""
    set variableList ""
    set width 20
    set orientation vertical
    set contextHelp ""
    set contextHelpImage ""
    set gridPack ""
    APSStrictParseArguments {parent noPack packOption label \
				 variableList width orientation \
				 contextHelp contextHelpImage gridPack}

    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$orientation == "vertical"} {
        set packside top
    } else {
        set packside left
    }
    APSFrame $widget -parent $parent -label $label -orientation $orientation \
      -packOption $packOption -noPack $noPack -gridPack $gridPack
    set i 1
    global tcl_version
    foreach var $variableList {
	if {[string range $tcl_version 0 2] <= 8.3} {
	    entry $parent$widget.frame.entry$i -relief ridge -width $width \
		-textvariable $var -state disabled
	} else {
	    entry $parent$widget.frame.entry$i -relief ridge -width $width \
		-textvariable $var -state readonly
	}
        pack $parent$widget.frame.entry$i -side $packside
	if {[llength $var]} {
	    APSEntryInfoBalloon_for $parent$widget.frame.entry$i $var
	}
        incr i
    }
}

proc APSControlRadioButtonFrameHelp {} {
    return "usage: APSControlRadioButtonFrame widget\n\[-state {0|1}\]\n"
}

proc APSControlRadioButtonFrame {widget args} {
    set state ?
    APSStrictParseArguments {state}
    if {[string compare $state ?]!=0} {
        if {$state} {
            set state normal
        } else {
            set state disabled
        }
        set button 1
        while 1 {
            if {[winfo exists $widget.frame.button$button]} {
                $widget.frame.button$button configure -state $state
                incr button
            } else {
                break
            }
        }
    }
}

proc APSRadioButtonFrameHelp {} {
    return "Usage: APSRadioButtonFrame widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-label <string>\]\t\n\[-limitPerRow <number>\]\t\n\[-variable <string>\]\t\n\[-buttonList <list>\]\t\n\[-valueList <list>\]\t\n\[-orientation <string>\] where <string> is horizontal or vertical\n\[-commandList <list>\]\t\n\[-contextHelp <string>\]\t\n\[-contextHelpImage <filename>\]\t\n\nCreates\t\$parent\$widget.\n\tlabel\n\tframe\n\tframe.button1\n\tframe.button2,...\n"
}

proc APSRadioButtonEntryFrame {widget args} {
    global apsContextHelp apsContextHelpImage apsttk
    set parent ""
    set noPack 0
    set packOption "-side top"
    set label "NoLabel"
    set labelFont ""
    set variable ""
    set buttonList ""
    set valueList ""
    set orientation vertical
    set commandList ""
    set contextHelp ""
    set contextHelpImage ""
    set relief ridge
    set limitPerRow 0
    set gridPack ""
    set entryWidth 5
    set entryVariableList ""
    APSStrictParseArguments {parent noPack packOption label variable \
                               buttonList valueList orientation contextHelp contextHelpImage \
                               commandList relief limitPerRow gridPack labelFont entryWidth entryVariableList}

    if {$commandList != "" &&
        [llength $buttonList] != [llength $commandList]} {
        APSAlertBox [APSUniqueName .uniqueNameError] -errorMessage "commandList must be same length as buttonList"
        return
    }    
    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
        set ttk 1
    } else {
        set ttkPrefix ""
        set ttk 0
    }
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp    
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$orientation == "vertical"} {
        set packside top
        set opackside left
        set oanchor n
        set packOption "$packOption -fill y"
	set packOption1 "-side top -fill y"
	set packOption2 "-side left -fill both"
    } else {
        set packside left
        set opackside top
        set oanchor w
        set packOption "$packOption -fill y"
	set packOption1 "-side left -fill x"
	set packOption2 "-side top -fill both"
    }

    APSFrame $widget -parent $parent -packOption $packOption -noPack $noPack\
      -label $label -labelFont $labelFont -orientation $orientation -relief $relief -gridPack $gridPack

    set valueIndex 0
    set buttonNumber 1
    set variableIndex 0
    set numberInRow $limitPerRow
    set row 0
    foreach button $buttonList {
        if {$limitPerRow && $numberInRow>=$limitPerRow} {
            set numberInRow 0
            APSFrame .frame$row -parent $parent$widget.frame -packOption $packOption2 
            set parent1 $parent$widget.frame.frame$row.frame
            $parent1 configure -bd 0
            set parent1 $parent$widget.frame.row$row
            incr row
        } elseif {!$limitPerRow} {
            set parent1 $parent$widget.frame
        }
        set cmd [lindex $commandList $valueIndex]
	APSFrame .f$buttonNumber -parent $parent1 -packOption $packOption1
	set parent2 $parent1.f$buttonNumber.frame
	$parent2 configure -bd 0
        if {$ttk} {
            ttk::radiobutton $parent2.button -text $button -variable $variable -value [lindex $valueList $valueIndex] -command $cmd
            pack $parent2.button  -fill x -side left -in $parent2
        } else {
            radiobutton $parent2.button -text $button -variable $variable -value [lindex $valueList $valueIndex] -anchor w -command $cmd
            pack $parent2.button  -fill x -side left -in $parent2
        }
	if [llength $entryVariableList] {
	    APSLabeledEntry .entry -parent $parent2 -label "" \
		-textVariable [lindex $entryVariableList $variableIndex] \
		-width $entryWidth -packOption "-side left"
	}
        incr valueIndex
        incr buttonNumber
	incr variableIndex
        incr numberInRow
    }
}


proc APSRadioButtonFrame {widget args} {
    global apsContextHelp apsContextHelpImage apsttk
    set parent ""
    set noPack 0
    set packOption "-side top"
    set label "NoLabel"
    set labelFont ""
    set variable ""
    set buttonList ""
    set valueList ""
    set orientation vertical
    set commandList ""
    set contextHelp ""
    set contextHelpImage ""
    set relief ridge
    set limitPerRow 0
    set gridPack ""
    APSStrictParseArguments {parent noPack packOption label variable \
                               buttonList valueList orientation contextHelp contextHelpImage \
                               commandList relief limitPerRow gridPack labelFont}

    if {$commandList != "" &&
        [llength $buttonList] != [llength $commandList]} {
        APSAlertBox [APSUniqueName .uniqueNameError] -errorMessage "commandList must be same length as buttonList"
        return
    }    
    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
        set ttk 1
    } else {
        set ttkPrefix ""
        set ttk 0
    }
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp    
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$orientation == "vertical"} {
        set packside top
        set opackside left
        set oanchor n
        set packOption "$packOption -fill y"
    } else {
        set packside left
        set opackside top
        set oanchor w
        set packOption "$packOption -fill x"
    }

    APSFrame $widget -parent $parent -packOption $packOption -noPack $noPack\
      -label $label -labelFont $labelFont -orientation $orientation -relief $relief -gridPack $gridPack

    set valueIndex 0
    set buttonNumber 1
    set numberInRow $limitPerRow
    set row 0
    foreach button $buttonList {
        if {$limitPerRow && $numberInRow>=$limitPerRow} {
            set numberInRow 0
            ${ttkPrefix}frame $parent$widget.frame.row$row 
            pack $parent$widget.frame.row$row -fill y -fill x -side $opackside \
              -anchor $oanchor
            set parent1 $parent$widget.frame.row$row
            incr row
        } elseif {!$limitPerRow} {
            set parent1 $parent$widget.frame
        }
        set cmd [lindex $commandList $valueIndex]
        if {$ttk} {
            ttk::radiobutton $parent$widget.frame.button$buttonNumber -text $button -variable $variable -value [lindex $valueList $valueIndex] -command $cmd
            pack $parent$widget.frame.button$buttonNumber -side $packside -fill x \
          -in $parent1 -padx 5
        } else {
            radiobutton $parent$widget.frame.button$buttonNumber -text $button -variable $variable -value [lindex $valueList $valueIndex] -anchor w -command $cmd
            pack $parent$widget.frame.button$buttonNumber -side $packside -fill x \
          -in $parent1
        }
        incr valueIndex
        incr buttonNumber
        incr numberInRow
    }
}

proc APSCheckButtonFrameHelp {} {
    return "Usage: APSCheckButtonFrame widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-label <string>\]\t\n\[-limitPerRow <number>\]\t\n\[-buttonList <list>\]\t\n\[-variableList <list>\]\t\n\[-commandList <list>\]\n\t\[-relief <string>\]\t\n\[-orientation <string>\] where <string> is horizontal or vertical\n\[-allNone 1\]\[-toggle 1\] adds All and None buttons\t\n\[-contextHelp <string>\]\t\n\[-contextHelpImage <filename>\]\t\n\nCreates\t\$parent\$widget.\n\tlabel\n\tframe\n\tframe.button1\n\tframe.button2,...\n"
}

proc APSCheckButtonFrame { widget args } {
    global apsContextHelp apsContextHelpImage apsttk
    set parent ""
    set noPack 0
    set packOption "-side top"
    set label "NoLabel"
    set buttonList ""
    set variableList ""
    set commandList ""
    set orientation vertical
    set allNone 0
    set toggle 0
    set contextHelp ""
    set contextHelpImage ""
    set relief ridge
    set limitPerRow 0
    set buttonNameList ""
    set gridPack ""
    APSStrictParseArguments {parent noPack packOption label buttonList  variableList orientation allNone commandList  contextHelp contextHelpImage relief limitPerRow gridPack toggle}

    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
        set ttk 1
    } else {
        set ttkPrefix ""
        set ttk 0
    }
    if {$commandList != "" &&
        [llength $buttonList] != [llength $commandList]} {
        APSAlertBox [APSUniqueName .uniqueNameError] -errorMessage "commandList must be same length as buttonList"
        return
    }
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp    
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$orientation == "vertical"} {
        set packside top
        set opackside left
        set oanchor n
        set packOption "$packOption -fill y"
    } else {
        set packside left
        set opackside top
        set oanchor w
        set packOption "$packOption -fill x"
    }
    APSFrame $widget -parent $parent -packOption $packOption -noPack $noPack -label $label -orientation $orientation -relief $relief -gridPack $gridPack
    
    set variableIndex 0
    set buttonNumber 1
    set numberInRow $limitPerRow
    set row 0
    foreach button $buttonList {
        if {$limitPerRow && $numberInRow>=$limitPerRow} {
            set numberInRow 0
            ${ttkPrefix}frame $parent$widget.frame.row$row 
            pack $parent$widget.frame.row$row -fill y -fill x -side $opackside  -anchor $oanchor
            set parent1 $parent$widget.frame.row$row
            incr row
        } elseif {!$limitPerRow} {
            set parent1 $parent$widget.frame
        }
        set cmd [lindex $commandList $variableIndex]
#        global [lindex $variableList $variableIndex]
#        puts "[lindex $variableList $variableIndex] [info exists [lindex $variableList $variableIndex]]"
        if {$ttk} {
            if {[llength [lindex $variableList $variableIndex]]} {
                upvar \#0 [lindex $variableList $variableIndex] textVar
                if {![info exists textVar]} {
                    set textVar 0
                }
            }
        }
        ${ttkPrefix}checkbutton $parent$widget.frame.button$buttonNumber -text $button  -variable [lindex $variableList $variableIndex] -command $cmd
        if {$ttk} {
            pack $parent$widget.frame.button$buttonNumber -side $packside -fill x  -in $parent1 -padx 5
        } else {
            pack $parent$widget.frame.button$buttonNumber -side $packside -fill x  -in $parent1
        }
	lappend buttonNameList $parent$widget.frame.button$buttonNumber
        incr variableIndex
        incr buttonNumber
        incr numberInRow
    }
    if {$allNone} {
        set setBody {
            global $var
	    if {[set $var] == 0} {
            	$buttonName invoke
	    }
        }
        set setCmd [list foreach var $variableList buttonName $buttonNameList $setBody]
        set clrBody {
            global $var
	    if {[set $var] != 0} {
            	$buttonName invoke
	    }
        }
        set clrCmd [list foreach var $variableList buttonName $buttonNameList $clrBody]
        APSButton .all -parent $parent$widget.frame -text All -size small  -command $setCmd -width ""
        APSButton .none -parent $parent$widget.frame -text None -size small  -command $clrCmd -width ""
    }
    if {$toggle} {
        set toggleBody {
            global $var 
            if {[set $var]==0} {
                $buttonName invoke
            } else {
                $buttonName deselect
            }
        }
        set toggleCmd [list foreach var $variableList buttonName $buttonNameList $toggleBody]
        APSButton .toggle -parent $parent$widget.frame -text Toggle -size small -command $toggleCmd -width ""
    }
    return $buttonNameList
}

proc APSCheckButtonEntryFrameHelp {} {
    return "Usage: APSCheckButtonFrame widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-label <string>\]\t\n\[-limitPerRow <number>\]\t\n\[-buttonList <list>\]\t\n\[-variableList <list>\]\t\n\[-commandList <list>\]\n\t\[-relief <string>\]\t\n\[-orientation <string>\]\n\t\[-entryVariableList <list of entry variables>\]\n\t\[-entryWidth <value>\] where <string> is horizontal or vertical\n\[-allNone 1\]\[-toggle 1\] adds All and None buttons\t\n\[-contextHelp <string>\]\t\n\[-contextHelpImage <filename>\]\t\n\nCreates\t\$parent\$widget.\n\tlabel\n\tframe\n\tframe.button1\n\tframe.button2,...\nIf entry variableList provided, an entry will be created for each button.\n"
}

proc APSCheckButtonEntryFrame { widget args } {
    global apsContextHelp apsContextHelpImage
    set parent ""
    set noPack 0
    set packOption "-side top"
    set label "NoLabel"
    set buttonList ""
    set variableList ""
    set commandList ""
    set orientation vertical
    set allNone 0
    set toggle 0
    set contextHelp ""
    set contextHelpImage ""
    set relief ridge
    set limitPerRow 0
    set buttonNameList ""
    set gridPack ""
    set entryVariableList ""
    set entryWidth 5
    set fgColor ""
    set labelFont ""
    APSStrictParseArguments {parent noPack packOption label buttonList  variableList orientation allNone commandList  contextHelp contextHelpImage relief limitPerRow gridPack toggle entryVariableList entryWidth fgColor labelFont}

    if {$commandList != "" &&
        [llength $buttonList] != [llength $commandList]} {
        APSAlertBox [APSUniqueName .uniqueNameError] -errorMessage "commandList must be same length as buttonList"
        return
    }
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp    
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$orientation == "vertical"} {
        set packside top
        set opackside left
        set oanchor n
        set packOption "$packOption -fill y"
        set packOption1 "-side top -fill y"
        set packOption2 "-side left -fill both"
    } else {
        set packside left
        set opackside top
        set oanchor w
        set packOption "$packOption -fill x"
        set packOption1 "-side left -fill x"
        set packOption2 "-side top -fill both"
    }
    APSFrame $widget -parent $parent -packOption $packOption -noPack $noPack -label $label -orientation $orientation -relief $relief -gridPack $gridPack
    
    set variableIndex 0
    set buttonNumber 1
    set numberInRow $limitPerRow
    set row 0
    
    foreach button $buttonList {
        if {$limitPerRow && $numberInRow>=$limitPerRow} {
            set numberInRow 0
            APSFrame .frame$row -parent $parent$widget.frame -packOption $packOption2 
            set parent1 $parent$widget.frame.frame$row.frame
            $parent1 configure -bd 0
            incr row
        } elseif {!$limitPerRow} {
            set parent1 $parent$widget.frame
        }
        set cmd [lindex $commandList $variableIndex]
        APSFrame .frame$buttonNumber -parent $parent1 -packOption $packOption1
        set parent2 $parent1.frame$buttonNumber.frame
        $parent2 configure -bd 0
	if {[string length $labelFont] && [string length $fgColor]} {
	     checkbutton $parent2.button -text $button  -variable [lindex $variableList $variableIndex] -anchor w \
		-command $cmd -font $labelFont -fg $fgColor
	} elseif [string length $labelFont] {
	    checkbutton $parent2.button -text $button  -variable [lindex $variableList $variableIndex] -anchor w \
		-command $cmd -font $labelFont 
	} elseif [string length $fgColor] {
	    checkbutton $parent2.button -text $button  -variable [lindex $variableList $variableIndex] -anchor w \
		-command $cmd -fg $fgColor
	} else {
	    checkbutton $parent2.button -text $button  -variable [lindex $variableList $variableIndex] -anchor w \
		-command $cmd
	}
        pack $parent2.button -side left -fill x  -in $parent2
        if [llength $entryVariableList] {
            APSLabeledEntry .entry -parent $parent2 -label "" -textVariable \
                [lindex $entryVariableList $variableIndex] -width $entryWidth -packOption "-side left"
        }
        lappend buttonNameList $parent2.button
        incr variableIndex
        incr buttonNumber
        incr numberInRow
    }
    if {$allNone} {
        set setBody {
            global $var
	    if {[set $var] == 0} {
            	$buttonName invoke
	    }
        }
        set setCmd [list foreach var $variableList buttonName $buttonNameList $setBody]
        set clrBody {
            global $var
	    if {[set $var] != 0} {
            	$buttonName invoke
	    }
        }
        set clrCmd [list foreach var $variableList buttonName $buttonNameList $clrBody]
        APSButton .all -parent $parent$widget.frame -text All -size small  -command $setCmd
        APSButton .none -parent $parent$widget.frame -text None -size small  -command $clrCmd
    }
    if {$toggle} {
        set toggleBody {
            global $var 
            if {[set $var]==0} {
                $buttonName invoke
            } else {
                $buttonName deselect
            }
        }
        set toggleCmd [list foreach var $variableList buttonName $buttonNameList $toggleBody]
        APSButton .toggle -parent $parent$widget.frame -text Toggle -size small -command $toggleCmd
    }
    return $buttonNameList
}



proc APSFrameHelp {} {
    return "Usage: APSFrame widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-label <string>\]\t\n\[-width <num>\]\t\n\[-height <num>\]\t\n\[-orientation <string>\] where <string> is horizontal or vertical (default)\n\[-geometry <string>\]\t\n\[-relief <string>\]\t\n\[-contextHelp <string>\]\t\n\[-contextHelpImage <filename>\]\t\n\nCreates\t\$parent\$widget.\n\tlabel\n\tframe\n"
}

proc APSFrame {widget args} {
    global apsContextHelp apsContextHelpImage apsttk
    set parent ""
    set noPack 0
    set packOption "-side top"
    set label ""
    set labelFont ""
    set name ""
    set width 150
    set height 120
    set orientation vertical
    set geometry ""
    set contextHelp ""
    set contextHelpImage ""
    set relief ridge
    set gridPack ""
    APSStrictParseArguments {parent noPack packOption label labelFont name width height \
                               orientation geometry contextHelp contextHelpImage relief gridPack}

    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
    } else {
        set ttkPrefix ""
    }
    
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp    
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }

    if {$parent == ""} {
        toplevel $widget -bd 1
        wm title $widget $name
        if {$geometry != ""} {
            wm geometry $widget $geometry
        }
    } else {
        ${ttkPrefix}frame $parent$widget -borderwidth 1
        if {!$noPack} {
            if {[string length $gridPack]} {
                eval grid $parent$widget $gridPack
            } else {
                eval pack $parent$widget $packOption
            }
        }
    }
    if {$orientation == "vertical"} {
        set packside top
    } else {
        set packside left
    }
    if {$label != ""} {
        if {$packside == "top"} {
            if {$labelFont == ""} {
                ${ttkPrefix}labelframe $parent$widget.frame -relief $relief -borderwidth 2 -width $width -height $height -text $label
            } else {
                labelframe $parent$widget.frame -relief $relief -borderwidth 2 -width $width -height $height -text $label -font $labelFont
            }
        } else {
            if {$labelFont != ""} {
                ${ttkPrefix}label $parent$widget.label -text $label -font $labelFont
            } else {
                ${ttkPrefix}label $parent$widget.label -text $label
            }
            pack $parent$widget.label -side $packside -fill x
            ${ttkPrefix}frame $parent$widget.frame -relief $relief -borderwidth 2 -width $width -height $height
        }
    } else {
        ${ttkPrefix}frame $parent$widget.frame -relief $relief -borderwidth 2 -width $width -height $height
    }
    #previous version
    #pack $parent$widget.frame -side $packside -fill both 
    #changed to make the frame expandable if packOption for APSFrame has "-expand 1"
    if {[string match "*expand yes*" $packOption] || \
          [string match "*expand true*" $packOption] || \
          [string match "*expand 1*" $packOption]} {
        pack $parent$widget.frame -side $packside -fill both -expand yes
    } else {
        pack $parent$widget.frame -side $packside -fill both
    }
}

proc APSFrameGridHelp {} {
    return "Usage: APSFrameGrid widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-xList <list>\]\t\n\[-yList <list>\]\t\n\[-width <num>\]\t\n\[-height <num>\]\t\n\[-relief <string>\]\t\n\[-bd <string>\]\t\n\[-contextHelp <string>\]\t\n\[-contextHelpImage <filename>\]\t\n\nIf you supply just -xList or just -yList, it creates:\n\$parent\$widget.\n\t<name1>,...,<namen> where names are from xList or yList\n\nIf both -xList and -yList specified, it creates:\n\$parent\$widget.\n\t<xname1>.<yname1>,...,<xname1>.<ynamen>\n\t...\n\t<xnamen>.<yname1>,...,<xnamen>.<ynamen>\n"
}
proc APSFrameGrid {widget args} {
    global apsContextHelp apsContextHelpImage apsttk
    set xList ""
    set yList ""
    set parent ""
    set width 50m
    set height 8m
    set packOption "-side top -fill both -expand 1"
    set noPack 0
    set relief flat
    set bd 1
    set contextHelp ""
    set contextHelpImage ""
    set label ""
    APSStrictParseArguments {parent xList yList packOption noPack width \
                               height relief bd contextHelp contextHelpImage label}
    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
        set ttk 1
    } else {
        set ttkPrefix ""
        set ttk 0
    }

    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp    
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$parent == ""} {
        toplevel $widget -bd 1
        wm title $widget $label
    } else {
        ${ttkPrefix}frame $parent$widget -borderwidth 1
        if {!$noPack} {
            eval pack $parent$widget $packOption
        }
    }
    if {[llength $xList] == 0} {
        foreach yname $yList {
            ${ttkPrefix}frame $parent$widget.$yname -width $width -height $height \
              -relief $relief -borderwidth $bd
            pack $parent$widget.$yname -side top -fill both -expand 1
        }       
    } elseif {[llength $yList] == 0} {
        foreach xname $xList {
            ${ttkPrefix}frame $parent$widget.$xname -width $width -height $height \
              -relief $relief -borderwidth $bd
            pack $parent$widget.$xname -side left -fill both -expand 1
        }       
    } else {
        foreach xname $xList {
            ${ttkPrefix}frame $parent$widget.$xname 
            pack $parent$widget.$xname -side left -fill both -expand 1
            foreach yname $yList {
                ${ttkPrefix}frame $parent$widget.$xname.$yname -width $width -height $height \
                  -relief $relief -borderwidth $bd
                pack $parent$widget.$xname.$yname -side top -fill both -expand 1
            }
        }
    }
}

proc APSLabelHelp {} {
    return "Usage: APSLabel widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-text <string>\]\t\n\[-textVariable <string>\]\t\n\[-width <string>\]\t\n\[-contextHelp <string>\]\t\n\[-contextHelpImage <filename>\]\t\n\nCreates\t\$parent\$widget.\n\tlabel"
}

proc APSLabel {widget args} {
    global apsContextHelp apsContextHelpImage apsttk
    set parent ""
    set noPack 0
    set packOption "-side top -fill x"
    set text "NoText"
    set textVariable ""
    set width 20
    set contextHelp ""
    set contextHelpImage ""
    set gridPack ""
    set fgColor ""
    set bgColor ""
    set style "TLabel"
    set font ""
    APSStrictParseArguments {parent noPack packOption text textVariable \
                               width contextHelp contextHelpImage gridPack fgColor bgColor style font}

    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
        set ttk 1
    } else {
        set ttkPrefix ""
        set ttk 0
    }
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp    
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$parent == ""} {
        toplevel $widget -borderwidth 1
        wm title $widget $text
    } else {
        ${ttkPrefix}frame $parent$widget -borderwidth 1
        if {!$noPack} {
            if {[string length $gridPack]} {
                eval grid $parent$widget $gridPack
            } else {
                eval pack $parent$widget $packOption
            }
        }
    }
    if [string length $textVariable] {
        ${ttkPrefix}label $parent$widget.label -text $text -textvariable $textVariable
    } else {
        ${ttkPrefix}label $parent$widget.label -text $text
    }
    pack $parent$widget.label -side left -fill x
    if [string length $fgColor] {
        $parent$widget.label configure -foreground $fgColor
    }
    if [string length $bgColor] {
        $parent$widget.label configure -background $bgColor
    }
    if [string length $font] {
        $parent$widget.label configure -font $font
    }
    if {$ttk && ($style != "") && ($style != "TLabel")} {
        $parent$widget.label configure -style $style
    }
}

proc APSSetStateButton {widget args} {
    set variable ""
    set state 0
    
    APSStrictParseArguments {variable state}

    global $variable
    global apsStateButtonHighlight apsStateButtonHighlightColorList
    set highlight $apsStateButtonHighlight($variable)
    set highlightColorList $apsStateButtonHighlightColorList($variable)

    set $variable $state
    if {$state} {
        $widget configure -relief sunken
        if {$highlight} {
            [winfo parent $widget] configure -bg [lindex $highlightColorList 1]
        }
    } else {
        $widget configure -relief raised
        if {$highlight} {
            [winfo parent $widget] configure -bg [lindex $highlightColorList 0]
        }
    }
}

proc APSToggleStateButton {widget args} {
    set variable ""
    APSStrictParseArguments {variable}

    global $variable
    APSSetStateButton $widget -variable $variable \
	-state [expr {![subst \$$variable]}]
}

proc APSStateButtonHelp {} {
    return "Usage: APSStateButton widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-text <string>\]\t\n\[-variable <string>\]\t\n\[-command <string>\]\t\n\[-highlight 1\]\t\n\[-size <string>\] where <string> is small or medium (default)\n\[-contextHelp <string>\]\t\n\[-contextHelpImage <filename>\]\t\n\nCreates\t\$parent\$widget.\n\tbutton"
}

proc APSStateButton {widget args} {
    global apsContextHelp apsContextHelpImage
    set parent ""
    set noPack 0
    set packOption "-side left -padx 1 -pady 1"
    set text "notext"
    set command ""
    set highlight 0
    set highlightColorList {black black}
    set size medium
    set contextHelp ""
    set contextHelpImage ""
    set variable ""
    set gridPack ""
    APSStrictParseArguments {parent noPack packOption text command highlight \
				 size contextHelp contextHelpImage variable highlightColorList \
				 gridPack}

    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if {$variable == ""} {
        APSAlertBox [APSUniqueName .uniqueNameError] -errorMessage "No -variable option for APSStateButton"
        return
    }

    if {$parent == ""} {
        if {$highlight} {
            toplevel $widget -bd 2 -bg black
        } else {
            toplevel $widget -bd 2
        }
        wm title $widget $text
    } else {
        if {$highlight} {
            frame $parent$widget -bd 2 -bg black
        } else {
            frame $parent$widget -bd 2
        }
        if {!$noPack} {
            if {[string length $gridPack]} {
                eval grid $parent$widget $gridPack
            } else {
                eval pack $parent$widget $packOption
            }
        }
    }
    global apsStateButtonHighlight apsStateButtonHighlightColorList
    set apsStateButtonHighlight($variable) $highlight
    set apsStateButtonHighlightColorList($variable) $highlightColorList
    if {$size == "small"} {
        button $parent$widget.button -text $text -command \
          "APSToggleStateButton $parent$widget.button -variable $variable; $command" \
          -highlightthickness 0 -padx 3 -pady 1 -font \
          -adobe-courier-medium-r-normal-*-10-*-*-*-*-*-*-*
    } else {
        button $parent$widget.button -text $text -command \
          "APSToggleStateButton $parent$widget.button -variable $variable; $command" \
          -highlightthickness 0 -padx 6 -pady 3
    }
    global $variable
    set $variable 0
    $parent$widget.button configure -relief raised

    pack $parent$widget.button -side top -fill x
}


proc APSComboboxFrameHelp {} {
    return "Usage: APSComboboxFrame widget \n\[-parent <string>\]\t\n\[-noPack 1\]\t\n\[-packOption <list>\]\t\n\[-gridPack <list>\]\t\n\[-label <string>\]\t\n\[-textVariable <string>\]\t\n\[-textFont <string>\]\n\[-labelFont <string>\]\n\[-editable <1|0>\]\n\[-callback <string>\]\n\[-height <value>\]\n\[-width <value>\]\n\[-contextHelp <string>\]\t\n\[-contextHelpImage <filename>\]\t\n\nCreates\t\$parent\$widget.cb"
}

proc APSComboboxFrame {widget args} {
    global apsContextHelp apsContextHelpImage apsttk
    set parent ""
    set noPack 0
    set packOption "-side top -fill x"
    set label "NoLabel"
    set textVariable ""
    set width 20
    set contextHelp ""
    set contextHelpImage ""
    set gridPack ""
    set itemList ""
    set editable 0
    set height 11
    set callback ""
    set maxWidth 0
    #set labelFont "-*-Interface User-Medium-R-*-*-*-140-*-*-*-*-iso8859-1"
    if {[info exists apsttk] && ($apsttk != 0)} {
        set ttkPrefix ttk::
        set textFont TkDefaultFont
        set labelFont TkDefaultFont
    } else {
        set ttkPrefix ""
        set textFont -adobe-courier-medium-r-normal-*-14-*-*-*-*-*-*-*
        set labelFont -adobe-courier-medium-r-normal-*-14-*-*-*-*-*-*-*
    }
    APSStrictParseArguments {parent noPack packOption label textVariable editable height\
                               width contextHelp contextHelpImage gridPack itemList callback labelFont \
                               textFont maxWidth}
    if {$contextHelp != ""} {
        set apsContextHelp($parent$widget) $contextHelp    
    }
    if {$contextHelpImage != ""} {
        set apsContextHelpImage($parent$widget) $contextHelpImage
    }
    if ![llength $itemList] {
        return -code error "APSComboboxFrame: the item list not given."
    }
    if [string length $textVariable] {
        if ![regexp {\(} $textVariable] {
            global $textVariable
        }
    }
    if {$parent == ""} {
        toplevel $widget -bd 1
        wm title $widget $label
    } else {
        ${ttkPrefix}frame $parent$widget -borderwidth 1
        if {!$noPack} {
	    if {[string length $gridPack]} {
                eval grid $parent$widget $gridPack
            } else {
                eval pack $parent$widget $packOption
            }
        }
    }
    if $maxWidth {
        set maximum $width
        foreach item $itemList {
            if {[string length $item]>$maximum} {
                set maximum [string length $item]
            }
        }
        set width $maximum
    }
    ${ttkPrefix}label $parent$widget.label -text $label -font $labelFont
    pack $parent$widget.label -side left -fill x
    if {!$editable} {
        set state readonly
    } else {
        set state normal
    }
    if [string length $textVariable] {
        if {($editable == "0") || ($editable == "no") || ($editable == "false")} {

        }
        ttk::combobox $parent$widget.cb -width $width -height $height -cursor hand1 -textvariable $textVariable -state $state -values $itemList
        bind $parent$widget.cb <<ComboboxSelected>> "APSComboboxRunCallback %W -callback [list $callback] -textFont $textFont -editable $editable -textVariable $textVariable"
    } else {
        ttk::combobox $parent$widget.cb -width $width -height $height -cursor hand1 -state $state -values $itemList
        bind $parent$widget.cb <<ComboboxSelected>> "APSComboboxRunCallback %W -callback [list $callback] -textFont $textFont -editable $editable"        
    }
    pack $parent$widget.cb -side right -fill x
}

proc APSComboboxRunCallback {widget args} {
    set callback ""
    set textFont ""
    set editable 0
    set textVariable ""
    APSStrictParseArguments {callback textFont editable textVariable}
    $widget selection clear
    if [string length $callback] {
        if ![string length [$widget get]] {
            return
        }
        if [string length $textVariable] {
            global $textVariable
            if ![string length [set $textVariable]] {
                return
            }
        }
        eval $callback {[$widget current]}
    }
}

proc APSMakeLabelList {args} {
    set labelMaker ""
    set arrayName ""
    set callback ""
    set columnList ""
    set trim 1
    set filename ""
    set page 0
    APSStrictParseArguments {labelMaker arrayName callback columnList trim filename page}
    global $arrayName
    set maxlen {}
    foreach name $columnList {
        if {[string length $name]==0} {
            break;
        }
        set ${arrayName}($name) [APSGetSDDSColumn -fileName $filename -column $name -page $page]
        set width [APSMaxStringLength [subst \$${arrayName}($name)]]
        lappend maxlen $width
    }
    foreach name $columnList {
        if {[string length $name]==0} {
            break;
        }
        set ${arrayName}($name) [APSGetSDDSColumn -fileName $filename -column $name -page $page]
    }
    set i 0
    set itemsInList [llength [subst \$${arrayName}([lindex $columnList 0])]]
    set labelList ""
    for {set i 0} {$i<$itemsInList} {incr i} {
        set data {}
        foreach name $columnList {
            lappend data [lindex [subst \$${arrayName}($name)] $i]
        }
        set label [$labelMaker -dataList $data -widthList $maxlen]
        if {$trim} {
            # remove leading and trailing spaces
            regsub -all \[\001-\026\] [string trim $label] "" label
            # remove repeated spaces 
            while {[string first "   " $label]!=-1} {
                regsub -all "   " $label " " label
            }
        }
        lappend labelList $label
    }
    return $labelList
}

proc APSPVFilterWidget {widget args} {
    global apsSCRPVNameFilter apsSCRFilterFileDir apsSCRFilterFileName apsSCRFilterFileDescription 
    global apsSCRInvertFilterFile apsSCRSuppressSingleBeamline apsSCRPVSetpointFilter

    set parent ""
    set fileName ""
    set rootname ""
    set snapDir ""
    set limitPerRow 7
    set showSetpointFilter 0
    APSStrictParseArguments {parent fileName rootname snapDir limitPerRow showSetpointFilter}

    set name [APSRemoveGzipExtension $fileName]

    APSFrame $widget -parent $parent -packOption "-side top -expand true -fill both"
    set w ${parent}${widget}.frame

    set categories $snapDir/categories/categ$name
    if ![file exists $categories] {
        set categories $snapDir/categ$name
    }
    if ![file exists $categories] {
        if [catch {exec sddssort $snapDir/$fileName $categories -unique -column=Category } result] {
            return -code error "Error in generating category file (most probably you do not have write permission to $snapDir): $result"
        }
    }
    APSSDDSCheckButtons .list1 -parent $w -fileName $categories -column Category \
      -arrayName apsSCRFilterCategory -page 0 -limit $limitPerRow -duplicate 0 -modal 0 \
     -noOk 1 -noCancel 1 -buttonSize small
   
    set beamlines $snapDir/beamlines/beam$name
    if ![file exists $beamlines] {
        set beamlines $snapDir/beam$name
    }
    if ![file exists $beamlines] {
        if [catch {exec sddssort $snapDir/$fileName $beamlines -unique -column=Beamline } result] {
             return -code error "Error in generating beamline file (most probably you do not have write permission to $snapDir): $result"
        }
    }
    set showBeamlines 1
    if $apsSCRSuppressSingleBeamline {
        set nbeamlines [exec sdds2stream -rows=bare $beamlines]
        if $nbeamlines<=1 {
            set showBeamlines 0
        }
    }
    if $showBeamlines {
        APSSDDSCheckButtons .list2 -parent $w -fileName $beamlines -column Beamline \
          -arrayName apsSCRFilterBeamline -page 0 -limit 15 -duplicate 0 -modal 0 \
          -noOk 1 -noCancel 1 -buttonSize small
    } else {
        global apsSCRFilterBeamline
        set apsSCRFilterBeamline(DUMMY) 1
    }

    if {$showSetpointFilter} {
        APSCheckButtonFrame .setpoints \
          -parent $w \
          -label "" \
          -buttonList {"Setpoints Only"} \
          -variableList "apsSCRPVSetpointFilter"
    }

    if [winfo exists $w.pvname] {
        destroy $w.pvname
    }
    APSLabeledEntry .pvname -parent $w -textVariable apsSCRPVNameFilter -width 40  -label "PV name filter: " \
      -packOption "-side top" \
      -contextHelp "Enter a string to use in filtering process variable names prior to review/restore.\
 The character * matches zero or more arbitrary characters, while the character ? matches any single\
 character.  So S*A:Q1* would match all the A:Q1 quadrupole process variables for the SR.\n\n\
 Square brackets (\[ and \]) can be used to indicate sets of values.  For example, S\[1-4\]A:Q1*\
 would match all the A:Q1 quadrupole PVs in sectors 1 through 4, while S\[1-3\]9\[AB\]:Q1* would match*\
 A:Q1 and B:Q1 PVs in sectors 19, 29, and 39."

    bind $w.pvname.entry <Key> "set apsSCRInvertFilterFile 0"

    set filterFileList $apsSCRFilterFileDir/${rootname}-FilterFiles.sdds
    if [file exists $filterFileList] {
        set apsSCRFilterFileDescription ""
        set apsSCRFilterFileName ""
        set apsSCRInvertFilterFile 0
        set filterList [APSMakeLabelList -filename $filterFileList \
                          -labelMaker APSSCRMakeLBoxTextFilterFile -arrayName apsSCRFilterFileArray \
                          -callback APSSCRFilterFileCallback \
                          -columnList {Filename Description Wildcard BeamlineList CategoryList} ]
        if ![llength $filterList] {
            return
        }
        global apsSCRFilterFileDescriptionComboboxFrame 
        APSFrame .options -parent $w -packOption "-side top"
        $w.options.frame configure -borderwidth 0
        APSComboboxFrame .choice -parent $w.options.frame -label "Predefined filter:" -width 40  \
          -textVariable apsSCRFilterFileDescription -callback APSSCRFilterFileCallback \
          -itemList $filterList -packOption "-side top" \
          -contextHelp "Displays the choice of predefined filter.  If blank, no predefined filter is used"
        
        set apsSCRFilterFileDescriptionComboboxFrame $w.options.frame.choice.cb
        
        APSCheckButtonFrame .invert -parent $w.options.frame -label "" -packOption "-side left" \
          -buttonList {"Invert predefined filter"} -variableList apsSCRInvertFilterFile \
          -orientation horizontal -relief flat -contextHelp \
          "Inverts the selection of PVs with the filter file, so that the items selected are all those that would  normally be rejected.  For some predefined filters (those using wildcards instead of a file), this feature is disabled." \
          -commandList {APSSCRInvertFilterFileCallback}

        APSButton .ffclear -parent $w.options.frame -text CLEAR -size small -packOption "-side left" \
          -command {set apsSCRFilterFileName ""; set apsSCRPVNameFilter *; \
                      set apsSCRFilterFileDescription "" ; set apsSCRInvertFilterFile 0} \
          -contextHelp "Clears the predefined filter choice, so that no predefined filter is used."
    }

}

proc APSBarHelp {} {
    return "\
Usage: APSBar widget
\[-parent <string>\]\t
\[-noPack 1\]\t
\[-packOption <list>\]\t
\[-width <integer>\]\t
\[-height <integer>\]\t
\[-min <real>\]\t
\[-max <real>\]\t
\[-value <real>\]\t
\[-color <string>\]\t
\[-label <string>\]\t
\[-direction <right|left|up|down>\]\t

Creates\t\$parent\$widget.
\tbar

Returns \$parent\$widget
to be used with APSBarAdjust
"
}

proc APSBar {widget args} {
    global apsBackground
    set parent ""
    set width 100
    set height 20
    set packOption "-side top"
    set min 0
    set max 10
    set value 0
    set background $apsBackground
    set color blue
    set noPack 0
    set direction "right"
    set label ""
    APSStrictParseArguments {parent width height min max color value packOption noPack background direction label}

    set w ${parent}$widget
    frame ${parent}$widget \
      -width $width \
      -height $height \
      -relief raised \
      -bd 2 \
      -bg $background
    frame ${w}.bar \
      -relief sunken \
      -bd 2 \
      -bg $background
    frame ${w}.bar.level \
      -bg $color \
      -relief flat
    if {$label == "outline"} {
        label ${w}.max \
          -textvariable apsBarInfo(${w}.max) \
          -font [APSSelectADLFont -type bar -height $height]
        label ${w}.min \
          -textvariable apsBarInfo(${w}.min) \
          -font [APSSelectADLFont -type bar -height $height]
    }
    global apsBarInfo
    set apsBarInfo(${w}.min) $min
    set apsBarInfo(${w}.max) $max
    set apsBarInfo(${w}.value) $value
    set apsBarInfo(${w}.direction) $direction
    
    set value [expr {($value - $min) / ($max - $min)}]

    if {$direction == "right"} {
        if {$label == "outline"} {
            place ${w}.bar -relx 0 -rely .3 -anchor nw -relwidth 1 -relheight .67
            place ${w}.min -relx .01 -rely .01 -anchor nw
            place ${w}.max -relx .99 -rely .01 -anchor ne
        } else {
            place ${w}.bar -relx 0 -rely 0 -anchor nw -relwidth 1 -relheight 1
        }
        place ${w}.bar.level -relx 0 -rely 0 -anchor nw -relwidth $value -relheight 1
    } elseif {$direction == "left"} {
        if {$label == "outline"} {
            place ${w}.bar -relx 1 -rely .3 -anchor ne -relwidth 1 -relheight .67
            place ${w}.min -relx .01 -rely .01 -anchor nw
            place ${w}.max -relx .99 -rely .01 -anchor ne
        } else {
            place ${w}.bar -relx 1 -rely 0 -anchor ne -relwidth 1 -relheight 1
        }
        place ${w}.bar.level -relx 1 -rely 0 -anchor ne -relwidth $value -relheight 1
    } elseif {$direction == "up"} {
        if {$label == "outline"} {
            place ${w}.bar -relx .75 -rely .03 -anchor nw -relwidth .22 -relheight .94
            place ${w}.max -relx .70 -rely .01 -anchor ne
            place ${w}.min -relx .70 -rely .99 -anchor se
        } else {
            place ${w}.bar -relx 0 -rely 0 -anchor nw -relwidth 1 -relheight 1
        }
        place ${w}.bar.level -relx 0 -rely 1 -anchor sw -relwidth 1 -relheight $value
    } elseif {$direction == "down"} {
        if {$label == "outline"} {
            place ${w}.bar -relx .75 -rely .03 -anchor nw -relwidth .22 -relheight .94
            place ${w}.max -relx .70 -rely .01 -anchor ne
            place ${w}.min -relx .70 -rely .99 -anchor se
        } else {
            place ${w}.bar -relx 0 -rely 0 -anchor nw -relwidth 1 -relheight 1
        }
        place ${w}.bar.level -relx 0 -rely 0 -anchor nw -relwidth 1 -relheight $value
    }
    if {!$noPack} {
        eval pack ${w} $packOption
    }
    bind $w <Configure> "APSBarAdjust $w -value \[set apsBarInfo(${w}.value)\]"
    return $w
}

proc APSBarAdjustHelp {} {
    return "\
Usage: APSBarAdjust widget
\[-value <real>\]\t
\[-min <real>\]\t
\[-max <real>\]\t

Adjusts the length of the bar.
Please see APSBar 
for more information.
"
}

proc APSBarAdjust {widget args} {
    global apsBarInfo
    set min $apsBarInfo(${widget}.min)
    set max $apsBarInfo(${widget}.max)
    set value 0
    APSStrictParseArguments {value min max}
    set apsBarInfo(${widget}.value) $value
    set apsBarInfo(${widget}.min) $min
    set apsBarInfo(${widget}.max) $max
    set direction $apsBarInfo(${widget}.direction)
    set width [winfo width $widget]
    set height [winfo height $widget]
    set borderwidth [expr {2 * [$widget cget -bd]}]

    set value [expr {($value - $min) / ($max - $min)}]
    if {($direction == "right") || ($direction == "left")} {
        place configure ${widget}.bar.level -relwidth $value
    } else {
        place configure ${widget}.bar.level -relheight $value
    }
    update idletasks
}

proc APSLargeStringEditor {args} {
    set textVariable "" 
    set name "Edit Large String Entry"
    set widget ""
    set width 100
    set noLineFeed 0
    APSStrictParseArguments {textVariable name widget noLineFeed width}
    
    if ![string length $widget] {
        set widget .editLargeString
    }
    if [winfo exist $widget] {
        return -code error "Window $widget already exists."
    }
    if ![string length $textVariable] {
        return -code error "textVariable for entry is not provided."
    }
    if [regexp {(.*)\(} $textVariable a b c] {
        #if pass in variable is an array
        set var $b
    } else {
        set var $textVariable
    }
    global $var
   
    APSDialogBox $widget -name "Edit Large Entry String" -width $width \
        -contextHelp ""
    destroy $widget.buttonRow.ok.button 
    destroy $widget.buttonRow.cancel.button
    APSDialogBoxAddButton .dismiss -parent $widget -text "Dismiss" \
        -command "destroy $widget" -contextHelp ""
    
    APSScrolledText .largeText -parent $widget.userFrame -width $width \
        -height 20 -name LargeString -contextHelp ""
    
    if ![info exist $textVariable] {
        set $textVariable ""
    }
    
    set t $widget.userFrame.largeText.text
    $t insert end [set $textVariable]
    
    if [string compare [$t cget -state] normal]==0 {
        bindtags $t "Text . all $t"
        bind $t <KeyRelease> "APSUpdateTextWidgetVariable -widget $t -textVariable $textVariable -noLineFeed $noLineFeed" 
        event add <<Paste>> <ButtonRelease-2>
        bind $t <<Paste>> "APSUpdateTextWidgetVariable -widget $t -textVariable $textVariable -noLineFeed $noLineFeed" 
    }
}

proc APSUpdateTextWidgetVariable {args} {
    set widget ""
    set textVariable ""
    set noLineFeed 0
    APSStrictParseArguments {widget textVariable noLineFeed}
    if [regexp {(.*)\(} $textVariable a b c] {
        #if pass in variable is an array
        set var $b 
    } else {
        set var $textVariable
    }
    global $var
    if $noLineFeed {
        set $textVariable [regsub {\n} [$widget get 1.0 end] " "]
    } else {
        set $textVariable [string trimright [$t get 1.0 end] \n]
    }
    update
}

proc shuffle {data} {
    set rand_data [list]
    foreach elem $data {
        lappend rand_data [list [expr {rand()}] $elem]
    }
    set result [list]
    foreach elem [lsort -real -index 0 $rand_data] {
        lappend result [lindex $elem 1]
    }
    return $result
}
