# ------------------------------------------------------------------
# The QuestionBox is used for warning popups
# ------------------------------------------------------------------

proc QuestionBox {message bttn_list {default ""} {bitmap questhead}} {
    global questionBox

    set questionBox(value) $default
    set w .questionBox
    catch {destroy $w}

    toplevel $w
    wm title $w Alert
    wm transient $w .

    frame $w.top
    label $w.top.bitmap -bitmap $bitmap
    message $w.top.msg -text $message -aspect 350
    frame $w.border -bd 1 -relief sunken -height 2
    frame $w.bottom
    frame $w.bottom.defaultFrame -bd 2 -relief sunken

    foreach i $bttn_list {
	set j [string tolower $i]
	button $w.bottom.$j -text $i -command [ format {
	    SaveValueXY %s questionBox
	    destroy %s
	    set questionBox(value) {%s}
	} $w $w $i ]
	bind $w.bottom.$j <Return> "ActivateButton [list $w.bottom.$j]"
    }

    grid $w.top -gridwidth 0
    grid $w.top.bitmap -padx 10 -pady 10
    grid $w.top.msg -gridwidth 0 -padx 10 -pady 10
    grid $w.border -gridwidth 0 -weightx 1 -weighty 1 -fill both
    grid $w.bottom -gridwidth 0

    set oldFocus [focus]

    foreach i $bttn_list {
	set j [string tolower $i]
	if {$default == "$i"} {
	    grid $w.bottom.defaultFrame -padx 5 -pady 5
	    grid $w.bottom.$j -in $w.bottom.defaultFrame \
	    	-padx 5 -pady 5 -ipadx 4 -ipady 2
	    focus $w.bottom.$j
	} else {
	    grid $w.bottom.$j -padx 5 -pady 5 -ipadx 4 -ipady 2
	}
    }
    
    if [info exists questionBox(x)] {
	wm geometry $w \
	    [format +%d+%d $questionBox(x) $questionBox(y)]
    } else {
	CenterWindow $w
    }

    tkwait visibility $w
    grab $w
    tkwait window $w
    focus $oldFocus

    return $questionBox(value)
}

proc CenterWindow {w} {
    wm withdraw $w
    update idletasks
    set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	- [winfo vrootx [winfo parent $w]]]
    set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	- [winfo vrooty [winfo parent $w]]]
    wm geom $w +$x+$y
    wm deiconify $w
}

proc SaveValueXY {frame info} {
    global $info

    scan [wm geometry $frame] %dx%d+%d+%d width height x y
    set ${info}(x) $x
    set ${info}(y) $y
    set ${info}(width) $width
    set ${info}(height) $height
}

proc ActivateButton {w} {
    tkButtonEnter $w
    tkButtonDown $w
    update idletasks
    after 200
    tkButtonUp $w
}

# ------------------------------------------------------------------
# The LoadBox is used to select an item from a list
# ------------------------------------------------------------------

proc LoadBox {title list {load "Load"} {defaultIndex 0}} {
    global loadBox

    set w .loadBox
    catch {destroy $w}

    toplevel $w
    wm title $w $title
    wm minsize $w 64 64
    wm transient $w .

    listbox $w.list -yscrollcommand "$w.sbar set"
    bind $w.list <Double-Button-1> "$w.bttn.ok invoke"

    set maxLength 0
    foreach i $list {
	$w.list insert end $i
	set length [string length $i]
	if {$length > $maxLength} {
	    set maxLength $length
	}
    }
    $w.list configure -width [expr $maxLength+10] -height 10
    catch {$w.list select from $defaultIndex}

    scrollbar $w.sbar -orient vertical -command "$w.list yview"
    frame $w.bttn
    frame $w.bttn.defaultFrame -bd 2 -relief sunken
    button $w.bttn.ok -text $load \
    	-command [format {
	    set loadBox(value) [lindex [%s.list curselection] 0]
	    SaveValueXY %s loadBox
	    destroy %s
	} $w $w $w]
    button $w.bttn.cancel -text Cancel \
    	-command [format {
	    set loadBox(value) ""
	    SaveValueXY %s loadBox
	    destroy %s
	} $w $w]

    bind $w.bttn.ok <Return> "ActivateButton $w.bttn.ok"

    set oldFocus [focus]
    focus $w.bttn.ok

    grid $w.list -gridwidth -1 -weightx 1 -weighty 1 -fill both
    grid $w.sbar -gridwidth 0 -fill y
    grid $w.bttn -gridwidth 0
    grid $w.bttn.defaultFrame 
    grid $w.bttn.ok -in $w.bttn.defaultFrame
    grid $w.bttn.cancel

    if [info exists loadBox(x)] {
	wm geometry $w \
	    [format +%d+%d $loadBox(x) $loadBox(y)]
    } else {
	CenterWindow $w
    }

    tkwait visibility $w
    grab $w
    tkwait window $w
    focus $oldFocus

    return $loadBox(value)
}

# ------------------------------------------------------------------
# The EntryBox is used to select an item from a list
# ------------------------------------------------------------------

