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

proc setup_graphics_window {} {
    global black_and_white use_xwindows xwindows_fast use_dbuffer
    global tdv_cursor_path autohex_dir guibase_dir env
    global graph_action_var tdv_axes_var tdv_origin_var
    global tdv_no_redraw_ms
    global tdv_default

    # We have to do this pretty early ...  If the user hasn't given -x then
    # check in the relevant config files.
    
    if !$use_xwindows {
	foreach file {.icemcfd_options .med_options} {
	    set optf [home_directory]/$file
	    if ![catch {open $optf r} fp] {
		while {![eof $fp]} {
		    set line [gets $fp]
		    regexp {use_xwindows ([0-9])} $line dummy use_xwindows
		}
		close $fp
	    }
	}
    }
    
    switch $use_xwindows {
	0 { set graphics_type native }
	1 { set graphics_type X11 }
	2 { set graphics_type OpenGL }
    }
    if $black_and_white {
	set bgcolor white
    } else {
	set bgcolor black
    }
    
    set tdv_no_redraw_ms 0 ;# we use special dynamics display lists instead
    tdv_init $tdv_default 500 500 $graphics_type $bgcolor 0 $use_dbuffer
    if {[$tdv_default get -gsys] == "X11"} { set use_xwindows 1 }
    if !$xwindows_fast {
	$tdv_default configure -xhidden 1 -xgouraud 1
    }
    #$tdv_default configure -keep_bbox_updated 0
    
    tdv_dynamics_bindings $tdv_default
    tdv_selection_bindings $tdv_default
    
    lappend tdv_cursor_path $env(MED_ROOT)/lib/med
    lappend tdv_cursor_path $env(ICEM_ACN)/lib/med
    lappend tdv_cursor_path $guibase_dir
    
    tdv_init_shortcuts 0
    
    tdv_set_key_command Control-c "interrupt set" "Interrupt"
    tdv_set_key_command F11 "make_sane" "Emergency reset"
    # On sun F11 is used for something else ...  So we will take F4 also
    tdv_set_key_command F4 "make_sane" "Emergency reset"
    tdv_set_key_command j disp_toggle_solid "Toggle solid display"
    
    set tdv_axes_var($tdv_default) 1
    set tdv_origin_var($tdv_default) 1
}

proc med_home {} {
    global options
    global tdv_default

    if $options(home_after_load) {
	tdv_home $tdv_default
    }
}

proc make_sane {} {
    global tdv_default select_action
    
    set select_action cancel
    mess "Emergency reset\n" red
    banner ""
    busy reset
    interrupt reset
    tdv_dynamics_bindings $tdv_default
    tdv_cur $tdv_default dynamics
    tdv_active 1
    catch { aie_cutplane_clear }
    catch { aie_unset_all_selection_modes }
    bind $tdv_default c "do_center %x %y"
}

proc setup_display_menu_func {mb} {
    global background_color view_buttons axes_use_minmax display_axes
    global tdv_default

    set background_color #000000
    set display_axes 1
    
    $mb configure -menu $mb.m
    menu $mb.m
    $mb.m add command -label "Set background" -command set_background
    $mb.m add command -label "Distance" -command med_check_distance
    $mb.m add command -label "Location" -command med_check_location
    $mb.m add command -label "Angle" -command med_check_angle
    $mb.m add command -label "Bounding box" -command med_check_bbox
    if 0 {
    $mb.m add checkbutton -label Depthcue -variable tdv_depthcue_var($tdv_default) \
	-command "tdv_toggle_depthcue $tdv_default"
    }
    $mb.m add checkbutton -label "Coord axes" -variable tdv_axes_var($tdv_default) \
	-command " tdv_toggle_axes $tdv_default"
    $mb.m add checkbutton -label "Origin marker" -variable tdv_origin_var($tdv_default) \
	  -command "tdv_toggle_origin $tdv_default"
    $mb.m add separator
    $mb.m add command -label "Add marker" -command disp_add_marker
    $mb.m add command -label "Clear markers" -command disp_clear_markers
    $mb.m add command -label "Coord systems" -command coordinate_systems
}

proc med_check_distance {} {
    global med_distance_var
    
    set med_distance_var ""
    set dxdydz [med_get_distance med_distance_var]
    if {$med_distance_var == ""} return
    mess "delX = [format %g [lindex $dxdydz 0]], \
	    delY = [format %g [lindex $dxdydz 1]], \
	    delZ = [format %g [lindex $dxdydz 2]]; \
	    \nAbsolute Distance is [format %g $med_distance_var]\n"
    return $med_distance_var
}

