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

proc update_family_type {map fvar tvar what force} {
    set fvals ""; set tvals ""
    if {$fvar != ""} {
	global $fvar
	foreach f [array names $fvar] {
	    if [set ${fvar}($f)] { lappend fvals $f }
	}
    }
    if {$tvar != ""} {
	global $tvar
	foreach t [array names $tvar] {
	    if [set ${tvar}($t)] { lappend tvals $t }
	}
    }
    ic_uns_update_family_type $map $fvals $tvals $what $force
}

proc unstruct_selection_reset {} {
    global fam_visible uns_type_visible
    global selmap uns_use_subset
    
    update_family_type visible fam_visible uns_type_visible update 1
    if {!$uns_use_subset || !$selmap(cut_on)} {
	if [warn_many_elements visible] {
	    update_family_type visible fam_visible uns_type_visible update 1
	}
    }
}

proc unstruct_selection_new {} {
    set name [ic_uns_subset_unused_name Subset]
    set name [question_box .new_name "New name" "Name of new selection?" $name]
    if {$name == ""} return
    
    set prev [ic_uns_subset_get_current]
    set name [ic_uns_subset_create $name 1 $prev]
    update_uns_visible_subset $name
    update_uns_available
}

proc unstruct_selection_del {} {
    if {[ic_uns_subset_get_current] == "Selected"} {
	error "Can't delete that one"
    }
    ic_uns_subset_delete visible
    set nname [lindex [ic_uns_subset_list] 0]
    update_uns_visible_subset $nname
    update_uns_available
}

