
# 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

proc edit_family_dim {staircase_type} {
    switch $staircase_type {
	volume { set ndim 3 }
	quad   { set ndim 2 }
	bar    { set ndim 1 }
	default { set ndim 0 }
    }
    return $ndim
}

proc edit_add_stair {staircase_type} {
    global families family_name family_dims
    
    if {$staircase_type == "volume"} {
	error "Operation not possible on volume elements."
    }
    set fnames ""
    set ndim [edit_family_dim $staircase_type]
    foreach f $families {
	if [info exists family_name($f)] {
	    if {$family_dims($f) == $ndim} {
		lappend fnames $family_name($f)
	    }
	}
    }
    
    set fam [choose_one "Pick a family for the new\
		$staircase_type element." $fnames]
    if {$fam == ""} return
    check_new_family $fam $ndim
    
    while 1 {
	set banner "Select two corners with the left button;\
		middle = done, right = back up / cancel."
	set last_line [select_node $banner node 2]
	if {[llength $last_line] != 2} return
	
	command "add_staircase_$staircase_type $last_line $fam"
	update_display block quad edge scan
    }
}

proc edit_del_stair {staircase_type what} {
    global index_min index_max families family_active family_name
    global display_flag
    
    if {$staircase_type == "volume"} {
	error "Operation not possible on volume elements."
    }
    
    set quad_opts ""
    set do_quad 0
    set do_edge 0
    if {$staircase_type == "quad"} {
	set do_quad 1
	switch $what {
	    all_un { lappend quad_opts "-unneeded" }
	    all    { lappend quad_opts "-quads" }
	    sel_a - sel_a_un - sel_v - sel_v_un - vis - vis_un {
		if $display_flag(quad) {
		    if {$what == "sel_a_un" || $what == "sel_v_un" ||
			$what == "vis_un"} {
			lappend quad_opts "-unneeded"
		    } else {
			lappend quad_opts "-quads"
		    }
		} else {
		    # visible option set but nothing is visible
		    set do_quad 0
		}
	    }
	    default { set quad_opts "-quads" }
	}
		    
	if {$display_flag(edge) && \
		$display_flag(edge_dispval_modal) == "edges_quads"} {
	    lappend quad_opts "-edges"
	    set do_edge 1
	}
    } else {
	set do_edge 1
	switch $what {
	    sel_a - sel_v - vis {
		if !$display_flag(edge) { set do_edge 0 }
	    }
	    default {}
	}		    
    }
    
    if {!$do_quad && !$do_edge} {
	set message "No Quads and/or Edges Visible!"
	tk_dialog .qe_visible "No Visibility" $message "" 0 Ok
	return
    }
	
	
    # if need to do the flood fill staircase, do it here
    
    switch $what {
	all_un - vis_un - sel_v_un - sel_a_un {
	    if ![flood_fill_exec 1 1] return
	}
	
	default {
	}
    }
    
    if $display_flag(quad_autofix) {
	set message "Autofix flag currently on.  Turn it off?"
	set display_flag(quad_autofix) \
	    [tk_dialog .auto_flag "Autofix Flag" $message "" 0 Yes No]
    }
    set base_cmd "delete_staircase_${staircase_type}s $quad_opts"
    switch $what {
	all - all_un {
	    set message "Really delete all staircase elements"
	    if {$do_edge && !$do_quad} {
		append message " obeying edge/quad criteria specified"
	    }
	    append message " of type $staircase_type?"
	    if [tk_dialog .delete_all "Delete all" \
		    $message "" -1 Yes No] return
	    command "$base_cmd -all"
	    update_display
	}
	vis - vis_un {
	    set cmd "$base_cmd \
		\{ $index_min(0) $index_min(1)  $index_min(2) \} \
		\{ $index_max(0) $index_max(1)  $index_max(2) \}"
	    foreach f $families {
		if $family_active($f) { append cmd " $family_name($f)" }
	    }
	    command $cmd
	    update_display
	}
	fam { not currently used
	    set cmd "$base_cmd $family"
	    foreach f $families {
		if $family_active($f) { append cmd " $family_name($f)" }
	    }
	    command $cmd
	    update_display
	}
	sel_v -
	sel_a -
	sel_v_un -
	sel_a_un {
	    
	    if {$what == "sel_a" || $what == "sel_a_un"} {
		set vis_only 0
	    } else {
		set vis_only 1
	    }
	    while 1 {
		set banner \
		    "Select the elements to delete with the left button;\
		middle = accept, right = cancel."
		set last_line [select_node $banner $staircase_type 2 $vis_only]
		if {[llength $last_line] != 2} return
		
		set n1 [lindex $last_line 0]; set n2 [lindex $last_line 1]
		set opts ""
		set cmd "$base_cmd \{ $n1 \} \{ $n2 \} "
		if {$what == "sel_v" || $what == "sel_un"} {
		    foreach f $families {
			if $family_active($f) {
			    append cmd " $family_name($f)"
			}
		    }
		}
		command $cmd
		update_display block quad edge scan
	    }
	}
    }
}

