
# 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 select_rbox {x1 y1 x2 y2} {
    global tdv_current_viewer
    global env
    set try_overlay [expr ![info exists env(ICEM_NO_OVERLAY)]]

    set rbox [tdv_rubbox_im -color orange -x1 $x1 \
		  -y1 $y1 -x2 $x2 -y2 $y2]
    $tdv_current_viewer add_image $rbox
    # add tag for cleaning 
    $tdv_current_viewer add_tag $rbox selection_image
    $rbox configure -overlay $try_overlay
    return $rbox
}

proc select_circle {x1 y1 x2 y2} {
    global tdv_current_viewer
    global env
    set try_overlay [expr ![info exists env(ICEM_NO_OVERLAY)]]

    set circ [tdv_rubcirc_im -color orange -x1 $x1 \
		  -y1 $y1 -x2 $x2 -y2 $y2]
    $tdv_current_viewer add_image $circ
    $tdv_current_viewer add_tag $circ selection_image
    $circ configure -overlay $try_overlay
    return $circ
}

proc select_pline {} {
    global tdv_current_viewer
    global env
    set try_overlay [expr ![info exists env(ICEM_NO_OVERLAY)]]

    set pline [tdv_poly_im -color orange -transform 0 -draw_line 1]
    $tdv_current_viewer add_image $pline
    $tdv_current_viewer add_tag $pline selection_image
    $pline configure -overlay $try_overlay
    return $pline
}

proc select_highlight {im var_name} {
    global select_saved_config
    
    if {$var_name != ""} {
	global $var_name
        set ${var_name}($im) 1
    }
    set select_saved_config($im) \
	    "-width [$im get -width] -color [$im get -color] \
		-name_color [$im get -name_color] -visible [$im get -visible]"
    $im configure -width 3 -color white -name_color red -visible 1
}

proc select_unhighlight {im var_name} {
    global select_saved_config
   
    if {$im == ""} {
	foreach im [array names select_saved_config] {
	    select_unhighlight $im $var_name
	}
	return
    }
    if {$var_name != ""} {
	global $var_name
        set ${var_name}($im) 0
    }
    eval $im configure $select_saved_config($im)
    unset select_saved_config($im)
}

