
# This code creates the user interface for global.
#
# Copyright (c) 1993 - 1995 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Wayne A. Christopher, wayne@icemcfd.com

set all_scan_types "mesh blocks stair hgrid"
set one_plane_scantypes "blocks hgrid"
set ndim 3
proc mesh_scan_planes {} {
    global scan_major scan_minor scan_on scan_solid tool_dir last_line
    global subindex_min_limit subindex_max_limit guibase_dir scan_type
    global index_min_limit index_max_limit botform_geo scan_boundary
    global status_scan_type all_scan_types status_change_type
    global status_change_plane ndim scan_prev_type
    
    set buts {{Done {form_done .scanp; mesh_scan_done}}}
    
    set d [form_init .scanp "Scan plane control" mesh $buts]
    if {$d != ""} {
	form_frame $d.fr sunken 3 {0 0}; set d $d.fr
	
	foreach st $all_scan_types {
	    set status_scan_type($st) 0
	    set status_change_type($st) 0
	}
	
	set scan_type mesh
	set scan_prev_type mesh
	set status_scan_type(mesh) 1
	
	set up @$guibase_dir/goup.xbm
	set dn @$guibase_dir/godown.xbm
	
	form_frame $d.buts flat 0 {1 1 -cols 2}
	form_checkbutton $d.buts.solid "Solid" scan_solid {0 0} \
	    {{scan_type mesh blocks stair hgrid}}
	form_checkbutton $d.buts.bound "Boundary" scan_boundary {1 0} \
	    {{scan_type mesh}}
	form_radiobutton $d.buts.tmesh   Mesh   scan_type mesh {0 1}
	form_radiobutton $d.buts.tblocks Blocks scan_type blocks {1 1}
	form_radiobutton $d.buts.tstair  Stair  scan_type stair {2 1}
	form_radiobutton $d.buts.thgrid  H-grid scan_type hgrid {3 1}
	
	foreach i [winfo children $d.buts] {
	    $i configure -command scan_change_type
	}
	
	form_label $d.onl "On" {3 1}
	form_label $d.minorl "Minor" {3 7 -cols 3}
	form_frame $d.onul flat 2 {4 1 -pady 4 -anchor n}
	form_frame $d.minorul flat 2 {4 7 -cols 3 -pady 4 -anchor n}
	foreach i {onul minorul} { $d.$i configure -background black }
	
	for {set i 0} {$i < $ndim} {incr i} {
	    if ![info exists scan_minor($i)] { set scan_minor($i) 1 }
	    set status_change_plane($i) 0

	    set row [expr {$i + 5}]
	    form_checkbutton $d.on$i "# $i" scan_on($i) "$row 1"
	    $d.on$i configure -command "scan_on_minor $i" ;# should be $i
	    
	    form_entry $d.minor$i scan_minor($i) int "$row 7"
	    form_button_bitmap $d.minorup$i $up "scan_minor $i 1" "$row 8"
	    form_button_bitmap $d.minordn$i $dn "scan_minor $i -1" "$row 9"
	    
	    form_colwidth $d 2 4
	    form_colwidth $d 6 4
	}
	
	form_finish $botform_geo
    }
}

proc scan_minor {ind dir} {
    global index_min_limit index_max_limit scan_minor scan_on
    global scan_type status_change_type status_change_plane
    
    set minl $index_min_limit($ind)
    set maxl $index_max_limit($ind)
    incr scan_minor($ind) $dir
    set v $scan_minor($ind)
    set ch 1
    if {$v < $minl}  { set v $minl; set ch 0 }
    if {$v > $maxl}  { set v $maxl; set ch 0 }
    
    set do_update [expr ![info exists scan_on($ind)] || $scan_on($ind)]
    if {$ch && $do_update} {
	set status_change_type($scan_type) 1
	set status_change_plane($ind) 1
	set_minor_oneplane_scantypes $ind
	scan_update all
    }
    return $ch
}

proc scan_on_minor {ind} {
    global scan_type status_change_type status_change_plane
    
    set status_change_type($scan_type) 1
    set status_change_plane($ind) 1
    set_minor_oneplane_scantypes $ind
    
    scan_update all
}