proc edit_rebuild_stair {} {
    command "display_unstruct_quads -rebuild" 0
    update_display quad
}

proc edit_repair_stair {} {
    global display_flag
    
    if {!$display_flag(quad_marking) && !$display_flag(quad_showcre)} {
	command "flood_fill_staircase -erase" 0
    }
    
    if {$display_flag(quad_ff_type) == "-none"} {
	set display_flag(quad_ff_type) "-standard"
    }
    
    # don't update display in flood_fill_exec because for delete
    # we don't want to update until after the delete of the quads
    
    if [flood_fill_exec 1 1] {
	update_display block quad edge scan
    }
}

proc edit_display_unneeded {} {
    global display_flag
    
    if [flood_fill_exec 1 1] { 
	set opts "[surface_string] [range_string]"
	if $display_flag(quad_solid) {
	    append opts " solid"
	} elseif $display_flag(quad_hidden) {
	    append opts " hidden"
	}
	if $display_flag(quad_unneeded) {
	    append opts " -onlyunneeded"
	} else {
	    append opts " -unneeded"
	}
	command "display_unstruct_quads $opts"
    }
}

proc edit_delete_unneeded {} {
    global index_min index_max
    
    if [flood_fill_exec 1 1] {
	set cmd "delete_staircase_quads -unneeded "
	append cmd "\{ $index_min(0) $index_min(1)  $index_min(2) \} \
 \{ $index_max(0) $index_max(1)  $index_max(2) \} [family_string]"
	command $cmd
	update_display block quad edge scan
    }
}

proc edit_repair_dispquad {} {
    global display_flag
    
    set display_flag(quad) 1
    update_display block quad edge scan
}

proc edit_repair_erase {} {
    command "flood_fill_staircase -erase"
}

proc edit_change_stair {staircase_type} {
    global families family_name family_dims
    
    set fnames ""
    set ndim [edit_family_dim $staircase_type]
    set search_for_dim $ndim
    if {$staircase_type == "volume"} {
	foreach f $families {
	    if [info exists family_name($f)] {
		if {$family_dims($f) == $ndim} {
		    lappend fnames $family_name($f)
		}
	    }
	}
	set vfam [choose_one "Pick new volume family for elements" $fnames]
	if {$vfam == ""} return
	check_new_family $vfam 3
	
	set search_for_dim 2
    }
    
    set fnames ""
    foreach f $families {
	if [info exists family_name($f)] {
	    if {$family_dims($f) == $search_for_dim} {
		lappend fnames $family_name($f)
	    }
	}
    }
    if {$staircase_type == "volume"} {
	set msg "Pick a new surface family for the adjoining quad elements"
    } else {
	set msg "Pick a new surface family for the $staircase_type elements"
    }
    set fam [choose_one $msg $fnames]
    if {$fam == ""} return
    check_new_family $fam $search_for_dim
    
    while 1 {
	set banner "Select two corners with the left button;\
		middle = done, right = back up / cancel."
	set last_line [select_node $banner $staircase_type 2]
	if {[llength $last_line] != 2} return
	
	switch $staircase_type {
	    quad   { command "change_staircase_family $last_line $fam" }
	    bar    { command "change_staircase_bars $last_line $fam" }
	    volume { command "change_element_ids $last_line $vfam $fam" }
	}
	update_display
	banner ""
    }
}

