
# 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 make_unstruct_window {w} {
    menubutton $w.opt -text "Display options" -relief raised \
	-borderwidth 2 -menu $w.opt.m -padx 3 -pady 1
    menu $w.opt.m
    
    # -------------
    
    set do_cascade 0 ;# would be nice but the menus go off the right edge
    set cm $w.opt.m
    
    if $do_cascade {
	set cm $w.opt.m.els
	$w.opt.m add cascade -label "Element shading" -menu $cm
	menu $cm
    }
    $cm add radiobutton -label "Wireframe" \
	-variable disp_options(uns_disp) \
	-value Wire -command update_uns_disp
    $cm add radiobutton -label "Solid" \
	-variable disp_options(uns_disp) \
	-value Solid -command update_uns_disp
    $cm add radiobutton -label "Solid/wire" \
	-variable disp_options(uns_disp) \
	-value Solid/wire -command update_uns_disp
    $cm add radiobutton -label "Hidden line" \
	-variable disp_options(uns_disp) \
	-value "Hidden line" -command update_uns_disp
    $cm add radiobutton -label "By dimension" \
	-variable disp_options(uns_disp) \
	-value "By dimension" -command update_uns_disp
    
    if $do_cascade {
	set cm $w.opt.m.elo
	$w.opt.m add cascade -label "Element options" -menu $cm
	menu $cm
    } else {
	$cm add separator
    }
    $cm add checkbutton -label "Single edges" \
	-variable disp_options(uns_single_surfaces) \
	-command update_uns_disp
    $cm add checkbutton -label "Multiple edges" \
	-variable disp_options(uns_multiple_surfaces) \
	-command update_uns_disp
    $cm add checkbutton -label "Only show edges" \
	-variable disp_options(uns_only_edges) \
	-command update_uns_disp
    
    $cm add separator
    
    $cm add checkbutton -label "Face normals" \
	-variable disp_options(uns_normals) \
	-command update_uns_disp
    $cm add checkbutton -label "Face normals by color" \
	-variable disp_options(uns_normals_colored) \
	-command update_uns_disp
    $cm add checkbutton -label "Midside/midface nodes" \
	-variable disp_options(uns_midside_nodes) \
	-command update_uns_disp
    $cm add checkbutton -label "Face icons" \
	-variable disp_options(uns_icons) \
	-command update_uns_disp
    $cm add checkbutton -label "Couplings" \
	-variable disp_options(uns_couplings) \
	-command update_uns_disp
    $cm add checkbutton -label "Element numbers" \
	-variable disp_options(uns_enums) \
	-command update_uns_disp
    $cm add checkbutton -label "Shell thickness" \
	-variable disp_options(uns_thickness) \
	-command update_uns_disp
    $cm add checkbutton -label "Bar orientation" \
	-variable disp_options(uns_orientation) \
	-command update_uns_disp
    
    if $do_cascade {
	set cm $w.opt.m.shr
	$w.opt.m add cascade -label "Shrink elements" -menu $cm
	menu $cm
    } else {
	$cm add separator
    }
    $cm add radiobutton -label "No shrink" \
	-variable disp_options(uns_shrink) \
	-value 100 -command update_uns_disp
    $cm add radiobutton -label "Shrink 10%" \
	-variable disp_options(uns_shrink) \
	-value 90 -command update_uns_disp
    $cm add radiobutton -label "Shrink 50%" \
	-variable disp_options(uns_shrink) \
	-value 50 -command update_uns_disp
    $cm add checkbutton -label "Node pos" \
	-variable disp_options(uns_shrink_npos) \
	-command update_uns_disp
    
    if $do_cascade {
	set cm $w.opt.m.node
	$w.opt.m add cascade -label "Node options" -menu $cm
	menu $cm
    } else {
	$cm add separator
    }
    $cm add radiobutton -label "No nodes" \
	-variable disp_options(uns_node_type) \
	-value None -command update_uns_disp
    $cm add radiobutton -label "Dots" \
	-variable disp_options(uns_node_type) \
	-value Dots -command "update_uns_disp; print_node_color_message"
    $cm add radiobutton -label "External node numbers" \
	-variable disp_options(uns_node_type) \
	-value Ext -command "update_uns_disp; print_node_color_message"
    $cm add radiobutton -label "Internal node numbers" \
	-variable disp_options(uns_node_type) \
	-value Nums -command "update_uns_disp; print_node_color_message"
    $cm add radiobutton -label "Node coords" \
	-variable disp_options(uns_node_type) \
	-value Coords -command "update_uns_disp; print_node_color_message"
    $cm add radiobutton -label "Elem vert numbers" \
	-variable disp_options(uns_node_type) \
	-value Indices -command "update_uns_disp; print_node_color_message"
    $cm add checkbutton -label "Periodicity" \
	-variable disp_options(uns_periodicity) -command "update_uns_disp"
    $cm add checkbutton -label "Node changes" \
	-variable disp_options(uns_changes) -command "update_uns_disp"
    $cm add checkbutton -label "No inner elems" \
	-variable disp_options(uns_no_inner) -command "update_uns_disp"
    
    if $do_cascade {
	set cm $w.opt.m.bd
	$w.opt.m add cascade -label "Boundaries" -menu $cm
	menu $cm
    } else {
	$cm add separator
    }
    $cm add checkbutton -label "Volume bounds" \
	-variable disp_options(uns_vol_bounds) \
	-command update_uns_disp
    $cm add checkbutton -label "Surface bounds" \
	-variable disp_options(uns_surf_bounds) \
	-command update_uns_disp
    
    label $w.ml -text "Meshes"
    frame $w.m -borderwidth 2 -relief ridge -height 4
    #label $w.fl -text "Families"
    #frame $w.f -borderwidth 2 -relief ridge -height 4
    label $w.tl -text "Types"
    frame $w.t -borderwidth 2 -relief ridge -height 4
    checkbutton $w.sl -text "Display subset"  -variable uns_use_subset \
	-command update_uns_visible_subset
    frame $w.s -borderwidth 2 -relief ridge -height 4
    frame $w.se
    button $w.se.edit -text "Modify" -command unstruct_selection_edit
    button $w.se.reset -text "Reset" -command unstruct_selection_reset
    button $w.se.new -text "New" -command unstruct_selection_new
    button $w.se.delete -text "Delete" -command unstruct_selection_del
    #button $w.se.load -text "Load" -command unstruct_selection_load
    #button $w.se.save -text "Save" -command unstruct_selection_save
    grid $w.se.edit   -row 0 -column 0 -sticky news
    grid $w.se.reset  -row 0 -column 1 -sticky news
    grid $w.se.new    -row 1 -column 0 -sticky news
    grid $w.se.delete -row 1 -column 1 -sticky news
    #blt_table $w.se $w.se.load   2,0 -fill both
    #blt_table $w.se $w.se.save   2,1 -fill both
    # $w.f $w.fl 
    pack $w.se -side bottom -fill x -expand 0
    pack $w.s -side bottom -fill both -expand 1
    pack $w.sl -side bottom -fill x -expand 0
    pack $w.t -side bottom -fill both -expand 1
    pack $w.tl -side bottom -fill x -expand 0
    pack $w.opt -side bottom -fill x -expand 0
}