proc unstruct_selection_edit {} {
    global selmap uns_use_subset unstruct_map_active
    
    switch_to_subset $unstruct_map_active
    
    mess "[ic_uns_subset_count_elements visible] elements in subset\n"
    
    set d [form_init .unstruct_select "Element selection" "" done]
    
    if {$d != ""} {
	form_frame $d.op1 ridge 2 {0 0}
	form_frame $d.op2 ridge 2 {0 1}
	form_frame $d.op3 ridge 2 {0 2}
	form_frame $d.op4 ridge 2 {0 3}
	form_frame $d.op5 ridge 2 {0 4}
	
	# -------------------------------------------------------------
	
	form_button $d.op1.clear "Clear" es_clear {0 0 -sticky ew} unsmap_is_editable
	form_button $d.op1.res "Reset" es_reset {1 0 -sticky ew} unsmap_is_editable
	form_button $d.op1.inv "Invert" es_invert {2 0 -sticky ew} unsmap_is_editable
	form_button $d.op1.type "Active" es_settypes {3 0 -sticky ew} unsmap_is_editable
	form_button $d.op1.srestrs "Restrict" es_restrict {4 0 -sticky ew} unsmap_is_editable
	
	# -------------------------------------------------------------
	
	form_label $d.op2.lab "Add:" {0 0 -cols 2} unsmap_is_editable
	form_colwidth $d.op2 0 0 M
	
	form_button $d.op2.single "Specific" es_single {1 1 -sticky ew} \
	    unsmap_is_editable
	form_button $d.op2.sothers "Subset" es_add_subset {2 1 -sticky ew} \
	    unsmap_is_editable
	#form_button $d.op2.aatt "Attached" "es_add_attached" {3 1 -sticky ew} unsmap_is_editable
	form_button $d.op2.sadds "Screen" es_add {4 1 -sticky ew} \
	    unsmap_is_editable
	
	set m $d.op2.aatt.m
	form_menubutton_regular $d.op2.aatt "Fill" $m \
	    {3 1 -sticky ew} unsmap_is_editable
	menu $m
	$m add command -label "All attached" -command "es_add_attached all"
	$m add command -label "Same family" -command "es_add_attached fam"
	$m add command -label "To curve" -command "es_add_attached curve"
	$m add command -label "To angle" -command "es_add_attached angle"
	
	# -------------------------------------------------------------
	
	form_label $d.op3.lab "Remove:" {0 0 -cols 2} unsmap_is_editable
	form_colwidth $d.op3 0 0 M
	#form_button $d.op3.blanki "Hidden" es_rem_invisible {1 1 -sticky ew} unsmap_is_editable
	form_button $d.op3.blankn "Normals" es_rem_normals {2 1 -sticky ew} \
	    unsmap_is_editable
	#form_button $d.op3.ratt "Attached" "es_rem_attached 1" {3 1 -sticky ew} unsmap_is_editable
	form_button $d.op3.sremoves "Screen" es_remove {4 1 -sticky ew} \
	    unsmap_is_editable
	form_button $d.op3.sremovem "Manifold" es_rem_manif {5 1 -sticky ew} \
	    unsmap_is_editable
	
	set m $d.op3.ratt.m
	form_menubutton_regular $d.op3.ratt "Fill" $m \
	    {3 1 -sticky ew} unsmap_is_editable
	menu $m
	$m add command -label "All attached" -command "es_rem_attached all"
	$m add command -label "Same family" -command "es_rem_attached fam"
	$m add command -label "To curve" -command "es_rem_attached curve"
	$m add command -label "To angle" -command "es_rem_attached angle"
	
	# -------------------------------------------------------------
	
	form_label $d.op4.lab "Layers:" {0 0 -cols 3} unsmap_is_editable
	form_colwidth $d.op4 0 0 M
	form_frame $d.op4.fr flat 0 {1 1 -cols 2}
	form_button $d.op4.fr.xaddl "Add" es_layer_add {0 0 -sticky ew} \
	    unsmap_is_editable
	form_button $d.op4.fr.xremovel "Remove" es_layer_remove {0 1 -sticky ew} \
	    unsmap_is_editable
	form_label $d.op4.numl "Num layers" {2 1} \
	    unsmap_is_editable
	form_entry $d.op4.num selmap(num_layers) int {2 2} \
	    unsmap_is_editable
	$d.op4.num configure -width 6
	set m $d.op4.modeb.m
	form_menubutton_regular $d.op4.modeb "Active F & T" $m \
	    {3 1 -cols 2 -sticky ew} unsmap_is_editable
	menu $m
	foreach mm {
	    { "Active F & T" active_active }
	    { "All F, active T" all_active }
	    { "All F, surfs" all_surf }
	    { "Active F, surfs" active_surf }
	    { "Active F, all T" active_all }
	    { "All F, all T" all_all }
	} {
	    $m add command -label [lindex $mm 0] -command \
		"$d.op4.modeb configure -text \"[lindex $mm 0]\"; \
		set selmap(layer_mode) [lindex $mm 1]"
	}
	
	form_label $d.op4.labxxx " " {4 0}
	# -------------------------------------------------------------
	
	form_frame $d.op5.cut flat 0 {0 0 -cols -}
	form_checkbutton $d.op5.cut.on "Cut plane" selmap(cut_on) {0 0} unsmap_is_editable
	form_checkbutton $d.op5.cut.wh "Whole" selmap(cut_whole) {0 1} unsmap_is_editable
	form_frame $d.op5.fr flat 0 {1 0 -cols 2}
	form_label $d.op5.fr.res "Reset:" {0 0} unsmap_is_editable
	form_button $d.op5.fr.x "X" "es_cut_update 0" {0 1 -sticky ew} unsmap_is_editable
	form_button $d.op5.fr.y "Y" "es_cut_update 1" {0 2 -sticky ew} unsmap_is_editable
	form_button $d.op5.fr.z "Z" "es_cut_update 2" {0 3 -sticky ew} unsmap_is_editable
	form_button $d.op5.res "Restrict" "es_cut_update restrict" {2 0 -sticky ew} \
	    unsmap_is_editable
	form_button $d.op5.edit "Params" "es_cut_update edit" {2 1 -sticky ew} unsmap_is_editable
	form_scale $d.op5.sc selmap(cut_scan) \
	    "es_cut_update scan; list" h 0 1 0.001 {3 0 -cols 2 -fill x} \
	    unsmap_is_editable "es_cut_update scan_release"
	
	$d.op5.cut.on configure -command "es_cut_update update"
	$d.op5.cut.wh configure -command "es_cut_update update"
	
	# This one we don't want to autoraise ....
	form_finish bot 1 0
    }
}

proc uns_all_active_types_visible {} {
    global uns_type_visible

    foreach t [ic_uns_list_types] {
	if ![set uns_type_visible($t)] { return 0 }
    }
    return 1
}

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