proc scan_change_type {} {
    global scan_on scan_type scan_prev_type status_scan_type status_change_type
    global status_change_plane ndim one_plane_scantypes
    
    set status_scan_type($scan_prev_type) 0
    set status_change_type($scan_prev_type) 1
    
    for {set i 0} {$i < $ndim} {incr i} {
	set status_change_plane($i) 1
    }
    
    # If it is a one plane scantype, leave on only one plane
    
    if {[lsearch $one_plane_scantypes $scan_type] != -1} {
	
	# find first plane on
	
	set one_plane_on -1
	for {set i 0} {$i < $ndim} {incr i} {
	    if $scan_on($i) {
		set one_plane_on $i
		break;
	    }
	}
	
	# turn off everything else
	
	scan_update all
	
	# Now mark this type on and update the scan_on array
	
	set status_scan_type($scan_type) 1
	set status_change_type($scan_type) 1
	
	if {$one_plane_on != -1} {
	    set_minor_oneplane_scantypes $one_plane_on
	    scan_update $one_plane_on 0
	}
	
	# mark that the change status of all planes is now 0
	
	for {set i 0} {$i < $ndim} {incr i} {
	    set status_change_plane($i) 0
	}
	
    } else {
	
	# mark that scan type is now active and that we are
	# changing the status on that type only
    
	set status_scan_type($scan_type) 1
	set status_change_type($scan_type) 1
    
	scan_update all
    }
    
    # point the previous scan type to scan_type
    
    set scan_prev_type $scan_type
}

proc set_minor_oneplane_scantypes {ind} {
    global scan_type one_plane_scantypes status_change_type
    global status_change_plane status_scan_type scan_on ndim
    
    if {[lsearch $one_plane_scantypes $scan_type] != -1 &&
	$status_change_type($scan_type)} {
	
	# only one plane can be active at a time.  Just activate/
	# deactivate last plane selected.
	
	for {set i 0} {$i < $ndim} {incr i} {
	    if {$i == $ind} {
		set status_change_plane($i) 1
	    } else {
		set scan_on($i) 0
	    }
	}
    }
}
    
proc scan_update {ind {do_stair 1}} {
    global scan_minor scan_on scan_solid scan_boundary project_type scan_type
    global index_min index_max scan_prev_type hgrid_bbox last_line
    global status_scan_type all_scan_types status_change_type
    global status_change_plane ndim scan_last_ind
    
    if ![info exists scan_type] return
  
    if {$ind == "all"} {
	set uns_str ""
	set cur_scan_type $scan_type
	foreach st $all_scan_types {
	    if $status_change_type($st) {
		set scan_type $st
		set flag $status_scan_type($st)
		for {set i 0} {$i < $ndim} {incr i} {
		    if {[info exists scan_on($i)] && $status_change_plane($i)} {
			if !$flag {
			    set t $scan_on($i)
			    set scan_on($i) 0
			    scan_update $i
			    set scan_on($i) $t
			} else {
			    scan_update $i 0
			}
		    }
		}
		set status_change_type($st) 0
	    }
	}
	
	for {set i 0} {$i < $ndim} {incr i} {
	    set status_change_plane($i) 0
	}
	
	set scan_type $cur_scan_type
	
	if {$scan_type == "stair"} {
	    for {set i 0} {$i < $ndim} {incr i} {
		if {[info exists scan_on($i)] && $scan_on($i)} {
		    append uns_str " [range_string_sp2 $i $scan_minor($i)]"
		}
	    }
	    if {$uns_str != ""} {
		if $scan_solid { append uns_str " solid" }
		command "display_unstruct_quads [surface_string] $uns_str" 0
	    } else {
		command "display_unstruct_quads erase" 0
	    }
	}
	return
    }

    if {$ind == "last"} {
	if [info exists scan_last_ind] {
	    set ind $scan_last_ind
	} else {
	    set ind 0
	    set scan_on(0) 0
	}
    } else {
	set scan_last_ind $ind
    }
    switch "$scan_type $scan_on($ind)" {
	"mesh 1" {
	    set cmd "sp $ind $scan_minor($ind) [range_string]"
	    if $scan_solid { append cmd " solid" }
	    if $scan_boundary { append cmd " boundary" }
	    set fam [family_string]
	    if {$fam != ""} { append cmd " m $fam" }
	    command $cmd
	}
	"mesh 0" {
	    command "sp $ind erase"
	}
	"blocks 1" {
	    set cmd "dm [range_string_sp $ind $scan_minor($ind)]\
			m [volume_string] full"
	    if $scan_solid { append cmd " solid" }
	    command $cmd 0
	}
	"blocks 0" {
	    command "em" 0
	}
	"stair 1" {
	    if $do_stair {
		set cmd "display_unstruct_quads [surface_string]\
			[range_string_sp $ind $scan_minor($ind)]"
		if $scan_solid { append cmd " solid" }
		command $cmd 0
	    }
	}
	"stair 0" {
	    if $do_stair {
		command "display_unstruct_quads erase" 0
	    }
	}
	"hgrid 1" {
	    if ![info exists hgrid_bbox] hgrid_assign_bbox
	    set bmin [lindex [lindex $hgrid_bbox 0] $ind]
	    set bmax [lindex [lindex $hgrid_bbox 1] $ind]
	    set diff [expr {($bmax - $bmin) / 10.0}]
	    set val [expr {$bmin + $diff * $scan_minor($ind)}]
	    
	    set pl [lindex {x y z} $ind]
	    set opts "[surface_string] $pl $val"
	    if $scan_solid { append opts " solid" }
	    if [check_compute_hgrid] {
		command "display_hgrid $opts"
	    }
	}
	"hgrid 0" {
	    command "display_hgrid erase" 0
	}
    }
}