proc print_node_color_message {} {
    global disp_options print_node_color_message_once
    
    if ![info exists print_node_color_message_once] {
	mess "Node colors:"
 	mess "  prescribed" red
 	mess "  curve" green
 	mess "  surface" gray
	mess "  volume\n" cyan
	set print_node_color_message_once 1
    }
}

proc initialize_unstruct_visibility { { dummy "" } } {
    global fam_visible uns_type_visible uns_use_subset
    global unstruct_map_active
    
    foreach f [ic_uns_list_families] {
	if ![info exists fam_visible($f)] {
	    set fam_visible($f) 1
	}
    }
    foreach t [ic_uns_list_types] {
	if {([ic_count_elements] < 100000) || ![ic_count_elements BAR_2]} {
	    set vis {BAR_2 BAR_3 LINE_2 LINE_3 TRI_3 TRI_6 QUAD_4}
	} else {
	    set vis {BAR_2 BAR_3 LINE_2 LINE_3}
	}
	if ![info exists uns_type_visible($t)] {
	    set uns_type_visible($t) [expr {[lsearch $vis $t] >= 0}]
	}
    }
    set uns_use_subset 0
    set unstruct_map_active Selected
    display_update unstruct 0; #disp_new_stuff
}

proc uninitialize_unstruct_visibility {} {
    global uns_type_visible
    
    foreach t [ic_uns_list_types] {
	catch { unset uns_type_visible($t) }
    }
}