if ![catch {package present Tk}] {
    
    proc select_toggle_dynamics {keys} {
	global tdv_current_viewer select_in_dynamics_prev_banner
	global select_in_dynamics
	
	if ![info exists select_in_dynamics] return
	
	if $select_in_dynamics {
	    select_unset_bindings 0
	    select_set_bindings $keys 0 0 0 ""
	    set select_in_dynamics 0
	    if [info exists select_in_dynamics_prev_banner] {
		banner $select_in_dynamics_prev_banner
		unset select_in_dynamics_prev_banner
	    }
	    select_toolbar_gray 0
	} else {
	    tdv_dynamics_bindings $tdv_current_viewer
	    #bind $tdv_current_viewer <F9> "select_toggle_dynamics $keys"
	    #bind .v <F9> "select_toggle_dynamics $keys"
	    tdv_cur $tdv_current_viewer dynamics
	    bind $tdv_current_viewer c "do_center %x %y"
	    set select_in_dynamics 1
	    set select_in_dynamics_prev_banner \
		[banner "Dynamics mode - hit F9 to return to selection mode."]
	    select_toolbar_gray 1
	}
    }
    
    proc select_turn_off_mouse_bindings {} {
	global tdv_current_viewer
	foreach i {1 2 3} {
	    bind $tdv_current_viewer <Button$i-Motion> ""
	    bind $tdv_current_viewer <Shift-Button$i-Motion> ""
	    bind $tdv_current_viewer <ButtonPress-$i> ""
	    bind $tdv_current_viewer <ButtonRelease-$i> ""
	    bind $tdv_current_viewer <Shift-ButtonPress-$i> ""
	    bind $tdv_current_viewer <Shift-ButtonRelease-$i> ""
	}
    }
    
    proc select_set_bindings {keys put_toolbar inc_dim inc_type title} {
	global tdv_current_viewer aie_select_options select_option
	global select_in_dynamics tdv_mouse_bindings select_cad_autohex_options
	global saved_question_shortcut

	# next line is necessary because selection may be called when busy is "On"
	busy reset
	
	foreach i {0 1 2 3} {
	    if ![info exists select_option($i)] { set select_option($i) 1 }
	}
	
	select_turn_off_mouse_bindings
	
	set s $tdv_mouse_bindings(select)
	set d $tdv_mouse_bindings(done)
	set c $tdv_mouse_bindings(cancel)
	bind $tdv_current_viewer <ButtonPress-$s> {
	    global tdv_waiting_for_click
	    if [info exists tdv_waiting_for_click($tdv_current_viewer)] {
		set tdv_waiting_for_click($tdv_current_viewer) "%b %x %y"
	    } else {
		set select_action "press %x %y"
	    }
	}
	bind $tdv_current_viewer <ButtonRelease-$s>       { set select_action "release %x %y" }
	bind $tdv_current_viewer <Shift-ButtonRelease-$s> { set select_action "shiftrelease %x %y" }
	bind $tdv_current_viewer <Button$s-Motion>        { set select_action "move %x %y" }
	bind $tdv_current_viewer <Motion>                 { set select_action "nb_move %x %y" }
	bind $tdv_current_viewer <ButtonPress-$d>         { set select_action "done" }
	bind $tdv_current_viewer <ButtonPress-$c>         { set select_action "back" }
	tdv_push_key_command bracketright      { set select_action "done" }
	tdv_push_key_command bracketleft       { set select_action "back" }
    tdv_push_key_command z "" 
	tdv_push_key_command F9 "select_toggle_dynamics $keys"
	
	tdv_cur $tdv_current_viewer pick
	
	set select_in_dynamics 0
	
	tdv_push_key_command Shift-question "select_print_help $keys"
	
	set toolbar ""
	
	if $inc_dim {
	    lappend toolbar d0 "" d1 "" d2 "" d3 ""
	}
	
	switch $keys {
	    1 - 1-2 {
		tdv_push_key_command p "set select_action polygon"
		#tdv_push_key_command Shift-C "set select_action circle"
		tdv_push_key_command v "set select_action visible"
		lappend toolbar polygon p visible v
		# circle Shift-c
		
		if ![info exists aie_select_options] {
		   tdv_push_key_command f "set select_action family"
		   lappend toolbar family f
		}
		tdv_push_key_command x "set select_action cancel"
		tdv_push_key_command n "set select_action goto_next"
		if {$keys != "1-2"} {
		    tdv_push_key_command m "set select_action region_type"
		    tdv_push_key_command Shift-H "set select_action all_edge_select"
		    lappend toolbar cancel x region_type m goto_next n all_edge_select Shift-H
		} else {
		    lappend toolbar cancel x goto_next n 
		}
		if ![info exists select_cad_autohex_options] {
		    if {$keys != "1-2"} {
		        tdv_push_key_command b "set select_action blanked"
		        tdv_push_key_command Shift-N "set select_action name"
		        tdv_push_key_command l "set select_action flood"
		        tdv_push_key_command k "set select_action flood_one"
		        tdv_push_key_command g "set select_action feature_angle"
		        tdv_push_key_command o "set select_action boundary_type"
		        tdv_push_key_command a "set select_action all"
		        lappend toolbar blanked b name Shift-N flood l flood_one_geom k feature_angle g boundary_type o all a
		    } else {
		        tdv_push_key_command b "set select_action blanked"
		        tdv_push_key_command Shift-N "set select_action name"
		        tdv_push_key_command a "set select_action all"
		        lappend toolbar blanked b name Shift-N all a
		    }
		}
		if [info exists aie_select_options] {
		    if {$keys != "1-2"} {
		        tdv_push_key_command Shift-S "set select_action subset"
		        tdv_push_key_command Shift-P "set select_action part"
		        tdv_push_key_command Shift-N "set select_action name"
		        lappend toolbar subset Shift-S part Shift-P name Shift-N
		    } else {
		        tdv_push_key_command Shift-N "set select_action name"
		        lappend toolbar name Shift-N
		    }
		}
		if {$keys != "1-2"} {
		    lappend toolbar preselect ""
		}

		if $inc_type { lappend toolbar mesh "" }
	    }
	    2 {
		tdv_push_key_command a "set select_action all"
		tdv_push_key_command v "set select_action visible"
		tdv_push_key_command p "set select_action polygon"
		tdv_push_key_command Shift-C "set select_action circle"
		tdv_push_key_command m "set select_action region_type"
		tdv_push_key_command x "set select_action cancel"
		
		lappend toolbar all a visible v polygon p circle Shift-c region_type m cancel x
		
		if [info exists aie_select_options] {
		    tdv_push_key_command Shift-P "set select_action part"
		    tdv_push_key_command Shift-N "set select_action nnum"
		    lappend toolbar part Shift-P nnum Shift-N
		    
		} else {
		    tdv_push_key_command f "set select_action family"
		    lappend toolbar family f 
		}
		
		if $inc_type { lappend toolbar geom "" }
	    }
	    3 {
		tdv_push_key_command a "set select_action all"
		tdv_push_key_command n "set select_action new"
		tdv_push_key_command p "set select_action polygon"
		tdv_push_key_command Shift-C "set select_action circle"
		tdv_push_key_command m "set select_action region_type"
		tdv_push_key_command x "set select_action cancel"
		
		lappend toolbar all a new n polygon p circle Shift-c region_type m cancel x
		if [info exists aie_select_options] {
		    tdv_push_key_command Shift-P "set select_action part"
		    tdv_push_key_command Shift-N "set select_action nnum"
		    lappend toolbar part Shift-P nnum Shift-N
		} else {
		    tdv_push_key_command f "set select_action family"
		    lappend toolbar family f 
		}
		
		if $inc_type { lappend toolbar geom "" }
	    }
	    4 {
		tdv_push_key_command e "set select_action explicit"
		tdv_push_key_command x "set select_action cancel"
		
		lappend toolbar explicit e cancel x
	    }
	    5 {
		tdv_push_key_command p "set select_action polygon"
		#tdv_push_key_command Shift-C "set select_action circle"
		tdv_push_key_command l "set select_action flood"
		#tdv_push_key_command i "set select_action flood_between"
		tdv_push_key_command k "set select_action flood_one"
		tdv_push_key_command Shift-I "set select_action flood_split2"
		tdv_push_key_command x "set select_action cancel"
		tdv_push_key_command m "set select_action region_type"
		tdv_push_key_command g "set select_action feature_angle"
		
		lappend toolbar polygon p flood l flood_between i flood_one_geom k flood_split2 Shift-I \
		    cancel x region_type m feature_angle g
		#circle Shift-c
		if $inc_type { lappend toolbar mesh "" }
	    }
	    6 {
		tdv_push_key_command x "set select_action cancel"
		tdv_push_key_command n "set select_action proj_none"
		tdv_push_key_command s "set select_action proj_surf"
		tdv_push_key_command c "set select_action proj_curve"
		
		lappend toolbar cancel x proj_none n proj_surf s proj_curve c
		if $inc_type { lappend toolbar mesh "" }
	    }
	    7 {
		tdv_push_key_command p "set select_action polygon"
		tdv_push_key_command Shift-C "set select_action circle"
		tdv_push_key_command v "set select_action visible"
		tdv_push_key_command b "set select_action blanked"
		tdv_push_key_command x "set select_action cancel"
		tdv_push_key_command m "set select_action region_type"
		tdv_push_key_command a "set select_action all"
		tdv_push_key_command t "set select_action geo_proj"
		tdv_push_key_command 0 "set select_action dim0"
		tdv_push_key_command 1 "set select_action dim1"
		tdv_push_key_command 2 "set select_action dim2"
		tdv_push_key_command 3 "set select_action dim3"
		tdv_push_key_command l "set select_action flood_angle"
		tdv_push_key_command r "set select_action flood_curve"
		tdv_push_key_command k "set select_action flood_one"
		tdv_push_key_command g "set select_action feature_angle"
		
		lappend toolbar polygon p visible v blanked b cancel x region_type m all a
		
		if [info exists aie_select_options] {
		    tdv_push_key_command Shift-S "set select_action subset"
		    tdv_push_key_command Shift-P "set select_action part"
		    tdv_push_key_command Shift-E "set select_action enum"
		    tdv_push_key_command Shift-M "set select_action mater"
		    tdv_push_key_command Shift-R "set select_action prop"
		    
		    lappend toolbar subset Shift-S part Shift-P enum Shift-E \
			mater Shift-M prop Shift-R
		} else {
		    tdv_push_key_command f "set select_action family"
		    lappend toolbar family f
		}
		
		lappend toolbar geo_proj t circle Shift-C dim0 0 dim1 1 dim2 2 dim3 3 dim3-1 3-1 dim3-2 3-2 \
		    flood_angle l flood_curve r feature_angle g flood_one k
		if $inc_type { lappend toolbar geom "" }
	    }
	    8 - 8-2 - 8-3 - 8-4 {
		# 8   For hexa vertex selection
		# 8-2 For hexa edge selection
		# 8-3 For hexa face selection
		# 8-4 For hexa block selection
		tdv_push_key_command p "set select_action polygon"
		tdv_push_key_command v "set select_action visible"
		tdv_push_key_command a "set select_action all"
		tdv_push_key_command Shift-C "set select_action circle"
		lappend toolbar polygon p visible v 
		if {$keys == "8-4"} {
		    tdv_push_key_command b "set select_action blanked"
		    lappend toolbar blanked b	    
		}
		lappend toolbar circle Shift-c
		
		if {$keys == "8" || $keys == "8-4"} {
		    tdv_push_key_command Shift-N "set select_action hnum"
		    lappend toolbar hnum Shift-n
		}
		tdv_push_key_command x "set select_action cancel"
		tdv_push_key_command m "set select_action region_type"
		lappend toolbar cancel x region_type m
		
		if {$keys == "8-3" || $keys == "8-4"} {
		    tdv_push_key_command d "set select_action corners"
		    lappend toolbar corners d
		}
		if {$keys == "8-3"} {
		    tdv_push_key_command Shift-B "select_toggle_all_faces"
            lappend toolbar select_toggle_all_faces Shift-B
		}
		tdv_push_key_command Shift-S "set select_action subset"
		tdv_push_key_command Shift-P "set select_action part"
		lappend toolbar subset Shift-S part Shift-P
		if {$keys == "8-4"} {
		    tdv_push_key_command Shift-H "set select_action block_by_vertex"
            lappend toolbar block_by_vertex Shift-H
		}
		if {$keys == "8-2"} {
		    tdv_push_key_command n "set select_action highlight_segment"
            lappend toolbar highlight_segment n
		}
	    }
	    9 {
		# For location (xyz) selection
		tdv_push_key_command x "set select_action cancel"
		tdv_push_key_command 1 "do_toggle_global allow_plane_selection 1 0"
		tdv_push_key_command 2 "do_toggle_global allow_plane_selection 2 0"
		tdv_push_key_command 3 "do_toggle_global allow_plane_selection 3 0"
		tdv_push_key_command 4 "do_toggle_global allow_plane_selection 4 0"
		tdv_push_key_command 5 "do_toggle_global va_set(xyz_on_mesh) 1 0" 
		tdv_push_key_command 6 "do_toggle_global va_set(xyz_show_xyz) 1 0"
		tdv_push_key_command 7 "do_toggle_global va_set(xyz_show_typename) 1 0"
		tdv_push_key_command 8 "do_toggle_global va_set(xyz_show_entity) 1 0"
		lappend toolbar xyz_on_plane 1  xyz_on_plane_xy 2 xyz_on_plane_xz 3 xyz_on_plane_yz 4 xyz_on_mesh 5 xyz_show_xyz 6 xyz_show_typename 7 xyz_show_entity 8 cancel x
	    }
	    10 {
	    # For structured entities selection
		tdv_push_key_command p "set select_action polygon"
		tdv_push_key_command v "set select_action visible"
		tdv_push_key_command x "set select_action cancel"
		tdv_push_key_command Shift-B "set select_action all_boundary"
		tdv_push_key_command Shift-I "set select_action all_block"
		tdv_push_key_command m "set select_action region_type"
		tdv_push_key_command a "set select_action all"
		lappend toolbar polygon p visible v cancel x all_boundary Shift-B all_block Shift-I region_type m all a
		if [info exists aie_select_options] {
		    tdv_push_key_command Shift-P "set select_action part"
		    lappend toolbar part Shift-P
		}
	    }
	}
	if $put_toolbar { select_toolbar $toolbar $title }
    }
}

