# $Id: comboent.tcl,v 2.7 2004/06/27 23:51:47 jfontain Exp $


class comboEntry {}

proc comboEntry::comboEntry {this parentPath args} composite {
    [new frame $parentPath -highlightthickness $widget::option(button,highlightthickness)] $args
} {
    composite::manage $this\
        [new entry $widget::($this,path) -highlightthickness 0] entry\
        [new comboButton $widget::($this,path) -command "comboEntry::selected $this" -reference $widget::($this,path)] button
    widget::configure $composite::($this,button) base -highlightthickness 0
    grid $composite::($this,entry,path) -column 0 -row 0 -sticky nsew
    grid $composite::($this,button,path) -column 1 -row 0 -sticky nsew
    grid columnconfigure $widget::($this,path) 0 -weight 1
    grid rowconfigure $widget::($this,path) 0 -weight 1
    composite::complete $this
}

proc comboEntry::~comboEntry {this} {}

proc comboEntry::options {this} {                                      ;# force initialization on font (use bold), and state options
    return [list\
        [list -command {} {}]\
        [list -editable 1 1]\
        [list -font $widget::option(button,font)]\
        [list -justify $widget::option(entry,justify) $widget::option(entry,justify)]\
        [list -list {} {}]\
        [list -state normal]\
        [list -width $widget::option(entry,width) $widget::option(entry,width)]\
    ]
}

foreach option {-justify -width} {
    proc comboEntry::set$option {this value} "widget::configure \$composite::(\$this,entry) $option \$value"
}

proc comboEntry::set-command {this value} {}                                 ;# do nothing, command is stored at the composite level

proc comboEntry::set-editable {this value} {
    comboEntry::setStates $this
    comboEntry::setBindings $this
}

proc comboEntry::set-font {this value} {
    $composite::($this,entry,path) configure -font $value
    widget::configure $composite::($this,button) -font $value
}

proc comboEntry::set-list {this value} {
    widget::configure $composite::($this,button) -list $value
}

proc comboEntry::set-state {this value} {
    if {![regexp {^(disabled|normal)$} $value]} {
        error "bad state value \"$value\": must be normal or disabled"
    }
    setStates $this
    setBindings $this
}

proc comboEntry::set-troughcolor {this value} {
    widget::configure $composite::($this,button) -troughcolor $value
}

proc comboEntry::setStates {this} {
    if {[string equal $composite::($this,-state) disabled]} {                     ;# prevent the arrow button from getting the focus
        widget::configure $composite::($this,button) -state disabled -takefocus 0
        if {[package vcompare $::tcl_version 8.4] < 0} {
            widget::configure $composite::($this,entry) -state disabled
        } else {
            widget::configure $composite::($this,entry) -state readonly
        }
    } else {
        widget::configure $composite::($this,button) -state normal
        if {$composite::($this,-editable)} {         ;# prevent the arrow button from getting the focus, let the entry get the focus
            widget::configure $composite::($this,button) -takefocus 0
            widget::configure $composite::($this,entry) -state normal
        } else {
            widget::configure $composite::($this,button) -takefocus 1
            if {[package vcompare $::tcl_version 8.4] < 0} {
                widget::configure $composite::($this,entry) -state disabled
            } else {
                widget::configure $composite::($this,entry) -state readonly
            }
        }
    }
}

proc comboEntry::setBindings {this} {
    if {[string equal $composite::($this,-state) normal]&&$composite::($this,-editable)} {
        bind $composite::($this,entry,path) <Down> "comboButton::popupListBox $composite::($this,button)"
        bind $composite::($this,entry,path) <Return> "comboEntry::invoke $this"
        bind $composite::($this,entry,path) <KP_Enter> "comboEntry::invoke $this"
    } else {
        bind $composite::($this,entry,path) <Down> {}
        bind $composite::($this,entry,path) <Return> {}
        bind $composite::($this,entry,path) <KP_Enter> {}
    }
}

proc comboEntry::selected {this choice} {
    widget::configure $composite::($this,entry) -state normal
    set $this $choice
    setStates $this                                                                                  ;# restore entry state properly
    if {[string length $composite::($this,-command)]>0} {                  ;# always invoke command at global level as tk buttons do
        uplevel #0 $composite::($this,-command) [list $choice]
    }
}

proc comboEntry::invoke {this} {
    if {[string length $composite::($this,-command)]>0} {                  ;# always invoke command at global level as tk buttons do
        uplevel #0 $composite::($this,-command) [list [$composite::($this,entry,path) get]]
    }
}

proc comboEntry::set {this text} {                                                    ;# public procedure for setting entry contents
    $composite::($this,entry,path) delete 0 end
    $composite::($this,entry,path) insert 0 $text
}

proc comboEntry::get {this text} {                                                 ;# public procedure for retrieving entry contents
    return [$composite::($this,entry,path) get]
}