proc EntryBox {title message {buttonText OK} {init {}}} {
    global entryBox

    set w .entryBox
    catch {destroy $w}

    toplevel $w
    wm title $w $title
    wm minsize $w 64 64
    wm transient $w .

    message $w.msg -text $message -aspect 350
    entry $w.entry -textvariable entryBox(value)
    set entryBox(value) $init
    frame $w.pad -height 10

    frame $w.default -bd 2 -relief sunken
    button $w.ok -text $buttonText -command [format {
	SaveValueXY %s entryBox
	destroy %s
    } $w $w]
    button $w.cancel -text Cancel -command [format {
	set entryBox(value) ""
	SaveValueXY %s entryBox
	destroy %s
    } $w $w]

    bind $w.entry <Return> "ActivateButton $w.ok"
    set oldFocus [focus]
    focus $w.entry

    grid $w.msg -gridwidth 0
    grid $w.entry -padx 5 -pady 5 -gridwidth 0 -fill x
    grid $w.pad -gridwidth 0
    grid $w.default -padx 5 -pady 5 -weightx 1 -anchor e
    grid $w.ok -padx 5 -pady 5 -ipadx 4 -ipady 2 \
    	-in $w.default
    grid $w.cancel -padx 5 -pady 5 -ipadx 4 -ipady 2 \
    	-weightx 1 -anchor w

    if [info exists entryBox(x)] {
	wm geometry $w \
	    [format +%d+%d $entryBox(x) $entryBox(y)]
    } else {
	CenterWindow $w
    }

    tkwait visibility $w
    grab $w
    tkwait window $w
    focus $oldFocus

    return $entryBox(value)
}

# ------------------------------------------------------------------
# The MultiEntryBox is used for single or multi line entries
# ------------------------------------------------------------------

proc MultiEntryBox {} {}
rename MultiEntryBox {}

itcl_class MultiEntryBox {

    constructor {config} {
	#
	#  Create a toplevel window
	#
	set class [$this info class]
	toplevel $this-win -class $class
	set top $this-win

	bind $top <Destroy> [format {
	    if {[info commands %s] != ""} {
		%s cancel
	    }
	} $this $this]

	wm title $top $title
	wm minsize $top 64 64
	wm transient $top .

	#
	# Initialize all the variables and widgets
	#
	$this _initvars
	$this _initwidgets
    }

    # ------------------------------------------------------------------
    #  DESTRUCTOR - destroy window containing widget
    # ------------------------------------------------------------------
    destructor {
	destroy $this-win
    }

    # ------------------------------------------------------------------
    #  METHOD:  _initvars - used to initialize variables from subclasses
    # ------------------------------------------------------------------
    method _initvars {} {
	set multi_select 0
    }

    # ------------------------------------------------------------------
    #  METHOD:  _initwidgets - create all the widgets
    # ------------------------------------------------------------------
    method _initwidgets {} {
	upvar #0 $this info

	# Play with the window geometry
	if [info exists info(width)] {
	    wm geometry $top [format %dx%d $info(width) $info(height)]
	}
	if [info exists info(x)] {
	    wm geometry $top [format +%d+%d $info(x) $info(y)]
	}
	if ![info exists info(value)] {
	    set info(value) ""
	}

	# Start making widgets
	if {$message != ""} {
	    message $top.msg -text $message -aspect 350
	}
	
	frame $top.f1
	set index 0
	set last {}
	foreach entry $entryList {
	    set name [string tolower $entry]
	    label $top.f1.$name-L -text $entry
	    entry $top.f1.$name-E \
	    	-textvariable [format %s(%s) $this $entry]
	    grid $top.f1.$name-L -anchor w
	    grid $top.f1.$name-E -weightx 1 -gridwidth 0 -fill x -padx 4
	    
	    if {$last != {}} {
		tabbind $last $top.f1.$name-E
	    }
	    set last $top.f1.$name-E
	    incr index
	}
	set entry [lindex $entryList 0]
	if {$entry != {}} {
	    set name [string tolower $entry]
	    set entry $top.f1.$name-E
	    focus $entry
	    tabbind $last $entry
	}
	bind $last <Return> "ActivateButton $top.ok"
	
	frame $top.default -bd 2 -relief sunken
	button $top.ok -text $buttonText -command "$this ok"
	button $top.cancel -text Cancel -command "$this cancel"
	
	if {$message != ""} {
	    grid $top.msg -gridwidth 0
	}
	grid $top.f1 -weightx 1 -gridwidth 0 -fill x -pady 6
	grid $top.default -padx 5 -pady 5 -weightx 1 -anchor e
	grid $top.ok -padx 5 -pady 5 \
	    -in $top.default
	grid $top.cancel -padx 5 -pady 5 \
	    -weightx 1 -anchor w
    }

    method ok {} {
	upvar #0 $this info

	set info(value) ""
	foreach entry $entryList {
	    lappend info(value) $info($entry)
	}
	SaveValueXY $top $this
	eval $OkCallback [list $info(value)]
	$this delete
    }

    method cancel {} {
	upvar #0 $this info

	set $info(value) ""
	SaveValueXY $top $this
	eval $CancelCallback
	$this delete
    }

    public title {Multi Entry Box}
    public message {}
    public entryList Apply
    public buttonText {}
    public OkCallback {}
    public CancelCallback {}

    protected top {}
}