proc change_family_color {} {
    global last_line
    
    set fam [pick_family]
    if {$fam == ""} return
    
    command "change_family_color $fam"
    set cur "\#$last_line"
    set col [edit_one_color "Please define the $fam family color." $cur]
    if {$col == ""} return
    
    if {[scan $col \#%2x%2x%2x r g b] != 3} {
	mess "Bad color $col\n" red
	return
    }
    command "change_family_color $fam [format %2.2x%2.2x%2.2x $b $g $r]"
    update_display
}

proc pick_family {} {
    global families family_name selected_family
    
    set fams ""
    foreach f $families {
	lappend fams [list $f -text $family_name($f)]
    }
    
    if ![check_box_form .family_selection "Select a family" $fams 6 \
	     selected_family 0] {
		 return ""
	     } else {
		 return $family_name($selected_family)
	     }
}

proc edit_define_line {} {
    global define_data form_entry_datatype
    
    set buts [list "Create edit_define_line_create" done]
    set d [form_init .def_line "Define line" edit $buts]
    if {$d != ""} {
	foreach i {x1 y1 z1 x2 y2 z2} {
	    set define_data($i) 0.0
	}
	foreach i {i1 j1 k1 i2 j2 k2} {
	    set define_data($i) 0
	}
	set define_data(type) pos
	set define_data(family) [lindex [family_choice_list] 0]
	set define_data(name) ""
	
	form_label $d.faml Family {0 0 -cols 2}
	futil_listentry $d.fam define_data(family) family_choice_list {0 2}
	set form_entry_datatype($d.fam) string ;# HACK
	#form_label $d.namel Name {1 0 -cols 2}
	#form_entry $d.name define_data(name) string {1 2}
	form_radiobutton $d.bypos "By position" define_data(type) pos \
	    {10 0 -cols -}
	form_radiobutton $d.byind "By indices" define_data(type) ind \
	    {20 0 -cols -}
	form_colwidth $d 0 4 M
	
	set act {{define_data(type) pos}}
	form_label $d.x1l "Point1 X" {11 1} $act
	form_label $d.y1l "Point1 Y" {12 1} $act
	form_label $d.z1l "Point1 Z" {13 1} $act
	form_label $d.x2l "Point2 X" {14 1} $act
	form_label $d.y2l "Point2 Y" {15 1} $act
	form_label $d.z2l "Point2 Z" {16 1} $act
	
	form_entry $d.x1 define_data(x1) float {11 2} $act
	form_entry $d.y1 define_data(y1) float {12 2} $act
	form_entry $d.z1 define_data(z1) float {13 2} $act
	form_entry $d.x2 define_data(x2) float {14 2} $act
	form_entry $d.y2 define_data(y2) float {15 2} $act
	form_entry $d.z2 define_data(z2) float {16 2} $act
	
	set act {{define_data(type) ind}}
	form_label $d.i1l "Point1 I" {21 1} $act
	form_label $d.j1l "Point1 J" {22 1} $act
	form_label $d.k1l "Point1 K" {23 1} $act
	form_label $d.i2l "Point2 I" {24 1} $act
	form_label $d.j2l "Point2 J" {25 1} $act
	form_label $d.k2l "Point2 K" {26 1} $act
	
	form_entry $d.i1 define_data(i1) int {21 2} $act
	form_entry $d.j1 define_data(j1) int {22 2} $act
	form_entry $d.k1 define_data(k1) int {23 2} $act
	form_entry $d.i2 define_data(i2) int {24 2} $act
	form_entry $d.j2 define_data(j2) int {25 2} $act
	form_entry $d.k2 define_data(k2) int {26 2} $act
	
	form_button $d.sel1 Select "define_ijk_select 1" {21 3 -rows 3 -anchor nw -fill none} $act
	form_button $d.sel2 Select "define_ijk_select 2" {24 3 -rows 3 -anchor nw -fill none} $act
	
	form_finish bot
    }
}

proc edit_define_line_create {} {
    global define_data
    
    set cmd "define_line"
    switch $define_data(type) {
	pos {
	    foreach i {x1 y1 z1 x2 y2 z2} { append cmd " $define_data($i)" }
	}
	ind {
	    append cmd " indices"
	    foreach i {i1 j1 k1 i2 j2 k2} { append cmd " $define_data($i)" }
	}
    }
    if {$define_data(family) != ""} {
	append cmd " family $define_data(family)"
    }
    command $cmd
    update_display curve
    
    add_families
}

proc edit_define_point {} {
    global define_data form_entry_datatype
    
    set buts [list "Create edit_define_point_create" done]
    set d [form_init .def_point "Define point" edit $buts]
    if {$d != ""} {
	foreach i {x1 y1 z1} {
	    set define_data($i) 0.0
	}
	foreach i {i1 j1 k1} {
	    set define_data($i) 0
	}
	set define_data(type) pos
	set define_data(family) [lindex [family_choice_list] 0]
	set define_data(name) ""
	
	form_label $d.faml Family {0 0 -cols 2}
	futil_listentry $d.fam define_data(family) family_choice_list {0 2}
	set form_entry_datatype($d.fam) string ;# HACK
	#form_label $d.namel Name {1 0 -cols 2}
	#form_entry $d.name define_data(name) string {1 2}
	form_radiobutton $d.bypos "By position" define_data(type) pos \
	    {10 0 -cols -}
	form_radiobutton $d.byind "By indices" define_data(type) ind \
	    {20 0 -cols -}
	form_colwidth $d 0 4 M
	
	set act {{define_data(type) pos}}
	form_label $d.x1l "Point X" {11 1} $act
	form_label $d.y1l "Point Y" {12 1} $act
	form_label $d.z1l "Point Z" {13 1} $act
	
	form_entry $d.x1 define_data(x1) float {11 2} $act
	form_entry $d.y1 define_data(y1) float {12 2} $act
	form_entry $d.z1 define_data(z1) float {13 2} $act
	
	set act {{define_data(type) ind}}
	form_label $d.i1l "Point I" {21 1} $act
	form_label $d.j1l "Point J" {22 1} $act
	form_label $d.k1l "Point K" {23 1} $act
	
	form_entry $d.i1 define_data(i1) int {21 2} $act
	form_entry $d.j1 define_data(j1) int {22 2} $act
	form_entry $d.k1 define_data(k1) int {23 2} $act
	
	form_button $d.sel1 Select "define_ijk_select 1" {21 3 -rows 3 -anchor nw -fill none} $act
	
	form_finish bot
    }
}

proc edit_define_point_create {} {
    global define_data
        
    set cmd "define_point "
    switch $define_data(type) {
	pos {
	    foreach i {x1 y1 z1} { append cmd " $define_data($i)" }
	}
	ind {
	    append cmd " indices"
	    foreach i {i1 j1 k1} { append cmd " $define_data($i)" }
	}
    }
    if {$define_data(family) != ""} {
	append cmd " family $define_data(family)"
    }
    if {$define_data(name) != ""} {
	append cmd " name $define_data(name)"
    }
    command $cmd
    update_display point
    
    add_families
}

proc define_ijk_select {num} {
    global define_data 
    
    set banner \
	"Select a node for point $num with the left button; \
 middle = accept, right = cancel."
    set last_line [select_node $banner node 2]
    set n [lindex $last_line 0]
    if {$n == ""} return
    
    foreach i {0 1 2} {
	set define_data([lindex {i j k} $i]$num) [lindex $n $i]
    }
}

proc edit_delete_geo {what} {
    global last_line
    
    set ch [select_$what "Select the $what with the left button; \
 middle = accept, right = cancel."]
    if {$ch == ""} return
    command "delete_$what $ch"
    
    # display the change
    
    if {$what == "line"} {
	update_display curve
    } elseif {$what == "point"} {
	update_display point
    }
}

proc mirror_staircase {} {
    global global_options
    
    set d [form_init .mirror_stair "Mirror staircase" ""]
    if {$d != ""} {
	form_label $d.dirl "Direction" {0 0}
	form_label $d.vall "Value" {1 0}
	form_label $d.about "Reflect about" {2 0}
	
	form_radiobutton $d.vali I global_options(mdir) 0 {0 1}
	form_radiobutton $d.valj J global_options(mdir) 1 {0 2}
	form_radiobutton $d.valk K global_options(mdir) 2 {0 3}
	
	form_entry $d.val global_options(mval) val {1 1 -cols 3}
	
	form_radiobutton $d.abl "Grid Line" global_options(mtype) \
	    gridline {2 2}
	form_radiobutton $d.abc "Quad Center" global_options(mtype) \
	    center {2 1}
	
	form_checkbutton $d.all "Mirror Entire Model" global_options(mall) \
	    {3 0 -cols 2}
	
	form_checkbutton $d.matp "Mirror Material Points" \
	    global_options(mmat) {4 0 -cols 2}
	
	form_finish bot
    }
    if ![form_wait .mirror_stair] return
    
    if $global_options(mall) {
	set fams -all
    } else {
	set fams [surface_family_string_ids]
    }
    
    if {$fams != ""} {
	if $global_options(mmat) {
	    set mmat -matpoints
	} else {
	    set mmat ""
	}
	command "mirror_staircase -dim $global_options(mdir) \
-plane $global_options(mval) -type $global_options(mtype) $mmat $fams"
	command "mirror_staircase -clear" 0
    }
    
    update_index_planes
    update_display
}

proc mirror_update_info {} {
    global global_options
    
    if $global_options(famirrel) {
	set args "-nofamrel"
    } else {
	set args ""
    }
    command "mirror_staircase -info -autosym $args" 0
}

proc mirror_staircase_reset {} {
    command "mirror_staircase -full-clean" 0
}

proc symmetrize_staircase {} {
    global global_options family_active family_dims form_done_flag
    global mirror_surface_mat_i mirror_surface_mat_j mirror_surface_mat_k
    
    set allnams [families_in_order]
    set surfs ""
    foreach desc $allnams {
	set name [lindex $desc 0]
	set f [lindex $desc 1]
	set dim $family_dims($f)
	if {$dim >= 1 && $dim < 3} {
	    lappend surfs [list $f -text $name]
	}
    }
    
    if {$surfs == ""} {
	mess "Error: there are no surface families available.\n"
	return
    }
    
    mirror_update_info
    set buttons {{Accept {form_accept_hack .sym}} cancel \
		     {Reset {mirror_staircase_reset}}}
    set d [form_init .sym "Symmetrize Surfaces" "" $buttons]
    if {$d != ""} {
	form_label $d.symtype "Symmetrize" {1 0}
	form_radiobutton $d.manual "Manual" global_options(symtype) 1 {1 1} ""
	form_radiobutton $d.auto "Auto" global_options(symtype) 0 {1 2} ""
	
	form_checkbutton $d.igfam "Quads only determine symmetry" \
	    global_options(famirrel) {2 0 -cols 2} "" mirror_update_info
	
	form_frame $d.coms sunken 2 {5 0 -cols 3}
	form_button $d.coms.sym "Determine Symmetry" mirror_det_sym \
	    {0 0} global_options(symtype)
	form_button $d.coms.show "Show Correlation Values" \
	    "mirror_compute_corr 0" {0 1} global_options(symtype)
	
	form_label $d.li "I" {10 0} global_options(symtype)
	form_label $d.lj "J" {10 1} global_options(symtype)
	form_label $d.lk "K" {10 2} global_options(symtype)
	
	form_frame $d.fri ridge 2 {11 0 -fill none}
	form_frame $d.frj ridge 2 {11 1 -fill none}
	form_frame $d.frk ridge 2 {11 2 -fill none}
	
	foreach dir {i j k} {
	    catch {unset mirror_surface_mat_$dir}
	    check_box $d.fr$dir $surfs 6 mirror_surface_mat_$dir
	    foreach ff $surfs {
		set f [lindex $ff 0]
		set mirror_surface_mat_${dir}($f) $family_active($f)
	    }
	}	
	form_finish +300+300
    }
    
    tkwait variable form_done_flag(.sym)
    if $form_done_flag(.sym) {
	
	set args ""
	if $global_options(famirrel) {
	    set args "-nofamrel"
	}
	
	if {$global_options(symtype) == 0} {
	    command "mirror_staircase -noreinit -autosym \
-corr $global_options(corr) $args"
	} else {
	    foreach dir {i j k} {
		set fams ""
		foreach f [array names mirror_surface_mat_$dir] {
		    if {[set mirror_surface_mat_${dir}($f)]} {
			lappend fams $f
		    }
		}
		if {$fams != ""} {
		    command "mirror_staircase -noreinit -autoplane -dim \
$dir $args $fams"
		}
	    }
	}
    }
    
    # clean up
    
    command "mirror_staircase -clear" 0
    
    # redisplay
    
    update_display
}

proc mirror_det_sym {} {
    global global_options form_done_flag
    
    set w .detsym
    set buttons {{Done {form_accept_hack .detsym}}}
    set d [form_init $w "Determine Symmetry" "" $buttons]
    if {$d != ""} {
	form_label $d.lab "Symmetry Criteria" {0 0}
	form_entry $d.ent global_options(corr) float {0 1}
	
	form_finish +300+300
    }
    
    set oldfocus [focus]
    focus $w
    grab $w
    tkwait variable form_done_flag($w)
    grab release $w
    focus $oldfocus
    
    mirror_compute_corr 1
}

proc mirror_compute_corr {state} {
    global global_options last_line family_name family_dims
    global mirror_surface_mat_i mirror_surface_mat_j mirror_surface_mat_k
    global form_done_flag
    
    set args ""
    set com "mirror_staircase -info -noreinit -corr $global_options(corr) \
-autosym"
    
    if $global_options(famirrel) {
	append args " -nofamrel"
    }
    
    command "$com $args" 0
    set symmetry_info $last_line
    
    # once we have done this once, don't have to reinitialize -- only
    # need to cause the mirror db to be updated
    
    set df ""
    if {$state == 0} {
	set w .showcorr
	form_kill $w
	
	set buttons {{Done {form_accept_hack .showcorr}}}
	set df [form_init $w "Correlation Values" "" $buttons]
	
	form_label $df.h0 "Family" {0 0}
	form_label $df.h1 "Corr I" {0 1}
	form_label $df.h2 "Corr J" {0 2}
	form_label $df.h3 "Corr K" {0 3}
	set row 1
    }
    
    set crit $global_options(corr)
    foreach desc $symmetry_info {
	set fam [lindex $desc 0]
	set dim $family_dims($fam)
	if {$dim < 1 || $dim > 2} continue
	
	set sym(i) [lindex $desc 1]
	set sym(j) [lindex $desc 2]
	set sym(k) [lindex $desc 3]
	
	if {$df != ""} {
	    form_label $df.${row}0 $family_name($fam) "$row 0"
	    set col 1
	}
	foreach dir {i j k} {
	    set next $sym($dir)
	    set plane [lindex $next 0]
	    set type [lindex $next 1]
	    set qnsym [lindex $next 2]
	    set corr [lindex $next 3]
	    
	    if {$df != ""} {
		form_label $df.${row}${col} $corr "$row $col"
		incr col
	    } else {
		if {$corr >= $crit} {
		    set mirror_surface_mat_${dir}($fam) 1
		} else {
		    set mirror_surface_mat_${dir}($fam) 0
		}
	    }
	}
	
	if {$df != ""} {
	    incr row
	}
    }
    
    if {$df != ""} {
	form_finish +300+300
	
	set oldfocus [focus]
	focus $w
	grab $w
	tkwait variable form_done_flag($w)
	grab release $w
	focus $oldfocus
    }
}