proc mesh_scan_done {} {
    global scan_major
    
    foreach i [array names scan_major] {
	command "sp erase \{ $i 0 0 \}" 0
    }
}

# ---------------------------------------------------------

proc mesh_index_planes {} {
    global iplane_list iplane_info iplane_on all_lines iplane_current
    global iplane_add_type iplane_add_ind iplane_add_val iplane_with_name
    global iplane_add_min iplane_add_max plane_add_name plane_add_family
    global iplane_name iplane_family iplane_fams form_entry_datatype
    
    set d [form_init .iplane "Index plane control" mesh done]
    if {$d != ""} {
	set iplane_add_type plane
	set iplane_add_ind 0
	set iplane_add_val 0
	set iplane_add_min "0 0 0"
	set iplane_add_max "1 1 1"
	
	form_frame $d.fr sunken 3 {0 0}; set d $d.fr
	
	form_frame $d.top flat 0 {0 0 -cols -}
	
	form_listbox $d.top.list "Current objects" "" iplane_set "" \
	    "8x8" {0 0 -rows 2}
	set iplane_list $d.top.list
	
	form_label $d.top.flab "Families" {0 1}
	form_frame $d.top.fams flat 0 {1 1}
	set iplane_fams $d.top.fams
	
	form_frame $d.c flat 0 {1 0 -cols -}
	form_button $d.c.add "Add" iplane_add {1 0}
	form_button $d.c.remove "Remove" iplane_remove {1 1}
	form_checkbutton $d.c.active "Active" iplane_active {1 2}
	$d.c.active configure -command iplane_active_update
	
	set act1 {{iplane_add_type plane}}
	set act2 {{iplane_add_type box}}
	#form_colwidth $d 0 4 M
	
	form_frame $d.n flat 0 {3 0 -cols -}
	#form_label $d.n.namel "Name:" {0 0}
	form_label $d.n.faml "Family:" {1 0}
	#form_entry $d.n.name iplane_add_name string {0 1}
	futil_listentry $d.n.fam iplane_add_family iplane_family_list {1 1}
	set form_entry_datatype($d.n.fam) string ;# HACK
	
	form_radiobutton $d.t_ind "Index plane" iplane_add_type plane \
	    {4 0 -cols -} "" iplane_current_objects
	form_frame $d.ind flat 0 {5 1 -cols -}
	form_label $d.ind.l Dir: {0 0} $act1
	form_radiobutton $d.ind.i I iplane_add_ind 0 {0 1} $act1
	form_radiobutton $d.ind.j J iplane_add_ind 1 {0 2} $act1
	form_radiobutton $d.ind.k K iplane_add_ind 2 {0 3} $act1
	form_frame $d.ind.val flat 0 {3 0 -cols 3}
	form_label $d.ind.vl Value: {1 0} $act1
	form_entry $d.ind.ve iplane_add_val int {1 1 -cols 2} $act1
	
	form_radiobutton $d.t_box "Index box" iplane_add_type box \
	    {6 0 -cols -} "" iplane_current_objects
	form_frame $d.box flat 0 {7 1 -cols -}
	form_label $d.box.minl Min: {0 0} $act2
	form_label $d.box.maxl Max: {1 0} $act2
	form_entry $d.box.min iplane_add_min string {0 1} $act2
	form_entry $d.box.max iplane_add_max string {1 1} $act2
	
	foreach i "$d.n.fam $d.ind.ve $d.box.min $d.box.max" {
	    bind $i <Return> iplane_add
	}
	
	form_button $d.box.mins "Select" "iplane_add_set min" {0 2} $act2
	form_button $d.box.maxs "Select" "iplane_add_set max" {1 2} $act2
	
	form_button $d.setcol "Set color" iplane_set_color {10 0 -cols -}

	update_index_planes
	
	form_finish bot
    }
    if ![info exists iplane_current] { set iplane_current "" }
}