# All the subroutines for manipulating the selection.

proc es_clear {} {
    ic_uns_subset_clear visible
    mess "Cleared all elements\n"
}

proc es_reset {} {
   unstruct_selection_reset 
}

proc es_invert {} {
    ic_uns_invert_subset visible Selected
    mess "[ic_uns_subset_count_elements visible] elements\n"
}

proc es_settypes {} {
    update_family_type visible fam_visible uns_type_visible restrict_to 1
}

proc es_add {} {
    set sel [select_unstruct element 0 Selected "" "the region"]
    if {$sel == ""} return
    ic_uns_subset_add_from visible $sel
    ic_uns_subset_delete $sel
}

proc es_select_subset {not what} {
    set maps [ldelete [ic_uns_subset_list] $not]
    return [choose_one "Select the subset to $what." [lsort $maps]]
}

proc es_add_subset {} {
    set other [es_select_subset [ic_uns_subset_get_current] "copy from"]
    if {$other == ""} return
    ic_uns_subset_add_from visible $other
    if 0 { ic_uns_subset_delete $other } ;# cf. Bug #:3728
}

proc es_remove {} {
    set sel [select_unstruct element 0 visible "" "the elements to remove"]
    if {$sel == ""} return
    ic_uns_subset_subtract_from visible $sel
    ic_uns_subset_delete $sel
}

proc es_restrict {} {
    set sel [select_unstruct element 0 visible "" "the elements to keep"]
    if {$sel == ""} return
    ic_uns_subset_copy visible $sel
    ic_uns_subset_delete $sel
}

proc es_single {} {
    set d [form_init .unstruct_select_single "Individual elements" "" done]
    if {$d != ""} {
	form_button $d.enuml "Add by number" es_number {0 0} \
	    unsmap_is_editable
	form_entry $d.singlen selmap(single_element_num) int {0 1 -cols 2} \
	    unsmap_is_editable
	bind $d.singlen <Return> es_number
	form_radiobutton $d.global "Global" selmap(number_global_mode) 1 \
	    {1 0} unsmap_is_editable
	form_radiobutton $d.local "Local" selmap(number_global_mode) 0 \
	    {1 1 -cols 2} unsmap_is_editable
	form_label $d.ltypel "Type" {2 0 -sticky e} \
	    {unsmap_is_editable {selmap(number_global_mode) 0}}
	futil_menuentry $d.ltype selmap(number_local_type) \
	    ic_uns_list_types {2 1} \
	    {unsmap_is_editable {selmap(number_global_mode) 0}}
	form_button $d.nearl "Near position" es_nearpos {3 0 -sticky ew} \
	    unsmap_is_editable
	form_entry $d.nearp selmap(nearpos) string {3 1 -cols 2} \
	    unsmap_is_editable
	bind $d.nearp <Return> es_nearpos
	form_button $d.nearnl "Near nodes" es_nearnode {4 0 -sticky ew} \
	    unsmap_is_editable
	form_entry $d.nearn selmap(nearnode) int {4 1 -cols 2} \
	    unsmap_is_editable
	bind $d.nearn <Return> es_nearnode
	form_button $d.inreg "All in region" es_region {5 0  -sticky ew} \
	    unsmap_is_editable
	
	form_finish bot
    }
}

proc es_number {} {
    global selmap
    if $selmap(number_global_mode) {
	set n [ic_uns_subset_add_number visible $selmap(single_element_num) \
		   1 MIXED]
    } else {
	set n [ic_uns_subset_add_number visible $selmap(single_element_num) \
		   0 $selmap(number_local_type)]
    }
    switch -- $n {
	-1 { mess "That element is already selected\n" }
	0 { mess "Error: no element with that number\n" red }
	1 { mess "1 more element\n" }
	default { mess "Warning: $n elements found with that number\n" red }
    }
}