proc select_print_help {keys} {
    global select_cad_autohex_options aie_select_options
    
    switch $keys {
	1 - 1-2 {
	    if [info exists select_cad_autohex_options] {
		mess "p" blue; mess " = polygon; "
		mess "m" blue; mess " = toggle region mode; "
		mess "x" blue; mess " = cancel\n"
		mess "v" blue; mess " = all visible; "
		if [info exists aie_select_options] {
		    mess "f" blue; mess " = in a family; "
		}
		mess "n" blue; mess " = go to next"
	    } else {
		mess "p" blue; mess " = polygon; "
		if {$keys != "1-2"} {
		    mess "m" blue; mess " = toggle region mode; "
		}
		mess "x" blue; mess " = cancel\n"
		mess "a" blue; mess " = all items; "
		mess "v" blue; mess " = all visible; "
		mess "b" blue; mess " = all blanked\n"
		
		#mess "e" blue; mess " = by name;\n"
		if {$keys != "1-2"} {
		    mess "l" blue; mess " = flood-fill; "
	        mess "k" blue; mess " = flood-fill-one;\n"
		    mess "g" blue; mess " = set feature angle; "
		    mess "o" blue; mess " = toggle boundary mode;\n"
		}
		mess "n" blue; mess " = go to next; "
		if [info exists aie_select_options] {
		    if {$keys != "1-2"} {
		        mess "S" blue; mess " = in a subset; "
		        mess "P" blue; mess " = in a part;\n"
		    }
		    mess "N" blue; mess " = by name;\n"
		} else {
		    mess "f" blue; mess " = in a part; "
		}
	    }
	    mess "\n"
	}
	2 {
	    mess "a" blue; mess " = all nodes; "
	    mess "v" blue; mess " = all visible; "
	    mess "p" blue; mess " = polygon; "
	    mess "m" blue; mess " = toggle region mode\n"
	    if [info exists aie_select_options] {
		    mess "Shift-N" blue; mess " = by number; "
		} else {
		    mess "f" blue; mess " = in a part; "
		}
	    mess "x" blue; mess " = cancel\n"
	}
	3 {
	    mess "a" blue; mess " = all nodes; "
	    mess "n" blue; mess " = new node; "
	    mess "p" blue; mess " = polygon; "
	    mess "m" blue; mess " = toggle region mode\n"
	    if [info exists aie_select_options] {
		mess "Shift-N" blue; mess " = by number; "
	    } else {
		mess "f" blue; mess " = in a part; "
	    }
	    
	    mess "x" blue; mess " = cancel\n"
	}
	4 {
	    mess "e" blue; mess " = explicit; "
	    mess "x" blue; mess " = cancel\n"
	}
	5 {
	    mess "p" blue; mess " = polygon; "
	    mess "m" blue; mess " = toggle region mode; "
	    mess "x" blue; mess " = cancel;\n"
	    mess "l" blue; mess " = select all attached;"
	    mess "k" blue; mess " = select one attached layer;\n"
	    mess "Shift-I" blue; mess " = split edges and fill between;\n"
	    mess "i" blue; mess " = fill between two points; "
	    mess "g" blue; mess " = set feature angle;\n"
	    
	}
	6 {
	    mess "s" blue; mess " = project to surface; "
	    mess "c" blue; mess " = project to curve;\n"
	    mess "n" blue; mess " = project to none;"
	    mess "x" blue; mess " = cancel;\n"
	}
	7 {
	    mess "p" blue; mess " = polygon; "
	    mess "m" blue; mess " = toggle region mode; "
	    mess "x" blue; mess " = cancel\n"
	    mess "v" blue; mess " = all visible; "
	    mess "b" blue; mess " = all blanked; "
	    mess "a" blue; mess " = all items\n"
	    mess "t" blue; mess " = projected on geom entity\n"
	    mess "0" blue; mess " = select all nodes; "
	    mess "1" blue; mess " = select all lines; "
	    mess "2" blue; mess " = select all surfaces; "
	    mess "3" blue; mess " = select all volume elements;\n"
	    if [info exists aie_select_options] {
		mess "Shift-S" blue; mess " = in a subset; "
		mess "Shift-P" blue; mess " = in a part;\n"
		mess "Shift-E" blue; mess " = by number; "
		mess "Shift-M" blue; mess " = by material; "
		mess "Shift-R" blue; mess " = by property\n"
	    } else {
		mess "f" blue; mess " = in a part; "
	    }
	}
	8 - 8-2 - 8-3 - 8-4 {
	    mess "p" blue; mess " = polygon; "
	    mess "Shift-C" blue; mess " = circle; "
	    if {$keys == "8-3"} {
	        mess "Shift-B" blue; mess " = toggle between all faces and boundary faces;\n"
	    }
	    if {$keys == "8-4"} {
	        mess "Shift-V" blue; mess " = select block by vertex;\n"
	    }
	    if {$keys == "8-2"} {
	        mess "n" blue; mess " = select next edge segment;\n"
	    }
	    mess "d" blue; mess " = diagonal vertices; "
	    mess "x" blue; mess " = cancel\n"
	    mess "v" blue; mess " = all visible; "
	    mess "m" blue; mess " = toggle region mode; "
	    mess "S" blue; mess " = in a subset; "
	    mess "P" blue; mess " = in a part;\n"
	}
	9 {
	     mess "x" blue; mess " = cancel\n"
	     mess "1" blue; mess " = Toggle allow any plane selection; "
         mess "2" blue; mess " = Toggle allow on XY plane selection; "
         mess "3" blue; mess " = Toggle allow on XZ plane selection; "
         mess "4" blue; mess " = Toggle allow on YZ plane selection\n"
         mess "5" blue; mess " = Toggle allow on Mesh/Block selection\n"
         mess "6" blue; mess " = Toggle show location\n"
         mess "7" blue; mess " = Toggle show entity name\n"
         mess "8" blue; mess " = Toggle highlight entity\n"
	}
    }
}

proc select_unset_bindings {dismiss_toolbar} {
    global tdv_current_viewer saved_question_shortcut select_in_dynamics
        
    tdv_dynamics_bindings $tdv_current_viewer
    
    foreach k { Shift-question p m a v b l f c s g e t x n 0 1 2 3 4 5 6 7 8 z r k o d 
	Shift-C Shift-S Shift-P Shift-N Shift-C Shift-H Shift-I bracketleft bracketright 
	Shift-M Shift-E Shift-R Shift-B Shift-V} {
	tdv_pop_key_command $k
    }
    tdv_set_key_command F9 off
    
    tdv_cur $tdv_current_viewer dynamics
    bind $tdv_current_viewer c "do_center %x %y"
    catch {unset select_in_dynamics}
    
    if $dismiss_toolbar { select_toolbar "" "" }
}

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

# This just returns sets of N points that are gotten via the screen...

proc select_locations {num {mess ""} {preselect ""} {local_coords 0} 
		       {only_endpoints 0}} {
    global tdv_current_viewer
    global select_action options tdv_mouse_bindings
    
    if {$mess == ""} {
	set mess "$num points"
    }
    foreach s { select done cancel } {
	set b_$s [lindex {"" left middle right} $tdv_mouse_bindings($s)]
    }
    
    banner "Select $mess with the $b_select button; $b_done = done,\
	$b_cancel = back up / cancel, '?' = list options."
    select_set_bindings 4 0 0 0 ""
    
    set finished 0
    set nstuff 0
    set stuff ""
    
    foreach pt $preselect {
	set im [tdv_point_im -point $pt -size 3 -color white]
	$tdv_current_viewer add_image $im
	$tdv_current_viewer redraw
	lappend stuff $im
	incr nstuff
    }
    
    while {!$finished} {
	
	tkwait variable select_action
	
	switch [lindex $select_action 0] {
	    done {
		set finished 1
	    }
	    back {
		if !$nstuff {
		    set finished 1
		} else {
		    incr nstuff -1
		    set stuff [lrange $stuff $nstuff end]
		}
	    }
	    cancel {
		set finished -1
	    }
	    press {
	    }
	    release {
		set x [lindex $select_action 1]
		set y [lindex $select_action 2]
		set pt [lrange [$tdv_current_viewer get_3d_point $x $y [expr !$only_endpoints]] 0 2]
		if {$pt != ""} {
		set im [tdv_point_im -point $pt -size 5 -color yellow]
		$tdv_current_viewer add_image $im
		$tdv_current_viewer redraw
		lappend stuff $im
		incr nstuff
		}
	    }
	    explicit {
		global explicit_location_value
		
		if ![info exists explicit_location_value] {
		    set explicit_location_value ""
		}
		set pt [question_box .exp_loc "Explicit location" \
			    "Input the cordinates separated by spaces." \
			    $explicit_location_value]
		if {$pt != ""} {
		    set explicit_location_value $pt
		    set im [tdv_point_im -point $pt -size 3 -color white]
		    $tdv_current_viewer add_image $im
		    $tdv_current_viewer redraw
		    lappend stuff $im
		    incr nstuff
		}
	    }
	}
	if {$nstuff >= $num} { set finished 1 }
    }
    select_unset_bindings 1
    banner ""
    
    set ret ""
    if {$nstuff == $num} {
	foreach im $stuff {
	    set pt [$im get -point]
	    if {$local_coords && ([info command ic_coords_into_local] != "")} {
		set pt [ic_coords_into_local $pt]
	    }
	    lappend ret $pt
	}
    }
    foreach im $stuff { $im delete }
    return $ret
}

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

# This just asks the user to type yes or no

