-# Copyright (c) 1998-2002, Bryan Oakley
+# Copyright (c) 1998-2003, Bryan Oakley
# All Rights Reservered
#
# Bryan Oakley
# oakley@bardo.clearlight.com
#
-# combobox v2.2.1 September 22, 2002
+# combobox v2.3 August 16, 2003
#
# a combobox / dropdown listbox (pick your favorite name) widget
# written in pure tcl
# Scott Beasley Alexandre Ferrieux Todd Helfter
# Matt Gushee Laurent Duperval John Jackson
# Fred Rapp Christopher Nelson
-# Eric Galluzzo Jean-Francois Moine
+# Eric Galluzzo Jean-Francois Moine Oliver Bienert
#
# A special thanks to Martin M. Hunt who provided several good ideas,
# and always with a patch to implement them. Jean-Francois Moine,
# ... and many others over the years.
package require Tk 8.0
-package provide combobox 2.2.1
+package provide combobox 2.3
namespace eval ::combobox {
-bd -borderwidth \
-bg -background \
-borderwidth {borderWidth BorderWidth} \
+ -buttonbackground {buttonBackground Background} \
-command {command Command} \
-commandstate {commandState State} \
-cursor {cursor Cursor} \
-disabledforeground {disabledForeground DisabledForeground} \
-dropdownwidth {dropdownWidth DropdownWidth} \
-editable {editable Editable} \
+ -elementborderwidth {elementBorderWidth BorderWidth} \
-fg -foreground \
-font {font Font} \
-foreground {foreground Foreground} \
-highlightcolor {highlightColor HighlightColor} \
-highlightthickness {highlightThickness HighlightThickness} \
-image {image Image} \
+ -listvar {listVariable Variable} \
-maxheight {maxHeight Height} \
-opencommand {opencommand Command} \
-relief {relief Relief} \
delete get icursor index \
insert list scan selection \
xview select toggle open \
- close entryset \
+ close entryset subwidget \
]
set listCommands [list \
# exist...
scrollbar $tmpWidget
set sb_width [winfo reqwidth $tmpWidget]
+ set bbg [$tmpWidget cget -background]
destroy $tmpWidget
# steal options from the entry widget
destroy $tmpWidget
# these are unique to us...
+ option add *Combobox.elementBorderWidth 1 widgetDefault
+ option add *Combobox.buttonBackground $bbg widgetDefault
option add *Combobox.dropdownWidth {} widgetDefault
option add *Combobox.openCommand {} widgetDefault
option add *Combobox.cursor {} widgetDefault
# this helps (but doesn't fully solve) focus issues. The general
# idea is, whenever the frame gets focus it gets passed on to
# the entry widget
- bind Combobox <FocusIn> {::combobox::tkTabToWindow [::combobox::convert %W -W].entry}
+ bind Combobox <FocusIn> {::combobox::tkTabToWindow \
+ [::combobox::convert %W -W].entry}
# this closes the listbox if we get hidden
bind Combobox <Unmap> {[::combobox::convert %W -W] close}
set widgets(frame) ::combobox::${w}::$w
# gotta do this sooner or later. Might as well do it now
- pack $widgets(entry) -side left -fill both -expand yes
pack $widgets(button) -side right -fill y -expand no
+ pack $widgets(entry) -side left -fill both -expand yes
# I should probably do this in a catch, but for now it's
# good enough... What it does, obviously, is put all of
# to appear "inside" the entry widget.
$widgets(vsb) configure \
+ -borderwidth 1 \
-command "$widgets(listbox) yview" \
-highlightthickness 0
$widgets(button) configure \
+ -background $options(-buttonbackground) \
-highlightthickness 0 \
- -borderwidth 1 \
+ -borderwidth $options(-elementborderwidth) \
-relief raised \
-width [expr {[winfo reqwidth $widgets(vsb)] - 2}]
-highlightthickness 0
$widgets(dropdown) configure \
- -borderwidth 1 \
+ -borderwidth $options(-elementborderwidth) \
-relief sunken
$widgets(listbox) configure \
proc ::combobox::DestroyHandler {w} {
- # if the widget actually being destroyed is of class Combobox,
- # crush the namespace and kill the proc. Get it? Crush. Kill.
- # Destroy. Heh. Danger Will Robinson! Oh, man! I'm so funny it
- # brings tears to my eyes.
- if {[string compare [winfo class $w] "Combobox"] == 0} {
- upvar ::combobox::${w}::widgets widgets
- upvar ::combobox::${w}::options options
-
- # delete the namespace and the proc which represents
- # our widget
- namespace delete ::combobox::$w
- rename $w {}
- }
-
+ catch {
+ # if the widget actually being destroyed is of class Combobox,
+ # remove the namespace and associated proc.
+ if {[string compare [winfo class $w] "Combobox"] == 0} {
+ # delete the namespace and the proc which represents
+ # our widget
+ namespace delete ::combobox::$w
+ rename $w {}
+ }
+ }
return ""
}
}
$widgets(entry) selection range 0 end
+ $widgets(entry) icursor end
$widgets(this) close
switch $action {
"grow" {
if {$hlimit > 0 && [$widgets(listbox) size] > $hlimit} {
+ pack forget $widgets(listbox)
pack $widgets(vsb) -side right -fill y -expand n
+ pack $widgets(listbox) -side left -fill both -expand y
}
}
"crop" {
# this means the window was cropped and we definitely
# need a scrollbar no matter what the user wants
+ pack forget $widgets(listbox)
pack $widgets(vsb) -side right -fill y -expand n
+ pack $widgets(listbox) -side left -fill both -expand y
}
default {
if {$hlimit > 0 && [$widgets(listbox) size] > $hlimit} {
+ pack forget $widgets(listbox)
pack $widgets(vsb) -side right -fill y -expand n
+ pack $widgets(listbox) -side left -fill both -expand y
} else {
pack forget $widgets(vsb)
}
regsub $widgets($subwidget) $result $widgets(this) result
# replace specific instances of the subwidget command
- # with out megawidget command
+ # with our megawidget command
switch $subwidget,$subcommand {
listbox,index {regsub "index" $result "list index" result}
listbox,insert {regsub "insert" $result "list insert" result}
if {$options(-editable)} {
focus $widgets(entry)
$widgets(entry) select range 0 end
- $widgets(entry) icur end
+ $widgets(entry) icursor end
}
# if we are disabled, we won't allow this to happen
# ok, tweak the visual appearance of things and
# make the list pop up
$widgets(button) configure -relief sunken
- raise $widgets(dropdown) [winfo parent $widgets(this)]
wm deiconify $widgets(dropdown)
+ update idletasks
+ raise $widgets(dropdown)
# force focus to the entry widget so we can handle keypress
# events for traversal
}
switch -- $option {
+ -buttonbackground {
+ $widgets(button) configure -background $newValue
+ }
-background {
set updateVisual 1
set options($option) $newValue
-editable {
set updateVisual 1
- if {$newValue} {
- # it's editable...
- $widgets(entry) configure \
- -state normal \
- -cursor $defaultEntryCursor
- } else {
- $widgets(entry) configure \
- -state disabled \
- -cursor $options(-cursor)
- }
+ if {$newValue} {
+ # it's editable...
+ $widgets(entry) configure \
+ -state normal \
+ -cursor $defaultEntryCursor
+ } else {
+ $widgets(entry) configure \
+ -state disabled \
+ -cursor $options(-cursor)
+ }
+ set options($option) $newValue
+ }
+
+ -elementborderwidth {
+ $widgets(button) configure -borderwidth $newValue
+ $widgets(vsb) configure -borderwidth $newValue
+ $widgets(dropdown) configure -borderwidth $newValue
set options($option) $newValue
}
-image {
if {[string length $newValue] > 0} {
- $widgets(button) configure -image $newValue
+ puts "old button width: [$widgets(button) cget -width]"
+ $widgets(button) configure \
+ -image $newValue \
+ -width [expr {[image width $newValue] + 2}]
+ puts "new button width: [$widgets(button) cget -width]"
+
} else {
$widgets(button) configure -image ::combobox::bimage
}
set options($option) $newValue
}
+ -listvar {
+ if {[catch {$widgets(listbox) cget -listvar}]} {
+ return -code error \
+ "-listvar not supported with this version of tk"
+ }
+ $widgets(listbox) configure -listvar $newValue
+ set options($option) $newValue
+ }
+
-maxheight {
# ComputeGeometry may dork with the actual height
# of the listbox, so let's undork it