proc es_region {} {
    global selmap
    
    set d [form_init .unstruct_in_region "Add in region"]
    if {$d != ""} {
	form_label $d.xl1 "Min X" {0 0}
	form_label $d.yl1 "Min Y" {1 0}
	form_label $d.zl1 "Min Z" {2 0}
	form_label $d.xl2 "Max X" {0 2}
	form_label $d.yl2 "Max Y" {1 2}
	form_label $d.zl2 "Max Z" {2 2}
	form_entry $d.x1 selmap(reg_x1) float {0 1}
	form_entry $d.y1 selmap(reg_y1) float {1 1}
	form_entry $d.z1 selmap(reg_z1) float {2 1}
	form_entry $d.x2 selmap(reg_x2) float {0 3}
	form_entry $d.y2 selmap(reg_y2) float {1 3}
	form_entry $d.z2 selmap(reg_z2) float {2 3}
	form_checkbutton $d.part "Include elements partly in region" \
	    selmap(reg_part) {3 0 -cols 4}
	form_finish bot
    }
    if ![form_wait .unstruct_in_region] return
    
    set p1 [list $selmap(reg_x1) $selmap(reg_y1) $selmap(reg_z1)]
    set p2 [list $selmap(reg_x2) $selmap(reg_y2) $selmap(reg_z2)]
    set n [ic_uns_subset_add_region visible $p1 $p2 $selmap(reg_part)]
    mess "Total elements = [ic_uns_subset_count_elements visible],\
	total nodes = [ic_uns_subset_count_nodes visible].\n"
}

proc es_nearpos {} {
    global selmap
    set n [ic_uns_subset_add_near_pos visible $selmap(nearpos)]
    if !$n {
	mess "Error: no element near that position\n" red
    } else {
	mess "$n elements added\n"
    }
}

proc es_nearnode {} {
    global selmap
    set nn $selmap(nearnode)
    regsub -all \n $nn " " nn
    set n [ic_uns_subset_add_near_nodes visible $nn]
    if !$n {
	mess "Error: no elements attached to those nodes\n" red
    }
}

proc es_layer_add {} {
    global selmap
    
    set n [ic_uns_subset_add_layer visible $selmap(num_layers) \
	       [es_layer_fams] [es_layer_types]]
    mess "$n more elements\n"
}

proc es_layer_remove {} {
    global selmap
    
    set n [ic_uns_subset_remove_layer visible $selmap(num_layers) \
	       [es_layer_types]]
    mess "$n fewer elements\n"
}

proc es_layer_fams {} {
    global selmap
    
    switch -glob $selmap(layer_mode) {
	active_* { return active }
	all_*    { return all }
    }
}

proc es_layer_types {} {
    global selmap
    
    switch -glob $selmap(layer_mode) {
	*_active { return active }
	*_all    { return all }
	*_surf   { return surf }
    }
}

proc es_fill_to_curve {} {
    error "not yet implemented"
}

proc es_add_attached {how} {
    global selmap
    
    set a 0
    if {$how == "angle"} {
	set a [question "Angle (degrees)?" $selmap(fill_angle)]
	if {$a == ""} return
	set selmap(fill_angle) $a
    }
    ic_uns_subset_add_attached visible Selected $how $a

    mess "[ic_uns_subset_count_elements visible] elements\n"
}

proc es_rem_attached {how} {
    global selmap
    
    set tmp [select_unstruct element 0 visible ""]
    if {$tmp == ""} return
    
    set a 0
    if {$how == "angle"} {
	set a [question "Angle (degrees)?" $selmap(fill_angle)]
	if {$a == ""} { ic_uns_subset_delete $tmp; return }
	set selmap(fill_angle) $a
    }
    ic_uns_subset_add_attached $tmp visible $how $a
    ic_uns_subset_subtract_from visible $tmp
    ic_uns_subset_delete $tmp
    mess "[ic_uns_subset_count_elements visible] elements\n"
}

proc es_rem_manif {} {
    global selmap
    
    ic_uns_subset_remove_manifold_elements visible
    
    mess "[ic_uns_subset_count_elements visible] elements\n"
}

proc es_rem_invisible {} {
    error "not yet implemented"
}

proc es_rem_normals {} {
    global selmap
    
    set n [question_box .normals "Normal" "Remove with normal:" \
	       $selmap(normal)]
    if {$n == ""} return
    set selmap(normal) $n
    ic_uns_subset_remove_normal visible $selmap(normal)
    mess "[ic_uns_subset_count_elements visible] elements\n"
}

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