proc iplane_all_planes {} {
    global all_lines
    
    command list_index_planes 0
    set opts ""
    foreach p $all_lines {
	if {[scan $p "%d : %d %d %s" num dir ind name] == 4} {
	    lappend opts [list $num $dir $ind $name]
	}
    }
    return $opts
}

proc iplane_all_boxes {} {
    global all_lines
    
    command list_index_boxes 0
    set opts ""
    foreach p $all_lines {
	if {[scan $p "%d : %d %d %d %d %d %d %s" \
		 num imin jmin kmin imax jmax kmax name] == 8} {
	    lappend opts [list $num $imin $jmin $kmin $imax $jmax $kmax $name]
	}
    }
    return $opts
}

proc init_index_planes {} {
    global iplane_info iplane_name iplane_with_name
    global iplane_family iplane_on
    
    foreach p [iplane_all_planes] {
	set num "plane [lindex $p 0]"
	set dir [lindex $p 1]
	set ind [lindex $p 2]
	set name [lindex $p 3]
	
	set iplane_info($num) "[lindex {i j k} $dir]=$ind"
	set iplane_name($num) $name
	set iplane_with_name($name) $num
	set iplane_family($num) [lindex [split $name /] 0]
	if [info exists iplane_list] {
	    form_listbox_add $iplane_list $iplane_name($num)
	}
	if ![info exists iplane_on($num)] {
	    set iplane_on($num) 0
	}
    }

    foreach p [iplane_all_boxes] {
	set num "box [lindex $p 0]"
	set imin [lindex $p 1]
	set jmin [lindex $p 2]
	set kmin [lindex $p 3]
	set imax [lindex $p 4]
	set jmax [lindex $p 5]
	set kmax [lindex $p 6]
	set name [lindex $p 7]
	
	set iplane_info($num) "$imin,$jmin,$kmin->$imax,$jmax,$kmax"
	set iplane_name($num) $name
	set iplane_with_name($name) $num
	set iplane_family($num) [lindex [split $name /] 0]
	if [info exists iplane_list] {
	    form_listbox_add $iplane_list $iplane_name($num)
	}
	if ![info exists iplane_on($num)] {
	    set iplane_on($num) 0
	}
    }
}

proc update_index_planes {} {
    init_index_planes
    iplane_update_families
}

proc iplane_family_list {} {
    global families family_name iplane_family
    
    foreach f $families {
	set fams($family_name($f)) 1
    }
    foreach n [array names iplane_family] {
	set fams($iplane_family($n)) 1
    }
    return [lsort [array names fams]]
}

