
# This code creates the ICEM CFD Manager.
#
# Copyright (c) 1993 - 1996 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Wayne A. Christopher, wayne@icemcfd.com

# This is used by the modal and pathname forms.

proc varchange {w title vars} {
    global bigfont
    global varchange_done env bigfont normalfont smallfont
    
    set varchange_done 0
    
    catch {destroy $w}
    toplevel $w
    wm maxsize $w 2000 2000
    label $w.title -text $title -font $bigfont -foreground blue \
	-relief raised -borderwidth 2
    canvas $w.c -relief raised -borderwidth 2
    frame $w.c.vars
    frame $w.buts
    
    button $w.buts.okay -relief raised -borderwidth 2 -text "Save values" \
	-command "varchange_okay $w \{$vars\} *okay*"
    button $w.buts.temp -relief raised -borderwidth 2 -text "Temp only" \
	-command "varchange_okay $w \{$vars\} *temp*"
    button $w.buts.cancel -relief raised -borderwidth 2 -text "Cancel" \
	-command "varchange_cancel $w \{$vars\}"
    button $w.buts.defaults -relief raised -borderwidth 2 \
	-text "Set to defaults" \
	-command "varchange_defaults $w \{$vars\}"
    pack append $w.buts $w.buts.okay {left fill expand padx 5 pady 5} \
	    $w.buts.temp {left fill expand padx 5 pady 5} \
	    $w.buts.defaults {left fill expand padx 5 pady 5} \
	    $w.buts.cancel {left fill expand padx 5 pady 5} 
    
    set bback [$w cget -background]
    
    set maxvw 0
    foreach var $vars {
	set vw [string length [lindex $var 1]]
	if {$vw > $maxvw} {set maxvw $vw}
    }
    for {set i 0} {$i < [llength $vars]} {incr i} {
	set var [lindex $vars $i]
	set name [lindex $var 0]
	set descr [lindex $var 1]
	set type [lindex $var 2]
	set command [lindex $var 3]
	
	if [winfo exists $w.c.vars.$name] continue
	frame $w.c.vars.$name -relief sunken -border 1
	pack append $w.c.vars $w.c.vars.$name {top pady 4 fill expand}
	
	label $w.c.vars.$name.label -width $maxvw -text "$descr" \
	    -padx 5 -anchor e -foreground black
	set isalist 0; set isabool 0; set isapath 0; set isalistbox 0
	case $type in {
	    i {set dval 0; set entry_length 10}
	    f {set dval 0.0; set entry_length 10}
	    b {set dval true; set entry_length 5; set isabool 1}
	    p {set dval [pwd]; set entry_length 40; set isapath 1}
	    s {set dval ""; set entry_length 40}
	    default {set dval [lindex $type 0];
		set entry_length 10
		foreach v $type {
		    set el [string length $v]
		    if {$el > $entry_length} \
			{set entry_length $el}
		}
		if {[llength $type] > 10} {
		    set isalistbox 1
		} else {
		    set isalist 1
		}
	    }
	}
	
	global $name
	if [info exists $name] {
	    set dval [set $name]
	    if $isapath {
		regsub $env(ICEM_ACN) $dval ICEM_ACN dval
	    }
	}
	
	set packopts {left fill expand padx 5}
	if $isalist {
	    menubutton $w.c.vars.$name.entry -border 1 -text $dval -width \
		$entry_length -relief raised -anchor nw \
		-foreground blue -menu $w.c.vars.$name.entry.m \
		-background $bback
	    menu $w.c.vars.$name.entry.m -tearoff 0
	    foreach ent $type {
		$w.c.vars.$name.entry.m add command -label $ent \
		    -command "$w.c.vars.$name.entry configure -text $ent"
	    }
	    
	    bind $w.c.vars.$name.entry <Key-space> \
		"varchange_advance_menu $w.c.vars.$name.entry \"$type\""
	    
	} elseif $isalistbox {
	    button $w.c.vars.$name.entry -border 1 -text $dval -width \
		$entry_length -relief raised -anchor nw \
		-foreground blue -background $bback -command \
		[list varchange_pick_one $w.c.vars.$name.entry $type]
	    
	} elseif $isabool {
	    button $w.c.vars.$name.entry -border 1 -anchor w -text $dval -width 5 \
		-relief raised -padx 0 -pady 0 -foreground blue \
		-command "varchange_flip_bool $w.c.vars.$nname.entry" \
		-background $bback
	    
	    bind $w.c.vars.$name.entry <Key-space> "$w.c.vars.$name.entry invoke"
	    
	} else {
	    entry $w.c.vars.$name.entry -border 1 -width $entry_length \
		-foreground blue -background white
	    $w.c.vars.$name.entry insert 0 $dval
	    set packopts {left padx 5 fill expand}
	    if $isapath then {pathentry on $w.c.vars.$name.entry}
	}
	
	set next [expr {($i + 1) % [llength $vars]}]
	set nname [lindex [lindex $vars $next] 0]
	bind $w.c.vars.$name.entry <Return> "pathentry_clear; focus $w.c.vars.$nname.entry"
	# bind $w.c.vars.$name.entry <Any-F1> {help_provide [winfo containing %X %Y] %X %Y}
	
	global helpCmds
	set helpCmds(.modals.vars.$name.label) "set topic modals.$name"
	set helpCmds(.modals.vars.$name.entry) "set topic modals.$name"
	set helpCmds(.modals.vars.$name) "set topic modals.$name"
	
	if {$i == 0} {focus $w.c.vars.$name.entry}
	
	pack append $w.c.vars.$name $w.c.vars.$name.label {left padx 5} \
	    $w.c.vars.$name.entry $packopts
    }
    
    wm withdraw $w
    wm geometry $w +200+200
    update idle
    
    scroller $w $w.title $w.c $w.c.vars $w.buts
    
    update idle
    wm deiconify $w
    
    tkwait variable varchange_done
    
    return $varchange_done
}