proc warn_many_elements {map} {
    global disp_options uns_type_visible batch_mode
    global tdv_default draw_too_many_last_count

    return 0
    if {$batch_mode || !$disp_options(uns_warn_if_display)} { return 0 }
    
    if [ ic_uns_subset_is_cut $map ] {
	return 0 
    }
    
    set pa [tdv_active 0]
    set howmany [ic_uns_subset_count_elements $map]
    if {[info exists draw_too_many_last_count] && ($howmany == $draw_too_many_last_count)} { return 0 }
    catch {unset draw_too_many_last_count}
    set ch 0
    if {$howmany > $disp_options(uns_warn_if_display)} {
	set mess "You have just turned on $howmany elements.  Do you really\
		want to draw that many on the screen?"
	if [tk_dialog .draw_many "Draw many elements" $mess "" -1 Yes No] {
	    set ch 1
	    foreach t [array names uns_type_visible] {
		if $uns_type_visible($t) {
		    set ne [ic_count_elements $t]
		    if {$ne > $disp_options(uns_warn_if_display)} {
			set uns_type_visible($t) 0
			mess "Turned off the $t elements\n" red
		    }
		}
	    }
	} else {
	    # Make sure we don't get asked that question too many times
	    set draw_too_many_last_count $howmany
	}
    }
    tdv_active $pa
    return $ch
}

proc get_uns_type_visible {type} {
    global uns_type_visible
    if {![info exists uns_type_visible($type)] || !$uns_type_visible($type)} {
	return 0
    } else {
	return 1
    }
}

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

# This gets called when the current subset changes, or the subset is turned
# off or on.

proc update_uns_visible_subset {{setact ""}} {
    global uns_use_subset unstruct_map_active unsmap_is_editable
    
    with_view_inactive {
	set cur [ic_uns_subset_get_current]
	if {$setact != ""} {
	    set unstruct_map_active $setact
	    set uns_use_subset 1
	}
	if {$uns_use_subset && ($cur == "Selected")} {
	    if {$setact == ""} {
		set unstruct_map_active [lindex [ic_uns_subset_list] 0]
	    }
	    check_box_active .e.unstruct.s 1
	} elseif {!$uns_use_subset && ($cur != "Selected")} {
	    set unstruct_map_active Selected
	    check_box_active .e.unstruct.s 0
	} elseif {!$uns_use_subset || ($cur == $unstruct_map_active)} {
	    return
	}
	
	ic_uns_subset_set_current $unstruct_map_active
	set unsmap_is_editable [ic_uns_subset_is_editable $unstruct_map_active]
    }
}

# This gets called when the types or families available change for
# unstructured meshes.

proc update_uns_available {} {
    global fam_visible uns_type_visible unstruct_map_active
    global unsmap_is_editable batch_mode disp_options
    global uns_fam_visible uns_type_visible uns_map_visible
    global uns_use_subset
    
    if {$batch_mode || ![ic_uns_is_loaded]} return
    
    with_view_inactive {
	set opts ""
	set newtypes 0
	foreach t [ic_uns_list_types] {
	    set got($t) 1
	    if ![info exists uns_type_visible($t)] {
		set uns_type_visible($t) 0
		set newtypes 1
	    }
	    lappend opts [list $t -text $t -command "update_uns_visible"]
	}
	foreach t [array names uns_type_visible] {
	    if ![info exists got($t)] {
		unset uns_type_visible($t)
	    }
	}
	check_box .e.unstruct.t $opts 4 uns_type_visible 1 update_uns_visible
	
	update_fam_window
	
	# -------------------
	
	set opts ""
	foreach m [ic_uns_subset_list] {
	    lappend opts [list $m -text $m -command "update_uns_visible_subset"]
	}
	
	check_box .e.unstruct.s $opts 4 unstruct_map_active 0 \
	    update_uns_visible_subset
	check_box_active .e.unstruct.s $uns_use_subset
	
	update_uns_disp
	update_uns_visible
	update_family_type visible fam_visible uns_type_visible update 0
    }
}

# This gets called when the user changes the family or type selection

proc update_uns_visible {} {
    global fam_visible uns_type_visible unstruct_map_active
    global unsmap_is_editable batch_mode disp_options
    global uns_fam_visible uns_type_visible uns_map_visible
    global uns_use_subset
    
    if ![ic_uns_is_loaded] return
    
    busy 1
    update_family_type Selected \
	fam_visible uns_type_visible update 0
    if ![ info exists uns_use_subset ] {
	set uns_use_subset 0
    }
    if {!$uns_use_subset && [warn_many_elements Selected]} {
	update_family_type Selected \
	    fam_visible uns_type_visible update 0
    }
    busy 0
}

# This updates all the display properties on a subset