proc iplane_add_set {which} {
    global iplane_add_$which
    
    set banner "Select the corner nodes with the left button; \
 middle = done, right = cancel."
    set last_line [select_node $banner node 2]
    set n [lindex $last_line 0]
    if {$n == ""} return
    
    set iplane_add_$which $n
}

proc iplane_update {which} {
    update_index_planes
    # Not much to do.
}

proc iplane_set {name} {
    global iplane_current iplane_on iplane_active iplane_info iplane_list
    global iplane_name
    
    set iplane_current ""
    foreach i [array names iplane_name] {
	if {$iplane_name($i) == $name} {
	    set iplane_current $i
	    break
	}
    }
    if {$iplane_current != ""} {
	set iplane_active $iplane_on($iplane_current)
	form_listbox_select $iplane_list $name
    }
}

proc iplane_set_color {} {
    global iplane_current iplane_name last_line iplane_info
    
    if {$iplane_current == ""} {
	mess "No index plane or box selected\n" red
	return
    }
    set what [lindex $iplane_current 0]
    set name [lindex $iplane_current 1]
    
    command "set_index_${what}_color $name"
    set col $last_line
    set col [edit_one_color "Please define the color to use\
	    for the index plane." $col]
    if {$col == ""} return
    set c [string range $col 5 6][string range $col 3 4][string range $col 1 2]
    command "set_index_${what}_color $name $c"
}

proc iplane_add {} {
    global iplane_current iplane_add_ind iplane_add_val iplane_list
    global iplane_info last_line iplane_on iplane_name iplane_family
    global iplane_add_type iplane_add_min iplane_add_max iplane_with_name
    global iplane_add_name iplane_add_family
    
    switch $iplane_add_type {
	plane {
	    set info "[lindex {i j k} $iplane_add_ind]=$iplane_add_val"
	}
	box {
	    foreach i {0 1 2} {
		set [lindex {i j k} $i]min [lindex $iplane_add_min $i]
		set [lindex {i j k} $i]max [lindex $iplane_add_max $i]
	    }
	    set info "$imin,$jmin,$kmin->$imax,$jmax,$kmax"
	}
	default { error "bad type" }
    }
    
    #set name $info
    for {set i 0} {[info exists iplane_with_name($iplane_add_family/$i)]} \
	{incr i} {}
    set name $iplane_add_family/$i
    
    switch $iplane_add_type {
	plane {
	    command "define_index_plane $iplane_add_ind $iplane_add_val \
		$name $iplane_add_family"
	    if [regexp error $last_line] return
	    set n "plane $last_line"
	}
	box {
	    command "define_index_box $imin $jmin $kmin $imax $jmax $kmax \
		$name $iplane_add_family"
	    set n "box $last_line"
	}
    }
    set iplane_info($n) $info
    set iplane_name($n) $name
    set iplane_with_name($name) $n
    set iplane_family($n) $iplane_add_family
    
    iplane_update_families
    
    form_listbox_add $iplane_list $iplane_name($n)
    
    set iplane_on($n) 1
    command "display_index_[lindex $n 0] [lindex $n 1]"
    iplane_set $iplane_info($n)
}

proc iplane_remove {} {
    global iplane_current iplane_name iplane_info iplane_family iplane_list
    global iplane_with_name
    
    if {$iplane_current == ""} return
    
    set n $iplane_current
    command "delete_index_[lindex $n 0] [lindex $n 1]"
    # form_listbox_delete $iplane_list $iplane_name($n)
    unset iplane_info($n)
    unset iplane_with_name($iplane_name($n))
    unset iplane_name($n)
    unset iplane_family($n)
    set iplane_current ""
    
    iplane_update_families
}

proc iplane_active_update {{n ""} {on ""} {redraw "redraw"} {local_only 0}} {
    global iplane_active iplane_current iplane_on
    
    if {$n == ""} {
	if {$iplane_current == ""} return
	set n $iplane_current
    }
    
    if {$on == ""} {
	set iplane_on($n) $iplane_active
	set on $iplane_active
    } elseif !$local_only {
	set iplane_on($n) $on
    }
    
    if $on {
	command "display_index_[lindex $n 0] [lindex $n 1] $redraw" 0
    } else {
	command "erase_index_[lindex $n 0] [lindex $n 1] $redraw" 0
    }
}