proc select_query {mess opts} {
    global select_action
    
    banner $mess
    
    set i 0
    foreach k $opts {
	tdv_push_key_command $k "set select_action $i"
	incr i
    }
    
    tkwait variable select_action
    
    foreach k $opts {
	tdv_pop_key_command $k
    }
    
    banner ""
    if ![scan $select_action %d num] { set num -1 }
    return $select_action
}

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

# If sel_type is "part" that will return the families for a part
# If it's "part_name" then it will return the part names themselves
# FIXME - this is kind of confusing

proc select_families {sel_type multiple allow_new {mess ""}
		      {famvar fam_visible} {wpos +300+300} {title ""}} {
    global $famvar family_part_select family_part_mult_select
    global ai_environment family_part_preselect
    
    # for backward compatibility
    if {$sel_type == "0"} { set sel_type family }
    if {$sel_type == "1"} { set sel_type family } ;# No more color\ selection
    if { ([info exists ai_environment] && $ai_environment) } {
	if {$sel_type == "family"} {
	    set sel_type part
	}
    }
    
    set family_part_select ""
    catch {unset family_part_mult_select}
   
    form_kill .family_part_select
    if {$title == ""} {
	if {$sel_type == "part_name"} {
	    set title "Select part"
	} else {
	    set title "Select $sel_type"
	}
    }

    if $multiple {
        set buts [list accept [list All "select_families_all 1"] [list None "select_families_all 0"] [list {Screen} "select_families_on_screen $sel_type $multiple"] cancel]
    } else {
        if $allow_new {
            set buts [list accept [list {Screen} "select_families_on_screen $sel_type $multiple"] cancel]
        } else {
            set buts [list [list {Screen} "select_families_on_screen $sel_type $multiple"] cancel]
        }
    }
    set d [form_init .family_part_select $title "" $buts]
    
    set n 0
    if {$mess != ""} {
        form_label $d.mess $mess {0 0}
        $d.mess configure -justify l
    }

    if [catch {ic_geo_list_families} partnames] {
        set partnames [array names $famvar]
    }

    foreach f $partnames {
        lappend found([lindex [split $f :] 0]) $f
    }

    if [catch {aie_list_parts 0} fams] {
        set fams [lsort [array names found]]
    }

    if {$sel_type == "subpart"} {
        set meshparts ""
        foreach fam $fams {
            if [ic_uns_count_in_families $fam] {
                lappend meshparts $fam
            }
        }
        set fams $meshparts
    }

    if {[llength $fams] > 10} {
        set sw [form_scroller $d.stuff 300 {1 0}]
    } else {
        set sw $d.stuff; form_frame $sw ridge 2 {1 0}
    }

    set nfam [llength $fams]
    set nrow [expr ($nfam + 2) / 3]

    set max_len 20
    foreach fam $fams {
        set l [string length $fam]
        if {$max_len < $l} {
            set max_len $l
        }
    }

    set max_len [expr $max_len + 1]
    set button_width 20
    
    if {$max_len > 20 && $max_len <= 40} {
        set button_width [expr $max_len + 2]
    } elseif {$max_len > 40 && $max_len <= 60} {
        set button_width [expr $max_len + 4]
        set nrow [expr ($nfam + 2) / 2]
    } elseif {$max_len > 60 && $max_len <= 80} {
        set button_width [expr $max_len + 6]
        set nrow [expr ($nfam + 2) / 2]
    } elseif {$max_len > 80} {
        set button_width 100
        set nrow [expr ($nfam + 2) / 1]
    }

    if {$button_width > 100} { set button_width 100 }
    
    foreach fam $fams {
        set col [family_color_for_name $fam]
        if {[string length $fam] > $button_width} {
            set famn "[string range $fam 0 [expr $button_width - 3]]..."
        } else {
            set famn $fam
        }
        set bubble_create($fam) 1
        set r [expr $n % $nrow]
        set c [expr $n / $nrow]
        if $multiple {
            form_checkbutton $sw.but$n $famn family_part_mult_select($fam) "$r $c" "" "" "nonbool"
            if [info exists family_part_preselect($fam)] {
                set family_part_mult_select($fam) 1
            } else {
                set family_part_mult_select($fam) 0
            }
        } else {
            form_button $sw.but$n $famn "set family_part_select \"$fam\"; form_done .family_part_select" "$r $c"
        }
        bubble_clear $sw.but$n
        if [info exists bubble_create($fam)] {
            bubble_define $sw.but$n "$fam"
        }
        $sw.but$n configure -background $col -activebackground $col -width $button_width
        incr n
    }
    catch {array set family_part_preselect {}}

    if $allow_new {
        form_frame $d.new flat 0 {2 0}
        form_label $d.new.l "New $sel_type:" {0 0}
        form_entry $d.new.e family_part_select string {0 1}
        bind $d.new.e <Key-Return> {
            set form_done_flag(.family_part_select) 1
            form_done .family_part_select
        }
    }
    form_finish $wpos
    if [llength $fams] {
        form_scroller_hack $d.stuff
    }
    if ![form_wait .family_part_select] { return "" }
    if $multiple {
        set ret ""
        foreach ff [array names family_part_mult_select] {
            if $family_part_mult_select($ff) {
                lappend ret $ff
            }
        }
        if {$sel_type != "part_name"} {
            set ret2 ""
            foreach r $ret {
                if { [info exists found($r)] } {
                    set ret2 [concat $ret2 $found($r)]
                }
            }
            set ret $ret2
        }
        return $ret
    } else {
        if {$family_part_select == ""} {
            return ""
        } elseif {0 && [info exists found($family_part_select)]} {
            return $found($family_part_select)
        } else {
            return [string toupper $family_part_select]
        }
    }
}

proc select_families_all {on} {
    global family_part_mult_select
    foreach ff [array names family_part_mult_select] {
	set family_part_mult_select($ff) $on
    }
}

proc select_families_on_screen {sel_type multiple} {
    global family_part_select family_part_mult_select
    
    top_withdraw .family_part_select
    set sel [geo_select_either entity [expr 1 - $multiple] "a part on the screen"]
    if {$sel == ""} {
	form_cancel .family_part_select
    } elseif $multiple {
	foreach s $sel {
	    if [string match uns_sel* $s] {
		foreach f [ic_uns_subset_list_families $s] {
		    set family_part_mult_select([lindex [split $f :] 0]) 1
		}
	    } else {
		set f [ic_geo_get_family [lindex $s 0] [lindex $s 1]]
		set family_part_mult_select([lindex [split $f :] 0]) 1
	    }
	}
    } else {
	if [string match uns_sel* $sel] {
	    set f [lindex [ic_uns_subset_list_families $sel] 0]
	} else {
	    set f [ic_geo_get_family [lindex [lindex $sel 0] 0] [lindex [lindex $sel 0] 1]]
	}
	set family_part_select [lindex [split $f :] 0]
    }
    form_done .family_part_select
}