proc varchange_fetch_text {wid} {
    set curconf [$wid configure -text]
    set cur [lindex $curconf [expr {[llength $curconf] - 1}]]
}

proc varchange_flip_bool {but} {
    set cur [varchange_fetch_text $but]
    if {$cur == "true"} then \
	{$but configure -text "false"} else \
	{$but configure -text "true"}
}

proc varchange_advance_menu {menu items} {
    set cur [varchange_fetch_text $menu]
    set ind [lsearch $items $cur]
    set new [lindex $items [expr {($ind + 1) % [llength $items]}]]
    $menu configure -text $new
}

proc varchange_okay {w vars what} {
    global varchange_done env
    
    pathentry_clear
    set allokay 1
    foreach var $vars {
	set name [lindex $var 0]
	set type [lindex $var 2]
	set command [lindex $var 3]
	set okay 1
	case $type in {
	    {i} {
		set value [$w.c.vars.$name.entry get]
		if {![scan $value "%d" dummy]} {set okay 0}
	    }
	    {f} {
		set value [$w.c.vars.$name.entry get]
		if {![scan $value "%f" dummy]} {set okay 0}
	    }
	    {b} {
		set value [varchange_fetch_text \
			   $w.c.vars.$name.entry]
		if {($value != "true") &&
		    ($value != "false")} \
		    {set okay 0}
	    }
	    {p} {
		set value [$w.c.vars.$name.entry get]
		# gotta do something
	    }
	}
	if $okay then {$w.c.vars.$name.entry configure \
	    -foreground blue} else \
	    {$w.c.vars.$name.entry configure \
		-foreground red; set allokay 0}
    }
    if {!$allokay} {beep; return}
    
    foreach var $vars {
	set name [lindex $var 0]
	set type [lindex $var 2]
	set command [lindex $var 3]
	case $type in {
	    {i} {scan [$w.c.vars.$name.entry get] "%d" value}
	    {f} {scan [$w.c.vars.$name.entry get] "%d" value}
	    {p s} {
		set value [$w.c.vars.$name.entry get]
		regsub ICEM_ACN $value $env(ICEM_ACN) value
	    }
	    default {set value [varchange_fetch_text \
				$w.c.vars.$name.entry]}}
	#puts stdout "set $name to $value"
	global $name
	set $name "$value"
	# puts stdout "eval $command"
	eval $command
    }
    set varchange_done $what
    destroy $w
    focus .
}

proc varchange_cancel {w vars} {
    global varchange_done
    
    pathentry_clear
    set varchange_done *cancel*
    destroy $w
    focus .
}

proc varchange_defaults {w vars} {
    foreach var $vars {
	set name [lindex $var 0]
	set type [lindex $var 2]
	set val [lindex $var 4]
	case $type in {
	    {i f p s} {
		$w.c.vars.$name.entry delete 0 end
		$w.c.vars.$name.entry insert 0 $val
	    }
	    default {
		$w.c.vars.$name.entry configure -text $val
	    }
	}
    }
}

proc varchange_pick_one {ent choices} {
    set x [winfo rootx $ent]
    set y [expr [winfo rootx $ent] + [winfo height $ent]]
    
    catch {destroy .vc_pick_one}
    set m .vc_pick_one
    toplevel $m
    wm geometry $m +$x+$y
    
    listbox $m.list -relief sunken -borderwidth 2 -yscroll "$m.scroll set" \
	    -background white -exportselection 0 \
	    -width 20 -height 10
    scrollbar $m.scroll -command "$m.list yview" \
	    -background #cdb79e
    button $m.cancel -text Cancel -command "destroy $m"
    pack $m.cancel -side bottom -fill both
    pack $m.list -side left -fill both
    pack $m.scroll -side left -fill both
    
    bind $m.list <ButtonPress-1> "varchange_pick_one_select $m %y $ent"
    bind $m.list <Any-Motion> "%W selection clear 0 end ;\
	    %W selection set \[%W nearest %y\]"
    
    foreach ch $choices { $m.list insert end $ch }
    
    return 1
}

proc varchange_pick_one_select {listbox y entry} {
    set ch [$listbox.list get [$listbox.list nearest $y]]
    $entry configure -text $ch
    destroy $listbox
}
