
#         Portable Batch System (PBS) Software License
# 
# Copyright (c) 1999, MRJ Technology Solutions.
# All rights reserved.
# 
# Acknowledgment: The Portable Batch System Software was originally developed
# as a joint project between the Numerical Aerospace Simulation (NAS) Systems
# Division of NASA Ames Research Center and the National Energy Research
# Supercomputer Center (NERSC) of Lawrence Livermore National Laboratory.
# 
# Redistribution of the Portable Batch System Software and use in source
# and binary forms, with or without modification, are permitted provided
# that the following conditions are met:
# 
# - Redistributions of source code must retain the above copyright and
#   acknowledgment notices, this list of conditions and the following
#   disclaimer.
# 
# - Redistributions in binary form must reproduce the above copyright and 
#   acknowledgment notices, this list of conditions and the following
#   disclaimer in the documentation and/or other materials provided with the
#   distribution.
# 
# - All advertising materials mentioning features or use of this software must
#   display the following acknowledgment:
# 
#   This product includes software developed by NASA Ames Research Center,
#   Lawrence Livermore National Laboratory, and MRJ Technology Solutions.
# 
#         DISCLAIMER OF WARRANTY
# 
# THIS SOFTWARE IS PROVIDED BY MRJ TECHNOLOGY SOLUTIONS ("MRJ") "AS IS" WITHOUT 
# WARRANTY OF ANY KIND, AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE EXPRESSLY DISCLAIMED.
# 
# IN NO EVENT, UNLESS REQUIRED BY APPLICABLE LAW, SHALL MRJ, NASA, NOR
# THE U.S. GOVERNMENT BE LIABLE FOR ANY DIRECT DAMAGES WHATSOEVER,
# NOR ANY INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 
# This license will be governed by the laws of the Commonwealth of Virginia,
# without reference to its choice of law rules.
################################################################################
# This file contains procedures related to button widgets (checkboxes, radio
# buttons, command buttons.
################################################################################
# buildCheckboxes: creates a row or column of checkbuttons on 'frame_name' 
#	following the arrangement specified in 'checkbutton_list'.
#
# INPUT FORMATS:
#	'checkbutton_list' - 
#		{ {group1_button1_name group1_button1_label group1_button1_assoc}
#		  {group1_button2_name group1_button2_label group1_button1_assoc}
#		   . . . }
#		{ {group2_button1_name group2_button1_label group2_button1_assoc}
#		  {group2_button2_name group2_button2_label group2_button1_assoc}
#		   . . . }
#		}
#		
#	'orient' - how the group of checkbuttons are to be arranged: column, grid.  
#	'spacing' - amount of spacing between groups of checkbuttons (in Get_Pixels
#		    format).
# OPTIONS:
#	'checkbox_labelstr' - if the entire groups of checkbuttons are to be given one
#		 label string.
#	'place_buttonAssoc_right' - if the button*_assoc is to be placed on the
#		right side of a check button. 
#	'place_labelstr_top' - if 'checkbox_labelstr' is to be placed on top of all
#		checkbuttons instead of to the left.
#	'button_assoc_groove_relief' - if the button*_assoc is to be enclosed in a
#		a groove relief.
#	'selective_right_placement' - refers to the nth button whose
#				      association will be displayed on its
#				      right if 'place_buttonAssoc_right' is
#			              set.	
#					
###############################################################################
proc buildCheckboxes {frame_name checkbutton_list orient spacing \
   {checkbox_labelstr ""} {place_buttonAssoc_right 1} {place_labelstr_top 0} \
   {button_assoc_groove_relief 0} } {
  global LABELFONT BADPARAM errmsg

  set procname "buildCheckboxes"


## Let's be defensive about the input
  if { ![regexp "\\." $frame_name] || \
        ([string compare $orient "column"] != 0 &&  \
         [string compare $orient "grid"] != 0) } {
        puts "Error $BADPARAM in \{$procname $frame_name\}: $errmsg(BADPARAM)"
        exit $BADPARAM
  }
  
  if { [string compare $frame_name "."] == 0 } {
       set frame_name ""	
  }

  if {[string compare $checkbox_labelstr ""] != 0} {

    message $frame_name.clabel -font $LABELFONT -aspect 1000 \
		-text $checkbox_labelstr

    if {$place_labelstr_top} {
      pack $frame_name.clabel -side top -anchor nw
    } else {
      pack $frame_name.clabel -side left -anchor nw
    }
  }
  set i 1
  set allButtonsList ""
  foreach group [lrange $checkbutton_list 0 end] {

    frame $frame_name.$i
    label $frame_name.${i}_dummy -width 1 -font $LABELFONT -padx 1 -pady 1
    eval pack "$frame_name.${i}_dummy" -side left
    eval pack "$frame_name.$i" -side top -anchor nw

    set buttonList ""
    foreach button_entry [lrange $group 0 end] {
      set buttonName  [lindex $button_entry 0]
      set buttonLabel [lindex $button_entry 1]
      set buttonAssoc [lindex $button_entry 2]

      if {[string compare $buttonAssoc ""] != 0} {
 
        if {$button_assoc_groove_relief} {  
	  frame $frame_name.$i.f$buttonName -relief groove -borderwidth 2
        } else {
	  frame $frame_name.$i.f$buttonName
        }
        checkbutton $frame_name.$i.f$buttonName.$buttonName -relief flat \
		    -anchor c -font $LABELFONT -text $buttonLabel \
		    -padx 1 -pady 1
	if {$place_buttonAssoc_right} {
	  pack $frame_name.$i.f$buttonName.$buttonName -side left -anchor nw

	} else {
	  pack $frame_name.$i.f$buttonName.$buttonName -side top -anchor nw
	}
        pack forget $buttonAssoc
	if { $place_buttonAssoc_right } {
          pack $buttonAssoc -in $frame_name.$i.f$buttonName -side right \
		-anchor nw
        } else {
          pack $buttonAssoc -in $frame_name.$i.f$buttonName -side bottom -anchor nw 
        }
        raise $buttonAssoc $frame_name.$i.f$buttonName
        append buttonList " " $frame_name.$i.f$buttonName
        append allButtonsList " " $frame_name.$i.f$buttonName.$buttonName
      } else {
        checkbutton $frame_name.$i.$buttonName -relief flat -anchor c \
                  -font $LABELFONT -text $buttonLabel -padx 1 -pady 1
        append buttonList " " $frame_name.$i.$buttonName
        append allButtonsList " " $frame_name.$i.$buttonName
      }
    }
    if { [string compare $orient "column"] == 0 } {  
	eval pack "$buttonList" -side top -anchor nw -pady $spacing
    } else {
	eval pack "$buttonList" -side left -anchor nw -padx $spacing
    }
    incr i
  }
  return [concat $frame_name $allButtonsList]
}
###############################################################################
# buildCmdButtons: creates a row or column of command buttons on 'frame_name' 
#	following the arrangement specified in 'cmdbutton_list'.
#
# INPUT FORMATS:
#	'cmdbutton_list' - 
#		{ {group1_button1_name group1_button1_label group1_button1_assoc}
#		  {group1_button2_name group1_button2_label group1_button1_assoc}
#		   . . . }
#		{ {group2_button1_name group2_button1_label group2_button1_assoc}
#		  {group2_button2_name group2_button2_label group2_button1_assoc}
#		   . . . }
#		}
#		
#	'orient' - how the group of cmd buttons are to be arranged: x (lie in
#		a horizontal line), y (line in a vertical line), xy (row of columned
#		buttons).
#	'spacing' - amount of spacing between groups of checkbuttons (in Get_Pixels
#		    format).
#       'button_width'      - the width of a command button (in Get_Pixels format)
#        'button_height'     - the height of a command button(in Get_Pixels format)
# OPTIONS:
#        'first_group_spacing' - an optional boolean value that says to put
#                             a button spacing before the 1st group of buttons
#	'spread_out_buttons' - if 1 (true), then the buttons will be spread out
#                            in the frame
#	'group_spacing'	   - spacing between groups of cmd buttons.
#	'cmdbutton_labelstr' - if the entire groups of cmdbuttons are to be given one
#		 label string.
###############################################################################
proc buildCmdButtons {frame_name cmdbutton_list orient spacing button_width\
                      button_height {first_group_spacing 0} \
                      {spread_out_buttons 1} {group_spacing "10m"} \
		      {cmdButton_labelstr ""} {place_buttonAssoc_right 1} \
		      {place_labelstr_top 0} {button_assoc_groove_relief 0} } {
  global LABELFONT BADPARAM errmsg

  set procname "buildCmdboxes"


## Let's be defensive about the input
  if { ![regexp "\\." $frame_name] || \
        ([string compare $orient "x"] != 0 &&   \
         [string compare $orient "y"] != 0 &&   \
         [string compare $orient "xy"] != 0) || \
	 ![regexp "\[0-9]+" $button_width]  ||  \
	 ![regexp "\[0-9]+" $button_height] } {
        puts "Error $BADPARAM in \{$procname $frame_name\}: $errmsg(BADPARAM)"
        exit $BADPARAM
  }
  
  if { [string compare $frame_name "."] == 0 } {
       set frame_name ""	
  }
  if { [string compare $cmdButton_labelstr ""] != 0 } {
    message $frame_name.clabel -font $LABELFONT -text $cmdButton_labelstr \
            -aspect 1000
    pack $frame_name.clabel -side top -anchor nw
  }

  if {$spread_out_buttons} {
    pack forget $frame_name
    pack $frame_name -fill both -expand 1 -ipadx 5m -ipady 5m
  }

  set i 1
  set allButtonsList ""
  foreach group [lrange $cmdbutton_list 0 end] {
    frame $frame_name.$i -relief flat

    set buttonList ""
    foreach button_entry $group {
      set buttonName  [lindex $button_entry 0]
      set buttonLabel [lindex $button_entry 1]
      set buttonAssoc [lindex $button_entry 2]

      if {[string compare $buttonAssoc ""] != 0} {
 
        if {$button_assoc_groove_relief} {  
	  frame $frame_name.$i.f$buttonName -relief groove -borderwidth 2
        } else {
	  frame $frame_name.$i.f$buttonName
        }
        button $frame_name.$i.f$buttonName.$buttonName -anchor nw \
		    -font $LABELFONT -text $buttonLabel -width $button_width \
		    -height $button_height -padx 1 -pady 1

	if {$place_buttonAssoc_right} {
	  pack $frame_name.$i.f$buttonName.$buttonName -side left -anchor nw \
		-side left -anchor nw -fill x

	} else {
	  pack $frame_name.$i.f$buttonName.$buttonName -side top -anchor nw \
		-side top -anchor nw -fill y
	}

        pack forget $buttonAssoc
	if { $place_buttonAssoc_right } {
          pack $buttonAssoc -in $frame_name.$i.f$buttonName -side right \
		-anchor nw -fill x
        } else {
          pack $buttonAssoc -in $frame_name.$i.f$buttonName -side bottom \
		-anchor nw -fill y
        }
        raise $buttonAssoc $frame_name.$i.f$buttonName
        append buttonList " " $frame_name.$i.f$buttonName
        append allButtonsList " " $frame_name.$i.f$buttonName.$buttonName
      } else {	
	button $frame_name.$i.$buttonName -anchor c \
                  -font $LABELFONT -text $buttonLabel -width $button_width \
		  -height $button_height -padx 1 -pady 1

	append buttonList " " $frame_name.$i.$buttonName
	append allButtonsList " " $frame_name.$i.$buttonName
      }	
    }

    if { [string compare $orient "y"] == 0 } {  
	eval pack "$buttonList" -side top -anchor nw -pady $spacing
    } else {
	eval pack "$buttonList" -side left -anchor c -padx $spacing -expand 1
    }
    if {$i == 1 && $first_group_spacing} {   ;# put an extra spacing before 1st
      label $frame_name.empty$i -width $button_width -height $button_height \
	    -padx 1 -pady 1

      if { [string compare $orient "x"] == 0 } {

	if {$spread_out_buttons} {
          eval pack "$frame_name.empty$i $frame_name.$i" -anchor c \
	            -expand 1 -fill both
        } else {
          eval pack "$frame_name.empty$i $frame_name.$i" -anchor c 
        }

      } else {
	if {$spread_out_buttons} {
          eval pack "$frame_name.empty$i $frame_name.$i" -side top -anchor c \
		-fill both -expand 1
	} else {
          eval pack "$frame_name.empty$i $frame_name.$i" -side top -anchor c
	}
      }
    } elseif { [expr $i % 2] == 0 } {	   ;# space even number buttons
      if { [string compare $orient "x"] == 0 } {
	if {$spread_out_buttons} {
          eval pack "$frame_name.$i" -padx $group_spacing  -side left -anchor c \
	             -fill both -expand 1
        } else {
          eval pack "$frame_name.$i" -padx $group_spacing -side left -anchor c
        }
      } else {
	if {$spread_out_buttons} {
          eval pack "$frame_name.$i" -pady $group_spacing -side top -anchor c \
	            -fill both -expand 1
	} else {
          eval pack "$frame_name.$i" -pady $group_spacing -side top -anchor c
        }
      }
    } else {
      if { [string compare $orient "x"] == 0 } {
	if {$spread_out_buttons} {
          eval pack "$frame_name.$i" -side left -anchor c -fill both -expand 1
	} else {
          eval pack "$frame_name.$i" -side left -anchor c
	}
      } else {
	if {$spread_out_buttons} {
          eval pack "$frame_name.$i" -side top -anchor c -fill both -expand 1
        } else {
          eval pack "$frame_name.$i" -side top -anchor c
        }
      }
    }

    incr i
  }
  if {[string compare $cmdButton_labelstr ""] != 0} {
    return [concat $frame_name $allButtonsList $frame_name.clabel]
  } else {
    return [concat $frame_name $allButtonsList]
  }
}
###############################################################################
# buildRadioboxes: creates a row or column of radiobuttons on 'frame_name' 
#	following the arrangement specified in 'checkbutton_list'.
#
# INPUT FORMATS:
#	'radiobutton_list' - 
#		{ {group1_button1_name group1_button1_label group1_button1_assoc}
#		  {group1_button2_name group1_button2_label group1_button1_assoc}
#		   . . . }
#		{ {group2_button1_name group2_button1_label group2_button1_assoc}
#		  {group2_button2_name group2_button2_label group2_button1_assoc}
#		   . . . }
#		}
#		
#	'orient' - how the group of radiobuttons are to be arranged: column, grid.  
#	'spacing' - amount of spacing between groups of radiobuttons (in Get_Pixels
#		    format).
# OPTIONS:
#	'radiobox_labelstr' - if the entire groups of radiobuttons are to be given one
#		 label string.
#	'place_buttonAssoc_right' - if the button*_assoc is to be placed on the
#		right side of a check button. 
#	'place_labelstr_top' - if 'checkbox_labelstr' is to be placed on top of all
#		checkbuttons instead of to the left.
#	'button_assoc_groove_relief' - if the button*_assoc is to be enclosed in a
###############################################################################
proc buildRadioboxes {frame_name radiobutton_list orient spacing \
     {radiobox_labelstr ""} {place_buttonAssoc_right 1} \
     {place_labelstr_top 0} {button_assoc_groove_relief 0} \
     {selective_right_placement ".*"}} {
  global LABELFONT BADPARAM errmsg

  set procname "buildRadioboxes"

## Let's be defensive about the input
  if { ![regexp "\\." $frame_name] || \
        ([string compare $orient "column"] != 0 &&  \
         [string compare $orient "grid"] != 0) } {
        puts "Error $BADPARAM in \{$procname $frame_name\}: $errmsg(BADPARAM)"
        exit $BADPARAM
  }
  
  if { [string compare $frame_name "."] == 0 } {
       set frame_name ""	
  }

  if {[string compare $radiobox_labelstr ""] != 0} {
    message $frame_name.rlabel -font $LABELFONT -text $radiobox_labelstr \
	    -aspect 1000

    if {$place_labelstr_top} {
      pack $frame_name.rlabel -side top -anchor nw -pady $spacing
    } else {
      pack $frame_name.rlabel -side left -anchor nw -pady $spacing
    }
  }

  set i 1
  set allButtonsList ""
  foreach group [lrange $radiobutton_list 0 end] {

    frame $frame_name.$i
    label $frame_name.${i}_dummy -width 1 -font $LABELFONT -padx 1 -pady 1 
    eval pack "$frame_name.${i}_dummy" -side left -anchor nw
    eval pack "$frame_name.$i" -side top -anchor nw

    set buttonList ""
    set j 1
    foreach button_entry [lrange $group 0 end] {
      set buttonName  [lindex $button_entry 0]
      set buttonLabel [lindex $button_entry 1]
      set buttonAssoc [lindex $button_entry 2]

      if {[string compare $buttonAssoc ""] != 0} {

        if {$button_assoc_groove_relief} {  
	  frame $frame_name.$i.f$buttonName -borderwidth 2 -relief groove
        } else {
	  frame $frame_name.$i.f$buttonName
        }
        radiobutton $frame_name.$i.f$buttonName.$buttonName -relief flat -anchor c \
                  -font $LABELFONT -text $buttonLabel -padx 1 -pady 1
	if { $place_buttonAssoc_right && \
	     [regexp $selective_right_placement $j] } {
	  pack $frame_name.$i.f$buttonName.$buttonName -side left \
	       	-anchor nw
          pack $buttonAssoc -in $frame_name.$i.f$buttonName -side right \
		-anchor nw
	} else {
	  pack $frame_name.$i.f$buttonName.$buttonName -side top -anchor nw
          pack $buttonAssoc -in $frame_name.$i.f$buttonName -side bottom \
		-anchor nw
	}
        raise $buttonAssoc $frame_name.$i.f$buttonName
        append buttonList " " $frame_name.$i.f$buttonName
        append allButtonsList " " $frame_name.$i.f$buttonName.$buttonName
      } else {
        radiobutton $frame_name.$i.$buttonName -relief flat -anchor c \
                  -font $LABELFONT -text $buttonLabel -padx 1 -pady 1
        append buttonList " " $frame_name.$i.$buttonName
        append allButtonsList " " $frame_name.$i.$buttonName
      }	
      incr j
    }

    if { [string compare $orient "column"] == 0 } {
	eval pack "$buttonList" -side top -anchor nw -pady $spacing
    } else {
	eval pack "$buttonList" -side left -anchor nw -padx $spacing
    }
    incr i
    
  }
  if {[string compare $radiobox_labelstr ""] != 0} {
    return [concat $frame_name $allButtonsList $frame_name.rlabel]
  } else {
    return [concat $frame_name $allButtonsList]
  }
}
# disable_rcbutton: disables radio/check button.
proc disable_rcbutton button_name {
  global selColor disabledColor tk_version

  set state [lindex [$button_name configure -state] 4]
  if {[string compare $state "disabled"] == 0} {
    return		;# ignore if already disabled
  }

  if {$tk_version < 4.0} {
    set selColor($button_name) [lindex [$button_name configure -selector] 4]
    $button_name configure -state disabled -selector $disabledColor
  } else {
    set selColor($button_name) [lindex [$button_name configure -selectcolor] 4]
    $button_name configure -state disabled -selectcolor $disabledColor
  }

}