proc iplane_current_families {} {
    global iplane_family
    
    set ret ""
    if [info exists iplane_family] {
	foreach n [array names iplane_family] {
	    set fam $iplane_family($n)
	    if {[lsearch $ret $fam] < 0} { lappend ret $fam }
	}
    }
    return [lsort $ret]
}

proc iplane_update_families {} {
    global iplane_fams iplane_family iplane_family_active
    
    if ![info exists iplane_fams] return
    
    set cur_fams [iplane_current_families]
    set opts ""
    foreach n $cur_fams {
	if {$n != ""} {
	    lappend opts "$n -command \{iplane_update_family \{$n\}\}"
	    if ![info exists iplane_family_active($n)] {
		set iplane_family_active($n) 0
	    }
	}
    }
    check_box $iplane_fams $opts 8 iplane_family_active 1 \
	iplane_update_families_all
    
    # Make the global box correct
    
    add_new_families
}

# fill out the current object's box

proc iplane_current_objects {} {
    global iplane_list iplane_family_active
    
    # get current list of iplane_add_type's
    
    if {![info exist iplane_list]} return
    
    # pass 1 -- extract all families and all objects from list
    
    set obj_fam_list ""
    foreach e [iplane_all_planes] {
	set name [lindex $e 3]
	set fam [lindex [split $name /] 0]
	lappend obj_fam_list [list $fam $name]
    }
    
    foreach e [iplane_all_boxes] {
	set name [lindex $e 7]
	set fam [lindex [split $name /] 0]
	lappend obj_fam_list [list $fam $name]
    }
    
    # pass 2 - put all objects that belong to the same family together
    
    set all_fams ""
    catch {unset all_objs}
    
    foreach e $obj_fam_list {
	set fam [lindex $e 0]
	set name [lindex $e 1]
	set idx [lsearch $all_fams $fam]
	if {$idx >= 0} {
	    lappend all_objs($idx) $name
	} else {
	    set idx [llength $all_fams]
	    lappend all_fams $fam
	    set all_objs($idx) $name
	}
    }
    
    # pass 3 - put all objects for active families into list box
    
    form_listbox_clear $iplane_list
    
    set cur_fams [iplane_current_families]
    set opts ""
    foreach n $cur_fams {
	if {$n != ""} {
	    if ![info exists iplane_family_active($n)] {
		set iplane_family_active($n) 0
	    } elseif $iplane_family_active($n) {
		set idx [lsearch $all_fams $n]
		if {$idx >= 0} {
		    foreach e $all_objs($idx) {
			form_listbox_add $iplane_list $e
		    }
		}
	    }
	}
    }
}

proc iplane_update_family {fam} {
    global iplane_family iplane_family_active iplane_list
    
    set on $iplane_family_active($fam)
    foreach n [array names iplane_family] {
	if {$iplane_family($n) == $fam} {
	    iplane_active_update $n $on
	}
    }
    iplane_current_objects
}

proc iplane_update_families_all {{action 1}} {
    global iplane_family iplane_family_active
    
    command "redraw_flag 0" 0
    
    # default value of on is the action value
    
    set on $action
    foreach n [array names iplane_family] {
	
	# carry out update action
	
	catch {
	    switch $action {
		delete {
		    # deleting all boxes/planes
		
		    set on 0
		}
		off -
		0 {
		    # turning all planes/boxes off
		
		}
		1 -
		default {
		    # standard action is to display active families
		
		    set on $iplane_family_active($iplane_family($n))
		}
	    }
	    
	    iplane_active_update $n $on "-noredraw"
	    if {$action == "delete"} {
		iplane_remove $n
	    }
	}
    }
    iplane_current_objects
    command "redraw_flag 1" 0
}

# ---------------------------------------------------------