proc update_uns_disp {{maps ""}} {
    global disp_options shrink_index_message_printed
    global color_by_count_message_printed

    if ![ic_uns_is_loaded] return
    if {$maps == ""} { set maps visible }

    if {$disp_options(uns_shrink) < 0} {
	mess "Warning: shrink can't be less than 0\n" red
	set disp_options(uns_shrink) 0
    } elseif  {$disp_options(uns_shrink) > 100} {
	mess "Warning: shrink can't be more than 100\n" red
	set disp_options(uns_shrink) 100
    }
    
    array set optn {
	Wire wire Solid flat Solid/wire flat_wire "Hidden line" hidden
	"By dimension" by_type
    }
    
    set bcf ""
    if $disp_options(uns_bcfield) {
	set bcf $disp_options(uns_bcfield_name)
    }
    
    set icons $disp_options(uns_icons)
    if {$disp_options(uns_disp) != "Wire"} { set icons 0 }
    
    ic_uns_subset_configure "" -shade $optn($disp_options(uns_disp)) \
	-shrink $disp_options(uns_shrink) \
	-only_edges $disp_options(uns_only_edges) \
	-single_surfaces $disp_options(uns_single_surfaces) \
	-multiple_surfaces $disp_options(uns_multiple_surfaces) \
	-draw_normals $disp_options(uns_normals) \
	-draw_normals_colored $disp_options(uns_normals_colored) \
	-draw_midside_nodes $disp_options(uns_midside_nodes) \
	-draw_icons $icons \
	-draw_couplings $disp_options(uns_couplings) \
	-draw_icons_normals_vol $disp_options(uns_icons_normals_vol) \
	-draw_enums $disp_options(uns_enums) \
	-draw_thickness $disp_options(uns_thickness) \
	-draw_orientation $disp_options(uns_orientation) \
	-draw_vol_bounds $disp_options(uns_vol_bounds) \
	-draw_surf_bounds $disp_options(uns_surf_bounds) \
	-shrink_npos $disp_options(uns_shrink_npos) \
	-draw_periodicity $disp_options(uns_periodicity) \
	-draw_no_inner $disp_options(uns_no_inner) \
	-draw_changes $disp_options(uns_changes) \
        -color_by_quality $disp_options(uns_color_by_quality) \
        -locked_elements $disp_options(uns_locked_elements) \
        -draw_directions $disp_options(uns_directions) \
        -width [expr $disp_options(uns_wide_lines) ? 2 : 0] \
	-draw_bcfield $bcf \
        -show_dualmesh $disp_options(uns_dualmesh)
     
    update_uns_map_node_opts ""
    
    if {![info exists shrink_index_message_printed] && \
	    $disp_options(uns_nodes) && \
	    ($disp_options(uns_node_type) == "Indices") && \
	    ($disp_options(uns_shrink) == 100) && \
	    ([lindex [$map count] 0] > 1)} {
	mess "Note: to see the indices more clearly you should set the shrink\
		factor to something smaller than 100\n" red
	set shrink_index_message_printed 1
    }
    if {![info exists color_by_count_message_printed] &&
	($disp_options(uns_multiple_surfaces) ||
	 $disp_options(uns_single_surfaces))} {
	mess "yellow" #ffdd00 ; mess " = single\n"
	mess "blue" cyan ; mess " = multiple\n"
	set color_by_count_message_printed 1
    }
}

# This sets the node display options for a node set

proc update_uns_map_node_opts {map} {
    global disp_options
    
    array set ntypen { Dots 0 Couplings 0 Indices 1 Nums 2 Coords 3 Ext 4 None 0 }
    array set dtypen { Triad 0 Number 1 None 0 }
    if ![info exists disp_options(uns_displ_orient)] {
	set disp_options(uns_displ_orient) "Triad"
    }
    if {$disp_options(uns_displ_orient) == ""} {
	set disp_options(uns_displ_orient) "Triad"
    }
    ic_uns_subset_configure $map \
	-draw_node_type $ntypen($disp_options(uns_node_type)) \
	-draw_displ_orient $dtypen($disp_options(uns_displ_orient)) \
        -draw_nodes [expr {$disp_options(uns_node_type) != "None"}] \
        -draw_couplings $disp_options(uns_couplings)
}

# This one makes sure that we are in a subset with a given name

proc switch_to_subset {name} {
    global uns_use_subset

    ic_uns_subset_create $name
    
    if {$uns_use_subset && (($name == "") ||
			    ([ic_uns_subset_get_current] == $name))} return
    if {$name == ""} {
	set name [lindex [ic_uns_subset_list] 0]
	if {$name == ""} {
	    set name [ic_uns_subset_unused_name Subset]
	    ic_uns_subset_create $name 1
	}
    }
    
    update_uns_visible_subset $name
}