proc es_cut_update {how} {
    global selmap disp_options
    global tdv_default unsmap_is_editable

    if {(($how == "scan") || ($how == "scan_release")) && (![info exists unsmap_is_editable] || !$unsmap_is_editable || !$selmap(cut_on))} return
    
    if {($how == "update") && ![info exists selmap(cut_initialized)]} {
	set selmap(cut_initialized) 1
	set how 0
    }
    
    set bbox [ic_uns_subset_bbox visible 1]
    if {$bbox == ""} return
    
    set bmin [lindex $bbox 0]; set bmax [lindex $bbox 1]
    
    switch $how {
	update {
	    if !$selmap(cut_on) {
		if [warn_many_elements visible] {
		    update_family_type visible fam_visible uns_type_visible \
			restrict_to 1
		}
	    }
	}
	restrict {
	    es_cut_update update
	    ic_uns_subset_cut visible restrict
	    set selmap(cut_on) 0
	}
	edit {
	    set d [form_init .unstruct_cut "Plane params" "" \
		       [list {Apply {es_cut_update update}} dismiss]]
	    if {$d != ""} {
		form_label $d.pxl "X pt" {0 0}
		form_label $d.pyl "Y pt" {1 0}
		form_label $d.pzl "Z pt" {2 0}
		form_label $d.nxl "X norm" {3 0}
		form_label $d.nyl "Y norm" {4 0}
		form_label $d.nzl "Z norm" {5 0}
		form_entry $d.px selmap(cut_px) float {0 1}
		form_entry $d.py selmap(cut_py) float {1 1}
		form_entry $d.pz selmap(cut_pz) float {2 1}
		form_entry $d.nx selmap(cut_nx) float {3 1}
		form_entry $d.ny selmap(cut_ny) float {4 1}
		form_entry $d.nz selmap(cut_nz) float {5 1}
		form_checkbutton $d.whole "Whole elements" \
		    selmap(cut_whole) {6 0 -cols 2}
		form_finish bot
	    }
	}
	scan - scan_release {
	    if {[info exists selmap(cut_lastcount)] && \
		    ($selmap(cut_lastcount) > \
			 $disp_options(uns_cut_delay_count))} {
		if {$how == "scan"} {
		    if ![info exists selmap(cut_warnonce)] {
			set selmap(cut_warnonce) 1
			mess "Cut plane action is delayed until button release\n" orange
		    }
		    return
		}
	    } else {
		if {$how == "scan_release"} {
		    return
		}
	    }
	    set pt [list $selmap(cut_px) $selmap(cut_py) $selmap(cut_pz)]
	    set norm [list $selmap(cut_nx) $selmap(cut_ny) $selmap(cut_nz)]
	    set pt [ic_coords_into_global $pt]
	    set norm [ic_coords_dir_into_global $norm]
	    set npt [clip_scan_to_box $pt $norm $bmin $bmax $selmap(cut_scan)]
	    foreach i {0 1 2} {
		set selmap(cut_p[lindex {x y z} $i]) [lindex $npt $i]
	    }
	    if {$how == "scan_release"} {
		catch {unset selmap(cut_warnonce)}
	    }
	}
	0 - 1 - 2 {
	    foreach i {0 1 2} {
		set p [lindex {x y z} $i]
		set selmap(cut_p$p) [expr ([lindex $bmax $i] + \
					   [lindex $bmin $i]) / 2.0]
		set selmap(cut_n$p) [expr {$how == $i}]
	    }
	}
    }
    set n [ic_uns_subset_cut visible set $selmap(cut_on) $selmap(cut_whole) \
	       [list $selmap(cut_px) $selmap(cut_py) $selmap(cut_pz)] \
	       [list $selmap(cut_nx) $selmap(cut_ny) $selmap(cut_nz)]]
    if {$n >= 0} {
	mess "$n elements in cut\n"
    }
    set selmap(cut_lastcount) $n
    
    set pt [list $selmap(cut_px) $selmap(cut_py) $selmap(cut_pz)]
    set norm [list $selmap(cut_nx) $selmap(cut_ny) $selmap(cut_nz)]
    set $selmap(cut_scan) [clip_scan_to_box $pt $norm $bmin $bmax ""]
    $tdv_default redraw
}