proc mesh_slice_planes {} {
    
    global slice_plane_add_ind slice_plane_list
    global slice_plane_add_family slice_plane_do_compute
    global slice_plane_nsl slice_plane_np slice_plane_tol
    global form_entry_datatype slice_plane_ind_brflag slice_plane_brflag
    
    set d [form_init .slice_plane "Slice plane control" mesh done]
    if {$d != ""} {
	form_frame $d.fr sunken 3 {0 0}; set d $d.fr
	
	form_frame $d.top flat 0 {0 0 -cols -}
	
	form_listbox $d.top.list "Current objects" "" slice_plane_set "" \
	    "8x8" {0 0 -rows 2}
	set slice_plane_list $d.top.list
	
	form_frame $d.c flat 0 {1 0 -cols -}
	form_button $d.c.add "Add" slice_plane_add {1 0}
	form_button $d.c.remove "Remove" slice_plane_remove {1 1}
	form_checkbutton $d.c.active "Compute Slices" slice_plane_do_compute {1 2}
	set slice_plane_do_compute 0
	
	form_frame $d.n flat 0 {3 0 -cols -}
	#form_label $d.n.namel "Name:" {0 0}
	form_label $d.n.faml "Family:" {1 0}
	#form_entry $d.n.name iplane_add_name string {0 1}
	futil_listentry $d.n.fam slice_plane_add_family \
	    slice_plane_family_list {1 1}
	set form_entry_datatype($d.n.fam) string ;# HACK
	
	form_frame $d.geo flat 0 {4 0 -cols -}
	form_label $d.geo.br "Indent Geo.:" {1 0}
	form_radiobutton $d.geo.brn  "None" slice_plane_brflag 0 {1 1}
	form_radiobutton $d.geo.brmn "Min"  slice_plane_brflag 1 {1 2}
	form_radiobutton $d.geo.brmx "Max"  slice_plane_brflag 2 {2 1}
	form_radiobutton $d.geo.brbo "Both" slice_plane_brflag 3 {2 2}
	set slice_plane_brflag 0;
	
	form_frame $d.ind flat 0 {6 0 -cols -}
	form_label $d.ind.dir Dir: {0 0}
	form_radiobutton $d.ind.i X slice_plane_add_ind 0 {0 1}
	form_radiobutton $d.ind.j Y slice_plane_add_ind 1 {0 2}
	form_radiobutton $d.ind.k Z slice_plane_add_ind 2 {0 3}
	form_label $d.ind.nsl "Num. Slices:" {1 0}
	form_entry $d.ind.nslex slice_plane_nsl(0) int {1 1 -cols 2}
	form_entry $d.ind.nsley slice_plane_nsl(1) int {1 2 -cols 2}
	form_entry $d.ind.nslez slice_plane_nsl(2) int {1 3 -cols 2}
	form_label $d.ind.np "Num. Points:" {2 0}
	form_entry $d.ind.npex slice_plane_np(0) int {2 1 -cols 2}
	form_entry $d.ind.npey slice_plane_np(1) int {2 2 -cols 2}
	form_entry $d.ind.npez slice_plane_np(2) int {2 3 -cols 2}
	form_label $d.ind.tol "Tolerance:" {3 0}
	form_entry $d.ind.tolex slice_plane_tol(0) int {3 1 -cols 2}
	form_entry $d.ind.toley slice_plane_tol(1) int {3 2 -cols 2}
	form_entry $d.ind.tolez slice_plane_tol(2) int {3 3 -cols 2}
	set slice_plane_add_ind 0;
	
	for {set i 0} {$i < 3} {incr i} {
	    set slice_plane_ind_brflag($i) 0
	    set slice_plane_nsl($i) 3
	    set slice_plane_np($i) 3
	    set slice_plane_tol($i) 0.01
	}
		
	foreach i "$d.geo.brn $d.geo.brmn $d.geo.brmx $d.geo.brbo $d.c.active" {
	    $i configure -command "slice_plane_add"
	}
	
	foreach j "x y z" {
	    bind $d.ind.tole$j slice_plane_add
	    foreach i "$d.ind.nsle $d.ind.npe" {
		bind $i$j <Return> slice_plane_active
	    }
	}
	
	form_finish bot
    }
    if ![info exists slice_plane_current] { set slice_plane_current "" }
}