proc med_get_distance {varname} {
    global tdv_default
    global [lindex [split $varname \(] 0]
    
    tdv_cur $tdv_default pick
    banner "Select the first point on the screen with the left button."
    set pt1 [get_graphics_loc]
    banner ""
    if {$pt1 == ""} { tdv_cur $tdv_default dynamics; return }
    
    set im1 [tdv_point_im -point $pt1 -size 3 -color white]
    $tdv_default add_image $im1
    $tdv_default redraw
    
    banner "Select the second point on the screen with the left button."
    set pt2 [get_graphics_loc]
    banner ""
    if {$pt2 == ""} { tdv_cur $tdv_default dynamics; $im1 delete; return }
    
    set im2 [tdv_point_im -point $pt2 -size 3 -color white]
    $tdv_default add_image $im2
    $tdv_default redraw
    
    after 500
    
    set pt1 [ic_coords_into_local $pt1]
    set pt2 [ic_coords_into_local $pt2]
    
    set dist 0
    set dxdydz ""
    foreach i {0 1 2} {
	set p [expr {[lindex $pt2 $i] - [lindex $pt1 $i]}]
	set dist [expr {$dist + $p * $p}]
	lappend dxdydz $p
    }
    set $varname [expr {sqrt($dist)}]
    
    $im1 delete
    $im2 delete
    tdv_cur $tdv_default dynamics
    
    return $dxdydz
}

proc med_check_location {} {
    global tdv_default
    tdv_cur $tdv_default pick
    banner "Select the points on the screen with the left button;\
	    middle or right = done."
    set pp ""
    while 1 {
	set pt [get_graphics_loc]
	if {$pt == ""} break
	set tpt [ic_coords_into_local $pt]
	set im [tdv_point_im -point $pt -size 3 -color white]
	set im2 [tdv_text_im -point $pt -text " $tpt" -color white]
	$tdv_default add_image $im
	$tdv_default add_image $im2
	$tdv_default redraw
	lappend pp $im $im2
	mess "$tpt\n" blue
    }
    banner ""
    foreach p $pp { $p delete }
    tdv_cur $tdv_default dynamics
}

proc med_get_locations {{num 0} {mess "the points"}} {
    global tdv_default
    tdv_cur $tdv_default pick
    banner "Select $mess on the screen with the left button;\
	    middle or right = done."
    set pp ""
    set ret ""
    for {set i 0} {!$num || ($i < $num)} {incr i} {
	set pt [get_graphics_loc]
	if {$pt == ""} break
	set tpt [ic_coords_into_local $pt]
	set im [tdv_point_im -point $pt -size 3 -color white]
	set im2 [tdv_text_im -point $pt -text " $tpt" -color white]
	$tdv_default add_image $im
	$tdv_default add_image $im2
	$tdv_default redraw
	lappend pp $im $im2
	mess "$tpt\n" blue
	lappend ret $tpt
    }
    banner ""
    foreach p $pp { $p delete }
    tdv_cur $tdv_default dynamics
    return $ret
}

proc med_get_plane_normal_3pts {var} {
    global tdv_default
    upvar $var lvar
    set p ""; set ims ""
    foreach x {"the first point" "the second point" "the third point"} {
	set p1 [disp_get_location "" 1 $x]
	if {$p1 == ""} return
	lappend p $p1
	set im1 [tdv_point_im -point $p1 -size 3 -color white]
	$tdv_default add_image $im1
	lappend ims $im1
    }
    set lvar [get_plane_normal [lindex $p 0] [lindex $p 1] [lindex $p 2]]
    foreach i $ims { $i delete }
}

proc med_get_line_dir_2pts {var} {
    global tdv_default
    upvar $var lvar
    
    set p1 [disp_get_location "" 1 "the first point"]
    if {$p1 == ""} return
    set im1 [tdv_point_im -point $p1 -size 3 -color white]
    $tdv_default add_image $im1
    set p2 [disp_get_location "" 1 "the second point"]
    $im1 delete
    if {$p2 == ""} return
    set p ""
    foreach i {0 1 2} {
	lappend p [expr {[lindex $p2 $i] - [lindex $p1 $i]}]
    }
    set lvar $p
}

proc med_get_line_2pts {pvar dvar {ovar ""} {oval ""}} {
    global tdv_default
    upvar $pvar lpvar
    upvar $dvar ldvar
    
    set p1 [disp_get_location "" 1 "the first point"]
    if {$p1 == ""} return
    set im1 [tdv_point_im -point $p1 -size 3 -color white]
    $tdv_default add_image $im1
    set p2 [disp_get_location "" 1 "the second point"]
    $im1 delete
    if {$p2 == ""} return
    set p ""
    foreach i {0 1 2} {
	lappend p [expr {[lindex $p2 $i] - [lindex $p1 $i]}]
    }
    set ldvar $p
    set lpvar $p1
    if {$ovar != ""} { uplevel \#0 set $ovar $oval }
}

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

proc med_check_angle {} {
    global tdv_default
    tdv_cur $tdv_default pick
    banner "Select the vertex point on the screen with the left button."
    set pt1 [get_graphics_loc]
    banner ""
    if {$pt1 == ""} { tdv_cur $tdv_default dynamics; return }
    
    set im1 [tdv_point_im -point $pt1 -size 3 -color blue]
    $tdv_default add_image $im1
    $tdv_default redraw
    
    banner "Select the first vector end on the screen with the left button."
    set pt2 [get_graphics_loc]
    banner ""
    if {$pt2 == ""} { tdv_cur $tdv_default dynamics; $im1 delete; return }
    
    set im2 [tdv_point_im -point $pt2 -size 3 -color white]
    $tdv_default add_image $im2
    $tdv_default redraw
    
    banner "Select the second vector end on the screen with the left button."
    set pt3 [get_graphics_loc]
    banner ""
    if {$pt3 == ""} { tdv_cur $tdv_default dynamics; $im1 delete; return }
    
    set im3 [tdv_point_im -point $pt3 -size 3 -color white]
    $tdv_default add_image $im3
    $tdv_default redraw
    
    after 100
    
    set angle 0
    set dist 0
    foreach i {0 1 2} {
	set p  [expr {[lindex $pt2 $i] - [lindex $pt3 $i]}]
	set dist [expr {$dist + $p * $p}]
    }
    set l23 [expr {sqrt($dist)}]
    set dist 0
    foreach i {0 1 2} {
	set p  [expr {[lindex $pt1 $i] - [lindex $pt2 $i]}]
	set dist [expr {$dist + $p * $p}]
    }
    set l12 [expr {sqrt($dist)}]
    set dist 0
    foreach i {0 1 2} {
	set p  [expr {[lindex $pt1 $i] - [lindex $pt3 $i]}]
	set dist [expr {$dist + $p * $p}]
    }
    set l13 [expr {sqrt($dist)}]
    set temp [expr {acos(($l12*$l12+$l13*$l13-$l23*$l23)/(2*$l12*$l13))}]
    set angle [expr {$temp*180/3.1415926}]
    $im1 delete
    $im2 delete
    $im3 delete
    tdv_cur $tdv_default dynamics
    
    mess "Angle is $angle degrees\n"
    return [list $angle]
}

proc med_get_local_location {{varname ""} {do_exp 1} {what "the point"}} {
    return [disp_get_location $varname $do_exp $what 1]
}

proc update_screen_label_point {name var} {
    global screen_label_point
    global tdv_default

    set pos ""
    if { [llength [uplevel \#0 set $var]] == 1 } { 
	set pos [eval ic_geo_get_point_location [uplevel \#0 set $var]]
	
    } elseif {[scan [string trim [uplevel \#0 set $var]] \
	    "%f %f %f" x y z] == 3} {
	set pos "$x $y $z"
	set pos [ic_coords_into_global $pos]
    }
    
    if [info exists screen_label_point($var)] {
	if {$name == ""} {
	    $screen_label_point($var) delete
	    unset screen_label_point($var)
	} elseif {$pos != ""} {
	    $screen_label_point($var) configure -point $pos
	}
    } elseif {($name != "") && ($pos != "")} {
	set im [tdv_text_im -point $pos -text $name]
	$tdv_default add_image $im
	set screen_label_point($var) $im
    }
}

proc update_screen_label_point_activate_all {on} {
    global screen_label_point
    
    foreach nn [array names screen_label_point] {
	$screen_label_point($nn) configure -visible $on
    }
}

proc med_check_bbox {} {
    global tdv_default

    set bb [$tdv_default bbox interesting]
    if {$bb == ""} return
    if [string compare $bb "{0 0 0} {0 0 0}"] {
	set min1 [ic_coords_into_local [lindex $bb 0]]
	set max1 [ic_coords_into_local [lindex $bb 1]]
	set min2 ""; set max2 ""
	foreach a $min1 b $max1 {
	    if {$a > $b} {
		lappend min2 $b; lappend max2 $a
	    } else {
		lappend min2 $a; lappend max2 $b
	    }
	}
	
	mess "Minimum: $min2\n"
	mess "Maximum: $max2\n"
    }
}

proc orient_home_command {} { 
    global tdv_default
    tdv_home $tdv_default 
}

proc orient_command {dir}   { 
    global tdv_default
    tdv_along_axis $tdv_default $dir 
}

proc create_visible_menu {} {
}

proc update_type_visible {t} {
}

proc create_view_menu {} {
}

proc graph_change_shading {} {
}

proc view_toggle_auto_redraw {} {
}

proc set_background_command {col} {
    global tdv_default
    $tdv_default configure -background $col
    $tdv_default redraw
}

proc graphics_loc_command {} {
    global tdv_default
    global tdv_waiting_for_click explicit_location_value
    
    tdv_cancel_rubbox $tdv_default
    
    tdv_set_key_command F9 "set tdv_waiting_for_click($tdv_default) F9"

    set tdv_waiting_for_click($tdv_default) 1
    tkwait variable tdv_waiting_for_click
    set cc $tdv_waiting_for_click($tdv_default)
    unset tdv_waiting_for_click($tdv_default)
    tdv_set_key_command F9 ""
    switch -- [lindex $cc 0] {
	e       { return [lrange $cc 1 end] }
	1       {
	    set pt [lrange [$tdv_default get_3d_point [lindex $cc 1] \
				[lindex $cc 2] 1] 0 2]
	    set explicit_location_value $pt
	    return $pt
	}
	F9 {
	    tdv_set_key_command F9 "set tdv_waiting_for_click(.v.view) F9"
	    tdv_cur $tdv_default dynamics
	    set pb [banner "Dynamics mode - hit F9 to return to selection mode."]
	    tkwait variable tdv_waiting_for_click
	    tdv_cur $tdv_default pick
	    banner $pb
	    return [graphics_loc_command]
	}
	default {
	    return ""
	}
    }
}

proc graphics_loc_command_2d {} {
    global tdv_default
    global tdv_waiting_for_click explicit_location_value
    
    tdv_cancel_rubbox $tdv_default
    
    set tdv_waiting_for_click($tdv_default) 1
    tkwait variable tdv_waiting_for_click
    set cc $tdv_waiting_for_click($tdv_default)
    unset tdv_waiting_for_click($tdv_default)
    switch -- [lindex $cc 0] {
	1 {
	    return [lrange $cc 1 2]
	}
	2 {
	    return 2
	}
	3 {
	    return 3
	}
	default { return "" }
    }
}

# Stuff for graphical interaction.  ----------------------------------

if {[info command tdv_select_action] == ""} {
    proc tdv_select_action {w button double shape spec geopos pos x y} {
    }
    proc tdv_move_action {w button pos x y} {
    }
    proc tdv_release_action {w button pos x y {what_mod 1}} {
    }
}

# savedview: Stuff for saving views by orientation and all -----------

proc savedview_save {v} {
    global savedview tdv_center tdv_rot tdv_scale tdv_pos
    
    set savedview(rot)    $tdv_rot($v)
    set savedview(scale)  $tdv_scale($v)
    set savedview(center) $tdv_center($v)
    set savedview(pos)    $tdv_pos($v)
}

proc savedview_restore {v} {
    global savedview tdv_center tdv_rot tdv_scale tdv_pos
    
    set tdv_rot($v)    $savedview(rot)
    set tdv_scale($v)  $savedview(scale)
    set tdv_center($v) $savedview(center)
    set tdv_pos($v)    $savedview(pos)
    tdv_trans_update $v
}

proc savedview_save_to_file {v} {
    global savedview tdv_center tdv_rot tdv_scale tdv_pos
    
    savedview_save $v    
    set fname [file_selection -new_ok 1 -title "Select screen data file" \
	    -message "File in which to save current view attributes"]
    if {$fname == ""} return    
    set f [open $fname w]    
    puts $f "#Rotation vector\n$savedview(rot)\n#Scale data\n$savedview(scale)"
    puts $f "#Center point\n$savedview(center)\n#Screen position\n$savedview(pos)"
    close $f
}

proc savedview_restore_from_file {v} {
    global savedview tdv_center tdv_rot tdv_scale tdv_pos
    
    savedview_save $v
    
    set fname [file_selection -new_ok 0 -title "Select screen data file" \
	    -message "File from which to load saved view attributes"]
    if {$fname == ""} return
    set f [open $fname r]
    
    set nlines 0
    while {![eof $f]} {
	set l [gets $f]
	incr nlines
	if {"" == $l} continue
	if [string match "#*" $l] {
	    # this is for files created by with comments
	    if [string match "#Rotation vector*" $l] {
		set mode rot
	    } elseif [string match "#Scale data*" $l] {
		set mode scale
	    } elseif [string match "#Center point*" $l] {
		set mode center
	    } elseif [string match "#Screen position*" $l] {
		set mode pos
	    } else {
		ic_mess "Unrecognized view attribute $l"
		continue
	    }
	    set value [gets $f]
	    set savedview($mode) $value
	} else {
	    # this is to support any old style files using Ben K' scripts
	    switch $nlines {
		1 { 
		    if {[llength $l] != 4} { mess "Invalid rotation vector: $l\n" red; return }
		    set savedview(rot) $l
		}
		2 {		    
		    if {[llength $l] != 3} { mess "Invalid scale data: $l\n" red; return }
		    set savedview(scale) $l
		}
		3 { 		    
		    if {[llength $l] != 3} { mess "Invalid center point: $l\n" red; return }
		    set savedview(center) $l
		}
		4 {		    
		    if {[llength $l] != 3} { mess "Invalid screen position: $l\n" red }
		    set savedview(pos) $l
		}
		default {
		    mess "Unrecognized view attribute: $l \n" red
		}
	    }
	}
    }
    
    savedview_restore $v
}

proc savedview_edit {v {top ""}} {
    
    if ![ic_geo_is_loaded] { ic_mess "Geometry not loaded \n" red }
    
    if {$top != ""} {
	set w $top
	set ch [winfo children $w]
	if {$ch != ""} {
	    pack propagate $w 0
	    $w configure -width [winfo width $w] -height [winfo height $w] 
	    foreach ww $ch {
		destroy $ww
	    }
	}
    } else {
	set w .savedview
	if {[winfo exists $w]} { ShowWindow $w ; return }
	toplevel $w
	wm geometry $w +800+600
	wm title $w "Edit saved views"
	form_auto_raise $w
    }
        
    frame $w.data 
    frame $w.buttons
    
    label $w.data.l_cp -text "Center point"
    entry $w.data.e_cp -width 40 -textvar tdv_center($v)
    label $w.data.l_sp -text "Screen position"
    entry $w.data.e_sp -width 40 -textvar tdv_pos($v)
    label $w.data.l_nv -text "Rotation vector"
    entry $w.data.e_nv -width 40 -textvar tdv_rot($v)
    label $w.data.l_sc -text "Scale"
    entry $w.data.e_sc -width 40 -textvar tdv_scale($v)
    bind $w.data.e_cp <Return> "tdv_trans_update $v"
    bind $w.data.e_sp <Return> "tdv_trans_update $v"
    bind $w.data.e_nv <Return> "tdv_trans_update $v"
    bind $w.data.e_sc <Return> "tdv_trans_update $v"
    grid $w.data.l_cp $w.data.e_cp -padx 6 -pady 3
    grid $w.data.l_sp $w.data.e_sp -padx 6 -pady 3
    grid $w.data.l_nv $w.data.e_nv -padx 6 -pady 3
    grid $w.data.l_sc $w.data.e_sc -padx 6 -pady 3
    
    button $w.buttons.save -text "Grab" -command "savedview_save $v" -padx 5
    button $w.buttons.save_in_file -text "Save" -command "savedview_save_to_file $v" -padx 5
    button $w.buttons.get -text "Restore" -command "savedview_restore $v" -padx 5
    button $w.buttons.get_from_file -text "Load" -command "savedview_restore_from_file $v" -padx 5
    button $w.buttons.done -text "Done" -command "savedview_done $w" -padx 5
    grid $w.buttons.get_from_file $w.buttons.save $w.buttons.get $w.buttons.save_in_file \
	$w.buttons.done
    pack $w.data $w.buttons -fill both
    
    if ![info exists savedview(fout)]  {set savedview(fout) "" }
}

proc savedview_done {w} {
    if {[winfo parent $w] == "."} {
	destroy $w
    } else {
	set ch [winfo children $w]
	if {$ch != ""} {
	    pack propagate $w 0
	    $w configure -width [winfo width $w] -height [winfo height $w] 
	    foreach ww $ch {
		destroy $ww
	    }
	}
    }
}