proc select_family_set_var {var} {
    set fam [select_families 0 0 1]
    if {$fam != ""} { uplevel \#0 set $var $fam }
}

proc select_families_by_premesh {type multiple allow_new {wpos +300+300}} {
    global family_part_select family_part_mult_select smooth_multi_block
    global use_output_blocks family_part_preselect
    
    set family_part_select ""
    set sel_type part
    catch {unset family_part_mult_select}
   
    form_kill .family_part_select
    set title "Select pre-mesh part"

    if $multiple {
	set buts [list accept \
	         [list All "select_families_all_by_premesh 1 $type"] \
	         [list None "select_families_all_by_premesh 0 $type"] \
	         cancel]
    } else {
	if $allow_new {
	    set buts [list accept [list {Screen} "select_families_on_screen $sel_type $multiple"] cancel]
	} else {
	    set buts [list [list {Screen} "select_families_on_screen $sel_type $multiple"] cancel]
	}
    }
    set d [form_init .family_part_select $title "" $buts]
        
    set premesh_families ""
    if {$type == "face"} {
        foreach pf [array names smooth_multi_block faceFamily,*] {
            set pre_fam [lindex [split $pf ,] 1]
            if {$pre_fam == "ORFN"} continue
            lappend premesh_families $pre_fam
        }
    } elseif {$type == "vertex"} {
        foreach pre_fam [ic_geo_list_families] {
            if {$pre_fam == "ORFN"} continue
            if [ic_geo_count_in_family point $pre_fam] {
                lappend premesh_families $pre_fam
            }
        }
    } elseif {$type == "block"} {
        foreach pf [array names smooth_multi_block VolumeBlockParts,*] {
            set pre_fam [lindex [split $pf ,] 1]
            if {$pre_fam == "ORFN"} continue
            lappend premesh_families $pre_fam
        }
    }
    set nfam [llength $premesh_families]
    if {$nfam > 10} {
        set sw [form_scroller $d.stuff 300 {1 0}]
    } else {
        set sw $d.stuff; form_frame $sw ridge 2 {1 0}
    }
    set r 0
    foreach fam [lsort -dictionary $premesh_families] {
        set col [family_color_for_name $fam]
        set famn $fam
        if $multiple {
            form_checkbutton $sw.but$r $famn family_part_mult_select($fam) "$r 0 -sticky nsew" "" \
                "show_families_by_premesh $type" "nonbool"
            if [info exists family_part_preselect($type,$fam)] {
                set family_part_mult_select($fam) 1
            } else {
                set family_part_mult_select($fam) 0
            }
        } else {
            form_button $sw.but$r $famn "set family_part_select \"$fam\"; form_done .family_part_select" "$r 0 -sticky nsew"
        }
        bubble_clear $sw.but$r
        if {[string length $famn] > 20} {
            bubble_define $sw.but$r "$fam"
        }
        $sw.but$r configure -background $col -activebackground $col
        incr r
    }
    
    if $allow_new {
	form_frame $d.new flat 0 {2 0}
	form_label $d.new.l "New $sel_type:" {0 0}
	form_entry $d.new.e family_part_select string {0 1}
	bind $d.new.e <Key-Return> {
	    set form_done_flag(.family_part_select) 1
	    form_done .family_part_select
	}
    }
    form_finish $wpos
    if {$nfam > 10} {
        form_scroller_hack $d.stuff
    }
    set min_width [winfo reqwidth .family_part_select.bottom]
    grid columnconfigure $sw 0 -minsize $min_width
    catch { array set family_part_preselect {} }
    set ret [form_wait .family_part_select]
    switch $type {
        face {
            set cmd "display_super_faces [range_string] [family_activename_string] erase_icon"
            hex_command "$cmd"
        }
        block {
            hex_command "display_elements erase"
            hex_command "mark_blocks unmark"
        }
    }    
    if !$ret { return "" }
    if $multiple {
        set ret ""
	foreach ff [array names family_part_mult_select] {
	    if $family_part_mult_select($ff) {
	        lappend ret $ff
	    }
	}
	return $ret
    } else {
	if {$family_part_select == ""} {
	    return ""
	} else {
	    return [string toupper $family_part_select]
	}
    }
}

proc show_families_by_premesh {type} {
    global smooth_multi_block use_output_blocks family_part_mult_select

    if ![ic_hex_blocking_loaded] return
    if {$type == "vertex"} return
    switch $type {
        vertex { return }
        face {
            set cmd "display_super_faces [range_string] [family_activename_string] erase_icon"
            hex_command "$cmd"
            set pre_faces ""
            foreach ff [array names family_part_mult_select] {
                if !$family_part_mult_select($ff) continue
                append pre_faces "$smooth_multi_block(faceFamily,$ff) "
            }
            aie_hex_multiblock_display_faces 1
            if {$pre_faces == ""} return  
            set color white
            set len_topo_nums [llength $pre_faces]
            set cmd "display_super_faces [range_string] [family_activename_string] color $color \
                     preselected_faces $len_topo_nums $pre_faces only_listed show_full"
            if $use_output_blocks { append cmd " output_blocks" } 
            hex_command "$cmd"
        }
        block {            
            hex_command "display_elements erase"
            hex_command "mark_blocks unmark"
            set pre_blocks ""
            foreach ff [array names family_part_mult_select] {
                if !$family_part_mult_select($ff) continue
                append pre_blocks "$smooth_multi_block(VolumeBlockParts,$ff) "
            }
            foreach block $pre_blocks {
	        set cmd "mark_blocks superblock $block"
	        if $use_output_blocks { append cmd " output_blocks" }
	        hex_command $cmd
            }
            set cmd "display_elements marked m [volume_activename_string] -not_blanked -solid super"            
            if $use_output_blocks { append cmd " output_blocks" }
            hex_command "$cmd"
        }
    }
}

proc select_families_all_by_premesh {on type} {
    global family_part_mult_select
    foreach ff [array names family_part_mult_select] {
	set family_part_mult_select($ff) $on
    }
    show_families_by_premesh $type
}

proc select_struct_families {type {wpos +300+300}} {
    global family_part_select family_part_mult_select family_part_preselect
    
    set family_part_select ""
    catch { unset family_part_mult_select }    
    set parts ""
    if {$type == "domain" || $type == "subface" || $type == "edge" || $type == "vertex"} {
        foreach p [ic_str_list_families] {
            if {[ic_str_list_in_families $type $p] != ""} {
                lappend parts $p
            }
        }
    }    
    form_kill .family_part_select
    set title "Select structured part"
    set buts [list accept \
	     [list All "select_struct_families_all 1 $type"] \
	     [list None "select_struct_families_all 0 $type"] \
	     cancel]
    set d [form_init .family_part_select $title "" $buts]
           
    set nparts [llength $parts]
    if {$nparts > 10} {
        set sw [form_scroller $d.stuff 300 {1 0}]
    } else {
        set sw $d.stuff; form_frame $sw ridge 2 {1 0}
    }
    set r 0
    foreach p [lsort -dictionary $parts] {
        set col [family_color_for_name $p]
        form_checkbutton $sw.but$r $p family_part_mult_select($p) "$r 0 -sticky nsew" "" \
                 "show_struct_families $type" "nonbool"
        if [info exists family_part_preselect($type,$p)] {
            set family_part_mult_select($p) 1
        } else {
            set family_part_mult_select($p) 0
        }
        bubble_clear $sw.but$r
        if {[string length $p] > 20} {
            bubble_define $sw.but$r "$p"
        }
        $sw.but$r configure -background $col -activebackground $col
        incr r
    }
    form_finish $wpos
    if {$nparts > 10} {
        form_scroller_hack $d.stuff
    }
    set min_width [winfo reqwidth .family_part_select.bottom]
    grid columnconfigure $sw 0 -minsize $min_width
    catch { array set family_part_preselect {} }
    set ret [form_wait .family_part_select]
    switch $type {
        domain - subface { str_select_unhighlight $type "" "" }
    }
    if !$ret { return "" }
    set ret ""
    foreach p [array names family_part_mult_select] {
        if $family_part_mult_select($p) {
            lappend ret $p
        }
    }
    return $ret
}

proc show_struct_families {type} {
    global family_part_mult_select

    set parts ""
    str_select_unhighlight $type "" ""
    foreach p [array names family_part_mult_select] {
        set nums [ic_str_list_in_families $type $p]
        ic_str_highlight $type $nums $family_part_mult_select($p)
    }
}

proc select_struct_families_all {on type} {
    global family_part_mult_select
    foreach p [array names family_part_mult_select] {
	set family_part_mult_select($p) $on
    }
    show_struct_families $type
}


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

# This is a tree-based selection method...

proc select_existing_parts {dimens multiple preselect {from_parts_list ""}} {
#
# optional "from_parts_list" restrict selection to the list.
# usage: long part list or part list for preselected entities. 
# 
    global ::AIEnv::GUIManagement::Tree::VisibilityImages
    global select_existing_parts_tree
    set parts ""
    foreach d $dimens { set dimens1($d) 1 }
    if [info exists dimens1(2)] { set dimens1(2s) 1; set dimens1(2d) 1 }
    set use_parts [aie_list_parts 0]
    if {$from_parts_list != ""} {
        foreach p $use_parts { set tmp_arr($p) 1 }
        set use_parts ""
        foreach p $from_parts_list {
            if [info exists tmp_arr($p)] {
                lappend use_parts $p
            }
        }
    }
    
    foreach p $use_parts {
        if {$dimens == -1} {
            set ok 1
        } elseif {$dimens == "prism"} {
            set ok 0
            set sel_map [ic_uns_subset_create]
            ic_uns_subset_make_families $sel_map $p
            set types [ic_uns_subset_list_types $sel_map]
            if {[lsearch $types PENTA_6] >= 0} {
                set ok 1
            }
            ic_uns_subset_delete $sel_map
        } elseif {$dimens == "volume"} {
            set ok 0
            set parts [ic_hex_list_blocking_parts]
            if {$parts != ""} break
        } else {
            set ok 0
            foreach pd [ic_boco_parts_dim $p] {
                if [info exists dimens1($pd)] { set ok 1; break }
            }
        }
        if $ok { lappend parts $p }
    }

    #puts [list select_existing_parts $dimens $multiple $preselect]
    #return [select_families part_name $multiple 0 "Select parts"]
    
    foreach p $preselect { set psel($p) 1 }
    
    if {$dimens == "prism"} {
	set buts [list accept cancel nl \
		  {All "select_existing_parts_all all"} \
		  {None "select_existing_parts_all none"} \
		  {Invert "select_existing_parts_all inv"}]
   } else {
	set buts [list accept cancel {Screen select_existing_parts_screen} nl \
		  {All "select_existing_parts_all all"} \
		  {None "select_existing_parts_all none"} \
		  {Invert "select_existing_parts_all inv"}]
    }
    form_kill .sel_parts
    set sel [form_init .sel_parts "Select parts" "" $buts]
    set sw [ScrolledWindow $sel.tree]
    grid $sw -row 0 -column 0 -sticky news
    set tr $sw.t
    Tree $tr -relief flat -borderwidth 0 -width 30 -height 22 -background white -linesfill gray50
    $sw setwidget $tr
    set select_existing_parts_tree(tr) $tr
    set select_existing_parts_tree(multiple) $multiple
    
    set isvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(isVisImg)
    set notvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(notVisImg)
    set somevisim $::AIEnv::GUIManagement::Tree::VisibilityImages(someVisImg)
    
    set cmd [list select_existing_parts_toggle]
    $tr bindText <ButtonRelease-1> $cmd
    $tr bindImage <ButtonRelease-1> $cmd
    
    set allnodes ""
    set intnodes ""
    foreach name $parts {
	set name2 ""
	set par root
	foreach comp [split $name /] {
	    if {$name2 == ""} {
		set name2 $comp
	    } else {
		append name2 /$comp
	    }
	    if ![$tr exists $name2] {
		if [info exists psel($name2)] {
		    set visim $isvisim
		} else {
		    set visim $notvisim
		}
		if {$name2 == $name} {
		    set col [family_color_for_name $name]
		} else {
		    set col black
		    lappend intnodes $name2
		}
		$tr insert end $par $name2 -text $comp -image $visim \
		    -fill $col -open 1
		lappend allnodes $name2
	    }
	    set par $name2
	}
    }
    foreach in $intnodes {
	if [info exists psel($in)] {
	    select_existing_parts_set_subtree_vstatus $tr $in $isvisim
	}
    }
    foreach in $intnodes {
	    set vs [select_existing_parts_vstatus $tr $in $isvisim $notvisim $somevisim]
	    set vim [lindex [list $notvisim $isvisim $somevisim] $vs]
	    $tr itemconfigure $in -image $vim
    }
    
    form_finish +200+200
    if ![form_wait .sel_parts] { return "" }
    
    foreach n $allnodes {
	    if {[$tr itemcget $n -image] == $isvisim} {
	        set pts [ic_geo_list_parts $n/]
	        if {$pts == ""} {
		        set got($n) 1
	        } else {
		        foreach p $pts { set got($p) 1 }
	        }
	    }
    }
    return [lsort [array names got]]
}

proc select_existing_parts_toggle {node} {
    global ::AIEnv::GUIManagement::Tree::VisibilityImages
    global select_existing_parts_tree
    
    set tr $select_existing_parts_tree(tr)
    set multiple $select_existing_parts_tree(multiple)
    set isvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(isVisImg)
    set notvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(notVisImg)
    set somevisim $::AIEnv::GUIManagement::Tree::VisibilityImages(someVisImg)
    
    if !$multiple {
	select_existing_parts_set_subtree_vstatus $tr root $notvisim
    }
    
    set im [$tr itemcget $node -image]
    if {$im == $isvisim} {
	set vim $notvisim
    } else {
	set vim $isvisim
    }
    select_existing_parts_set_subtree_vstatus $tr $node $vim
    select_existing_parts_update_parents $tr $node $notvisim $isvisim $somevisim
}

proc select_existing_parts_update_parents {tr node notvisim isvisim somevisim} {
    if [$tr exists $node] {
        for {set par [$tr parent $node]} {$par != "root"} {set par [$tr parent $par]} {
            set vs [select_existing_parts_vstatus $tr $par $notvisim $isvisim $somevisim]
            $tr itemconfigure $par -image [lindex [list $notvisim $isvisim $somevisim] $vs]
        }
    }
}

proc select_existing_parts_set_subtree_vstatus {tr node vim} {
    if {$node != "root"} {
        if [$tr exists $node] {
            $tr itemconfigure $node -image $vim
        }
    }
    if [$tr exists $node] {
        foreach ch [$tr nodes $node] {
            select_existing_parts_set_subtree_vstatus $tr $ch $vim
        }
    } else {
        mess "Part $node is not selectable\n" red
    }
}

proc select_existing_parts_vstatus {tr n isvisim notvisim somevisim} {
    global ::AIEnv::GUIManagement::Tree::VisibilityImages
    global select_existing_parts_tree
    
    set tr $select_existing_parts_tree(tr)
    set multiple $select_existing_parts_tree(multiple)
    set isvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(isVisImg)
    set notvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(notVisImg)
    set somevisim $::AIEnv::GUIManagement::Tree::VisibilityImages(someVisImg)
    
    set chs [$tr nodes $n]
    if ![llength $chs] {
        return [expr {[$tr itemcget $n -image] == $isvisim}]
    }
    set vs ""
    foreach ch $chs {
        set vs1 [select_existing_parts_vstatus $tr $ch $isvisim $notvisim $somevisim]
        if {($vs == "") || ($vs == $vs1)} {
            set vs $vs1
        } else {
            set vs 2
        }
    }
    return $vs
}

proc select_existing_parts_screen {} {
    global ::AIEnv::GUIManagement::Tree::VisibilityImages
    global select_existing_parts_tree
    
    set tr $select_existing_parts_tree(tr)
    set multiple $select_existing_parts_tree(multiple)
    set isvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(isVisImg)
    set notvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(notVisImg)
    set somevisim $::AIEnv::GUIManagement::Tree::VisibilityImages(someVisImg)
    
    set sel [geo_select_either entity [expr 1 - $multiple] "a part on the screen"]
    if {$sel != ""} {
        if !$multiple {
            select_existing_parts_set_subtree_vstatus $tr root $notvisim
        }
        foreach s $sel {
            if [string match uns_sel* $s] {
                set f [lindex [ic_uns_subset_list_families $s] 0]
            } else {
                set f [ic_geo_get_family [lindex $s 0] [lindex $s 1]]
                ic_show_geo_selected [lindex $s 0] [lindex $s 1] 0
            }
            set p [lindex [split $f :] 0]
            select_existing_parts_set_subtree_vstatus $tr $p $isvisim
            select_existing_parts_update_parents $tr $p $notvisim $isvisim $somevisim
        }
    }
}

proc select_existing_parts_all {how} {
    global ::AIEnv::GUIManagement::Tree::VisibilityImages
    global select_existing_parts_tree
    
    set tr $select_existing_parts_tree(tr)
    set multiple $select_existing_parts_tree(multiple)
    set isvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(isVisImg)
    set notvisim $::AIEnv::GUIManagement::Tree::VisibilityImages(notVisImg)
    set somevisim $::AIEnv::GUIManagement::Tree::VisibilityImages(someVisImg)
    
    set nn [select_existing_parts_all_leaves_and_internal $tr root]
    foreach node [lindex $nn 0] {
	if {$node == "root"} continue
	set im [$tr itemcget $node -image]
	switch $how {
	    all {  set vim $isvisim }
	    none { set vim $notvisim }
	    inv {
		if {$im == $isvisim} {
		    set vim $notvisim
		} else {
		    set vim $isvisim
		}
	    }
	}
	$tr itemconfigure $node -image $vim
    }
    foreach node [lindex $nn 1] {
	# these nodes are bottom-up
	set vs [select_existing_parts_vstatus $tr $node $notvisim $isvisim $somevisim]
	$tr itemconfigure $node -image [lindex [list $notvisim $isvisim $somevisim] $vs]
    }
    
}

# Returns a list of leaf nodes and internal nodes, with the lowest internal nodes
# first

proc select_existing_parts_all_leaves_and_internal {tree node} {
    set ch [$tree nodes $node]
    if {$ch == ""} {
        return [list $node ""]
    } else {
        set leaves ""
        set ints ""
        foreach c $ch {
            set li [select_existing_parts_all_leaves_and_internal $tree $c]
            set leaves [concat $leaves [lindex $li 0]]
            set ints [concat $ints [lindex $li 1] [list $c]]
        }
        return [list $leaves $ints]
    }	
}

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

proc select_location {{mess "a point"} {local_coords 0}} {
    global tdv_current_viewer
    banner "Select $mess on the screen with the left button; middle = done, right = cancel, 'e' = explicit coordinates."
    tdv_cur $tdv_current_viewer pick
    tdv_push_key_command e "select_location_explicit tdv_waiting_for_click($tdv_current_viewer)"
    set pt [graphics_loc_command]
    tdv_cur $tdv_current_viewer dynamics
    tdv_pop_key_command e
    banner ""
    if {$local_coords && ([info command ic_coords_into_local] != "")} {
	    set pt [ic_coords_into_local $pt]
    }
    return $pt
}

proc select_location_explicit {v} {
    global explicit_location_value
    
    set def ""
    if [info exists explicit_location_value] {
	    set def $explicit_location_value
    }
    set pt [question_box .explicit_location "Location" "Enter the point location as 3\nnumbers separated by spaces." $def]
    if {$pt != ""} {
	    set explicit_location_value $pt
    }
    if {$pt != ""} {
	    uplevel \#0 set $v \"e $pt\"
    }
}

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

set select_toolbar_opts {
    dynamics {select_F9_rot select_F9_sel} "Toggle dynamics" {"" "select_toggle_dynamics 1"}
    preselect  {select_prehighlight_OFF select_prehighlight_ON} "Toggle preselect highlight and name" ::vam_events(do_onMotion)
    sep "" "" ""
    
    polygon select_polygon "Select items in a polygonal region" "set select_action polygon"
    circle select_circle "Select items in a circular region" "set select_action circle"
    all select_all "Select all appropriate objects (visible or blanked)" "set select_action all"
    visible select_visible "Select all appropriate visible objects" "set select_action visible"
    blanked select_blanked "Select all appropriate blanked objects" "set select_action blanked"
    family select_family "Select items in part" "set select_action family"
    cancel select_cancel "Cancel selection" "set select_action cancel"
    sep "" "" ""
    
    region_type {select_part_in select_all_in} "Toggle between all and partial enclosure" {options(select_mode) {} some all}
    goto_next select_goto_next "Select the next item picked" "set select_action goto_next"
    broken_all_edge_select {select_toggle_all_edges select_toggle_only_edges} "Toggle between all edges and highlighted edges" "set select_action all_edge_select"
    all_edge_select {select_toggle_all_edges select_toggle_only_edges} "Toggle between all edges and highlighted edges" {options(select_edge_mode) select_toggle_all_edges}
    select_toggle_all_faces {select_boundary_off select_boundary_on} "Toggle between all faces and boundary faces" {options(face_mode) select_toggle_all_faces}
    block_by_vertex select_vertex "Select block by vertex" "set select_action block_by_vertex"
    color select_color "Select by color" "set select_action color"
    highlight_segment select_next_segment "Select next edge segment" "set select_action highlight_segment"
    sep "" "" ""
    
    flood select_flood "Select all items attached to current selection" "set select_action flood"
    flood_angle select_flood_angle "Select all items attached to current selection, up to an angle" "set select_action flood_angle"
    flood_curve select_flood_curve "Select all items attached to current selection, up to a curve" "set select_action flood_curve"
    flood_one select_flood_one "Select one attached layer" "set select_action flood_one"
    flood_one_geom select_flood1geom "Select one attached layer" "set select_action flood_one"
    flood_between select_flood_between "Select a path in-between two selected nodes" "set select_action flood_between"
    flood_split2 select_flood_split "Split two edges and flood fill in-between them" "set select_action flood_split2"
    feature_angle select_feature_angle "Set feature angle for flood fill" "set select_action feature_angle"
    boundary_type {select_boundary_off select_boundary_on} "Toggle boundary type" {options(boundary_mode) {} outer all}
    all_boundary select_boundary_on "Select all boundary subfaces" "set select_action all_boundary"
    all_block select_boundary_off "Select all blockinterfaces" "set select_action all_block"
    sep "" "" ""
    
    subset select_subset "Select items in a subset" "set select_action subset"
    part select_part "Select items in a part" "set select_action part"
    name select_name "Select by name" "set select_action name"
    new select_location "Select location as a new node" "set select_action new"
    explicit select_explicit "Create a new point at a specified location" "set select_action explicit"
    enum select_enum "Select elements by numbers" "set select_action enum"
    nnum select_nnum "Select nodes by numbers" "set select_action nnum"
    hnum select_nnum "Select by numbers" "set select_action hnum"
    mater select_mater "Select elements by material" "set select_action mater"
    prop select_prop "Select elements by property" "set select_action prop"
    
    geo_proj select_geo_proj "Select mesh attached to geometry" "set select_action geo_proj"
    sep "" "" ""
    
    d0 {select_d0_off select_d0_on} "Toggle selection of points" "select_option(0) select_toggle_dimensions"
    d1 {select_d1_off select_d1_on} "Toggle selection of curves" "select_option(1) select_toggle_dimensions"
    d2 {select_d2_off select_d2_on} "Toggle selection of surfaces" "select_option(2) select_toggle_dimensions"
    d3 {select_d3_off select_d3_on} "Toggle selection of bodies" "select_option(3) select_toggle_dimensions"
    
    dim0 select_Nodes_on "Select all node elements" "set select_action dim0"
    dim1 select_Bars_on "Select all line elements" "set select_action dim1"
    dim2 select_Shells_on "Select all surface elements" "set select_action dim2"
    dim3 select_VolElems_on "Select all volume elements" "set select_action dim3"
    
    mesh select_mesh_tools "Toggle mesh select tools" "set select_action select_mesh"
    geom select_geom_tools "Toggle geometry select tools" "set select_action select_geom"
    corners {select_corners select_corners} "Toggle select diagonal corner vertices" {options(select_toggle_corners) select_toggle_corners}
    sep "" "" ""
    
	xyz_on_plane {select_planeOFF select_planeON} "Toggle allow any plane selection" allow_plane_selection
	xyz_on_plane_xy {radio select_planeXY_off select_planeXY_on} "Toggle allow on XY plane selection" {allow_plane_selection 2}
	xyz_on_plane_xz {radio select_planeXZ_off select_planeXZ_on} "Toggle allow on XZ plane selection" {allow_plane_selection 3}
	xyz_on_plane_yz {radio select_planeYZ_off select_planeYZ_on} "Toggle allow on YZ plane selection" {allow_plane_selection 4}

	xyz_on_mesh  {select_meshOFF select_meshON} "Toggle allow on Mesh/Block selection" ::va_set(xyz_on_mesh)
	xyz_show_xyz  {select_pre-XYZOFF select_pre-XYZON} "Toggle show location" ::va_set(xyz_show_xyz)
	xyz_show_typename  {select_pre-NameOFF select_pre-NameON} "Toggle show entity name" ::va_set(xyz_show_typename)
	xyz_show_entity  {select_pre-highlightOFF select_pre-highlightON} "Toggle highlight entity" ::va_set(xyz_show_entity)
}

proc select_toolbar {opts title} {
    global select_toolbar_opts icon_path env tdv_current_viewer use_select_toolbar
    global icon_size1 menu_buttons surface_select volume_select

    if ![info exists use_select_toolbar] return
    
    foreach t {tri quad} {
        set surface_select($t) 1
    }
    foreach t {tetra hexa penta pyra} {
        set volume_select($t) 1
    }
    
    set w .select_opts
    foreach {o k} $opts { append w _$o }
    
    if {$opts == ""} {
	    foreach w [winfo children .] {
	        if [string match .select_opts_* $w] {
		        catch {top_withdraw $w}
	        }
	    }
	    return
    } elseif {$opts == "all"} {
	    set opts ""
	    foreach {name icon bubble cmd} $select_toolbar_opts { lappend opts $name ? }
    }
    set opts [concat dynamics F9 $opts]    
    foreach {o k} $opts { set use($o) $k }
    if ![winfo exists $w] {
	    top_window_force $w 0 $title select_toolbar_delete
	    set bg [$w cget -background]
	    set sep 0
	    set col 0
	    foreach {name icon bubble cmd} $select_toolbar_opts {
	        incr col
	        if {$name == "sep"} {
		        if $sep {
		            frame $w.separator$col -width 1 -height 10 -borderwidth 1 -relief raised
		            set sep 0
		        }
		        continue
	        }
	        if ![info exists use($name)] continue
	        incr sep
	        if {$use($name) != ""} {
		        set bubble "$bubble (key = $use($name))"
	        }
	        if [file exists $env(MED_ROOT)/../icons/icon_box.xbm] {
	            set bad_im [image create bitmap -file $env(MED_ROOT)/../icons/icon_box.xbm -foreground black -background ""]
	        } else {
	            set bad_im [image create bitmap -file $env(MED_ROOT)/lib/icons/icon_box.xbm -foreground black -background ""]
	        }
	        set images ""
	        set radio 0
	        foreach ic $icon {
		        if {$ic == "radio"} { incr radio; continue }
		        set im ""
		        foreach dir $icon_path {
		            set file $dir/$ic
		            if {[file exists $file.gif] || [file exists $file$icon_size1.gif]} {
                        if [file exists $file$icon_size1.gif] {
                            set file_used $file$icon_size1
                        } else {
                            set file_used $file
                        }
			            if [catch {image create photo -file $file_used.gif} im] {
			                puts "ERROR: bad gif file $file_used: $im"
			                set im $bad_im
			            }
			            break
		            } elseif [file exists $file.xbm] {
			            if [catch {image create bitmap -file $file.xbm -foreground black -background ""} im] {
			                puts "ERROR: bad xbm file $file: $im"
			                set im $bad_im
			            }
			            break
		            }
		        }
		        if {$im == ""} {
		            puts "ERROR: can't find icon $ic"
		            set im $bad_im
		        }
		        lappend images $im
	        }
	        set wid $w.$name
	        if $radio {
		        radiobutton $wid -variable [lindex $cmd 0] -value [lindex $cmd 1] \
		            -command [lindex $cmd 2] -indicatoron 0 -selectcolor "" -borderwidth 1 \
		            -image [lindex $images 0] -selectimage [lindex $images 1]
	        } elseif {[llength $icon] == 2} {
		        checkbutton $wid -variable [lindex $cmd 0] -command [lindex $cmd 1] \
		            -indicatoron 0 -selectcolor "" -borderwidth 1 \
		            -image [lindex $images 0] -selectimage [lindex $images 1]
		        if {[llength $cmd] >= 4} {
		            $wid configure -offvalue [lindex $cmd 2] -onvalue [lindex $cmd 3]
		        }
	        } else {
	            # special cases, for surface/volume elements menu added
	            if {$name == "dim2" || $name == "dim3"} {
	                button $wid -image [lindex $images 0] -relief flat -borderwidth 1 -command $cmd -background $bg
	                set menu $wid.menu.m
	                menubutton $wid.menu -text "" -relief flat -borderwidth 0 -background $bg -menu $menu 
	                if {$icon_size1 < 25} {
	                    set ImageArrow [list 2 2 5 5 9 2]
	                } elseif {$icon_size1 < 36} {
	                    set ImageArrow [list 2 2 6 6 10 2]
	                }  else {
	                    set ImageArrow [list 2 2 7 7 11 2]
	                }
		            set dropdown [canvas $wid.arrow -bd 1 -relief raised -highlightthickness 0 -takefocus 0]
		            $dropdown create polygon $ImageArrow -outline black -fill black -width 1 -tags arrow
		            foreach {x1 y1 x2 y2} [$dropdown bbox arrow] break
		            $dropdown configure -width [expr {$x2 - $x1 - 1}] -height [expr {$y2 - $y1 - 1}]
		            place $dropdown -in $wid -relx 1 -x -1 -rely 1 -y -1 -anchor se
		            lappend menu_buttons $dropdown
	            } else {
		            button $wid -image [lindex $images 0] -relief flat -borderwidth 1 -command $cmd -background $bg
		        }
	        }
	        pack $wid -side left -padx 1 -pady 1 -anchor c
	        if {$name == "dim2" || $name == "dim3"} {
	            place $dropdown -in $wid -relx 1 -x -1 -rely 1 -y -1 -anchor se
	            bind $wid <Enter> "$wid configure -relief raised; $dropdown configure -relief raised"
	            bind $wid <Leave> "$wid configure -relief flat; $dropdown configure -relief raised"
	            bind $dropdown <ButtonPress-1> "select_show_types_menu $name $menu %X %Y"
	        } else {
	            bind $wid <Enter> "$wid configure -relief raised"
	            bind $wid <Leave> "$wid configure -relief flat"
	        }
	        bubble_define $wid $bubble
	    }
	    top_geometry_wrt $w $tdv_current_viewer - + 1
    }
    top_deiconify $w
    update
    select_toolbar_gray 0
    if {$title != ""} {
        select_toolbar_set_title $w "$title"
    }
    if [info exists menu_buttons] {
        foreach m $menu_buttons {
            if [winfo exists $m] {
                $m configure -relief raised
            }
        }
    }
}

proc select_show_types_menu {dim menu X Y} {
    global volume_select surface_select icon_path env icon_size1

    catch { destroy $menu }
    menu $menu -tearoff 0
    set types [ic_uns_list_types]
    if {$dim == "dim2"} {
        foreach "t1 t2" {Triangles tri Quads quad} {
            if ![info exists surface_select($t2)] {
                set surface_select($t2) 1
            }
            if {[lsearch -regexp $types [string toupper $t2]_+] < 0} {
                set surface_select($t2) 0
                continue
            }
            set file $env(ICEM_ACN)/lib/ai_env/icons/select_all_$t2$icon_size1.gif
            if {[file exists $file] && 0} {
                set im [image create photo -file $file]
                $menu add checkbutton -image $im -variable surface_select($t2)
            } else {
                $menu add checkbutton -label $t1 -variable surface_select($t2)
            }
        }
    } elseif {$dim == "dim3"} {
        foreach "t1 t2" {Tetrahedra tetra Hexahedra hexa Prisms penta Pyramids pyra} {
            if ![info exists volume_select($t2)] {
                set volume_select($t2) 1
            }
            if {[lsearch -regexp $types [string toupper $t2]_+] < 0} {
                set volume_select($t2) 0
                continue
            }
            set file $env(ICEM_ACN)/lib/ai_env/icons/select_all_$t2$icon_size1.gif
            if {[file exists $file] && 0} {
                set im [image create photo -file $file]
                $menu add checkbutton -image $im -variable volume_select($t2)
            } else {
                $menu add checkbutton -label $t1 -variable volume_select($t2)
            }
        }
    }
    tk_popup $menu [expr $X - 20] [expr $Y + 20]
}

proc select_toolbar_delete {} {
    global select_action
    set select_action cancel
    return 0
}

proc select_toggle_what {} {
    global select_action select_option
    
    set select_action select_$select_option(what)
}

proc select_toggle_all_edges {} {
    global select_action select_option
    
    set select_action all_edge_select
}

proc select_toggle_all_faces {} {
    global options use_output_blocks hexa_selection_display hexa_selection_last_display

    set display_cmd "display_super_faces [range_string] [family_activename_string] only_icons -not_blanked"
    if [info exists hexa_selection_display] {
        if {[lsearch $hexa_selection_display boundary] < 0} {
            append display_cmd " boundary"
        }
    }
	if $use_output_blocks { append display_cmd " output_blocks" }
	hex_command "$display_cmd"
	set hexa_selection_display $display_cmd
}

proc do_toggle_global {name v1 v2} {
	# name may be name of existing global variable; array member Ok
	set g ::
	if {[string range $name 0 1] != $g} {
		set name ${g}$name
	}
	if ![info exists $name] {return 0}
	set v [set $name]
	if {$v == $v1} { set $name $v2} else { set $name $v1}
	return 1
}

proc select_toggle_dimensions {} {
    global select_action select_option
    
    set sa only_dimensions
    foreach i {0 1 2 3} {
	    if $select_option($i) { lappend sa ${i}d }
    }
    set select_action $sa
}

proc select_toggle_corners {} {
    global options select_action
    if $options(select_toggle_corners) {
        set select_action corners
    } else {
        set select_action done
    }
}

proc select_toolbar_gray {gray} {
    foreach w [winfo children .] {
	    if {[string match .select_opts_* $w] && [winfo ismapped $w]} {
	        foreach sw [winfo children $w] {
		        if [string match *.separator* $sw] continue
		        if [string match *.dynamics $sw] continue
		        $sw configure -state [expr {$gray ? "disabled" : "normal"}]
	        }
	    }
    }
}

proc select_toolbar_gray_child {gray child} {
    foreach w [winfo children .] {
	    if {[string match .select_opts_* $w] && [winfo ismapped $w]} {
	        foreach sw [winfo children $w] {
		        if [string match *.separator* $sw] continue
		        if [string match *.dynamics $sw] continue
		        if [string match *.$child $sw] {
		            $sw configure -state [expr {$gray ? "disabled" : "normal"}]
		        }
	        }
	    }
    }
}

proc select_toolbar_set_title {w title} {
    global toplevel
    if {[string match .select_opts_* $w] && [winfo ismapped $w] && [info exists toplevel($w,head)]} {
        if [winfo exists $toplevel($w,head).l] {
            $toplevel($w,head).l configure -text " $title"
        }
    }
}

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

# This is a way for the calling routines (e.g. the ones that call
# aie_apply_attributes) to figure out what parts and/or subsets were
# actually selected, so that the names can be added to the
# APPLY_TO_PARTS and APPLY_TO_SUBSETS pseudo-bc's.

# This is a list of part P1 part P2 subset S1 ...

array set select_saved_parts {}
array set select_saved_subsets {}


proc select_get_parts_and_subsets {} {
    global select_saved_parts select_saved_subsets
    set ret ""
    foreach n [array names select_saved_parts] { lappend ret part $n }
    foreach n [array names select_saved_subsets] { lappend ret subset $n }
}

proc select_reset_parts_and_subsets {} {
    global select_saved_parts select_saved_subsets
    catch {unset select_saved_parts}
    catch {unset select_saved_subsets}
}

proc select_add_parts_and_subsets {t n} {
    global select_saved_parts select_saved_subsets
    switch $t {
	part { set select_saved_parts($n) 1 }
	subset { set select_saved_subsets($n) 1 }
	default error
    }
}