proc slice_plane_family_list {} {
    global families family_name slice_plane_family
    
    set slice_plane_families ""
    foreach f $families {
	set fams($family_name($f)) 1
	lappend slice_plane_families $f
    }
    return [lsort [array names fams]]
}

proc slice_plane_compute {do_compute} {
    global slice_plane_ind_brflag slice_plane_name slice_plane_tol
    global slice_plane_dim slice_plane_family_name slice_plane_nsl
    global slice_plane_np
    
    if $do_compute {
	set slice_plane_bingeo ""
	
	for {set i 0} {$i < 3} {incr i} {
	    set com_families($i) ""
	}
	
	foreach j [array names slice_plane_name] {
	    set i $slice_plane_dim($j)
	    set com_dim "-[lindex {i j k} $i]"
	    lappend com_families($i) $slice_plane_family_name($j) $com_dim
	}
	
	set atLeastOne 0
	for {set i 0} {$i < 3} {incr i} {
	    switch $slice_plane_ind_brflag($i) {
		1 {
		    set slice_plane_bingeo "-binmin"
		}
		2 {
		    set slice_plane_bingeo "-binmax"
		}
		3 {
		    set slice_plane_bingeo "-binboth"
		}
		0 -
		default {
		}
	    }
	    set com_flags "-tol $slice_plane_tol($i) $slice_plane_bingeo"
	    if {$com_families($i) != ""} {
		set slice_plane_com_line($i) "$com_flags $com_families($i)"
		set atLeastOne 1
	    } else {
		catch {unset slice_plane_com_line($i)}
	    }
	    
	    set plane [lindex {i j k} $i]
	    command "set_planespoints_slices -$plane $slice_plane_nsl($i) \
$slice_plane_np($i)" 0
	}
	
	if $atLeastOne {
	    set first 1
	    foreach j [array names slice_plane_com_line] {
		if $first {
		    set appendFlag ""
		    set first 0
		} else {
		    set appendFlag "-append"
		}
		command \
		    "compute_slices $appendFlag $slice_plane_com_line($j)" 0
	    }
	} else {
	    mess "No slice families selected\n" red
	}
    }
    update_display slice
}

proc slice_plane_set {name} {
    global slice_plane_current slice_plane_list
    global slice_plane_name
    
    set slice_plane_current ""
    foreach i [array names slice_plane_name] {
	if {$slice_plane_name($i) == $name} {
	    set slice_plane_current $i
	    break
	}
    }
    if {$slice_plane_current != ""} {
	form_listbox_select $slice_plane_list $name
    }
}

proc slice_plane_add {} {
    global slice_plane_current slice_plane_add_ind
    global slice_plane_list slice_plane_name slice_plane_family_name
    global slice_plane_do_compute slice_plane_dim slice_plane_brflag
    global slice_plane_add_family slice_plane_ind_brflag
    
    set add_plane "$slice_plane_add_family/[lindex {X Y Z} \
$slice_plane_add_ind]"
    if {![info exists slice_plane_name($add_plane)]} {
	set slice_plane_name($add_plane) $add_plane
	set slice_plane_family_name($add_plane) $slice_plane_add_family
	set slice_plane_dim($add_plane) $slice_plane_add_ind
    }
    
    form_listbox_add $slice_plane_list $add_plane
    set slice_plane_current $add_plane
    set slice_plane_ind_brflag($slice_plane_add_ind) $slice_plane_brflag
    slice_plane_compute $slice_plane_do_compute
}

proc slice_plane_remove {} {
    global slice_plane_current slice_plane_name
    global slice_plane_list slice_plane_family_name slice_plane_dim
    global slice_plane_do_compute
    
    if {$slice_plane_current == ""} return
    
    set n $slice_plane_current
    form_listbox_delete $slice_plane_list $slice_plane_name($n)
    
    unset slice_plane_name($n)
    unset slice_plane_family_name($n)
    unset slice_plane_dim($n)
    set slice_plane_current ""
    
    slice_plane_compute $slice_plane_do_compute
}

proc slice_plane_active {} {
    global slice_plane_do_compute
    slice_plane_compute $slice_plane_do_compute
}