# enable_rcbutton: enables radio/check button.
proc enable_rcbutton button_name {
  global selColor tk_version

  set state [lindex [$button_name configure -state] 4]
  if {![info exists selColor($button_name)] || \
       [string compare $state "normal"] == 0} {
    return
  }

  if {$tk_version < 4.0} {
    $button_name configure -state normal -selector $selColor($button_name)
  } else {
    $button_name configure -state normal -selectcolor $selColor($button_name)
  }
}

# disable_button: disables a command button.
proc disable_button button_name {
  global disabledColor

  set state [lindex [$button_name configure -state] 4]

  if {[string compare $state "disabled"] == 0} {
    return		;# ignore if already disabled
  }

  $button_name configure -state disabled
}

# enable_button: enables a command button.
proc enable_button button_name {

  $button_name configure -state normal
}
# disable_rcbuttons: disables a list of radio/checkbuttons.
proc disable_rcbuttons {args} {
  foreach button $args {
    disable_rcbutton $button
  }
}

# enable_rcbuttons: enables a list of radio/checkbuttons.
proc enable_rcbuttons {args} {
  foreach button $args {
    enable_rcbutton $button
  }
}

# invoke_rbutton: for invoking an appropriately set  radio button.
proc invoke_rbutton {buttons} {

  global qsubv qalterv qsigv

  foreach button $buttons {
    $button configure -state normal
    set var [lindex [$button configure -variable] 4]
    set val [lindex [$button configure -value] 4]
 
    global $var

    if { [string compare [set $var] $val] == 0 } {
      $button invoke
    }
  }
}

# invoke_cbutton: for invoking an appropriately set check button.
proc invoke_cbutton {buttons} {
  global selColor tk_version

  foreach button $buttons {

    set state [lindex [$button configure -state]  4]

    enable_rcbutton $button
    $button toggle
    $button invoke

    if {[string compare $state "disabled"] == 0} {
	disable_rcbutton $button
    } 

  }
}
