📄 combobox.itk
字号:
} elseif {$when != "now"} { error "bad option \"$when\": should be now or later" } if {$itk_option(-dropdown)} { grid configure $itk_component(list) -row 1 -column 0 -sticky news _resizeArrow grid config $itk_component(arrowBtn) -row 0 -column 1 -sticky nsew } else { # size and pack list hack grid configure $itk_component(entry) -row 0 -column 0 -sticky ew grid configure $itk_component(efchildsite) -row 1 -column 0 -sticky nsew grid configure $itk_component(list) -row 0 -column 0 -sticky nsew grid rowconfigure $itk_component(efchildsite) 1 -weight 1 grid columnconfigure $itk_component(efchildsite) 0 -weight 1 } set _repacking ""}# ------------------------------------------------------# PROTECTED METHOD: _positionList## Determine the position (geometry) for the popped up list# and map it to the screen.## ------------------------------------------------------body iwidgets::Combobox::_positionList {} { set x [winfo rootx $itk_component(entry) ] set y [expr [winfo rooty $itk_component(entry) ] + \ [winfo height $itk_component(entry) ]] set w [winfo width $itk_component(entry) ] set h [winfo height [_slbListbox] ] set sh [winfo screenheight .] if {([expr $y+$h] > $sh) && ($y > [expr $sh/2])} { set y [expr [winfo rooty $itk_component(entry) ] - $h] } $itk_component(list) configure -width $w wm overrideredirect $itk_component(popup) 0 wm geometry $itk_component(popup) +$x+$y wm overrideredirect $itk_component(popup) 1}# ------------------------------------------------------# PROTECTED METHOD: _postList## Pop up the list in a dropdown style Combobox.## ------------------------------------------------------body iwidgets::Combobox::_postList {} { if {[$itk_component(list) size] == ""} { return } set _isPosted true _positionList # map window and do a grab wm deiconify $itk_component(popup) _listShowing -wait if {$itk_option(-grab) == "global"} { grab -global $itk_component(popup) } else { grab $itk_component(popup) } raise $itk_component(popup) focus $itk_component(popup) _drawArrow}# ------------------------------------------------------# PROTECTED METHOD: _previous## Select the previous item in the list. Wraps at front# and end of list. ## ------------------------------------------------------body iwidgets::Combobox::_previous {} { if {[size] <= 1} { return } set i [curselection] if {$i == "" || $i == 0} { set i [expr [size] - 1] } else { incr i -1 } selection clear 0 end selection set $i $i see $i set _currItem $i}# ------------------------------------------------------# PROTECTED METHOD: _resizeArrow## Recalculate the arrow button size and then redraw it.## ------------------------------------------------------body iwidgets::Combobox::_resizeArrow {} { set bw [expr [$itk_component(arrowBtn) cget -borderwidth]+ \ [$itk_component(arrowBtn) cget -highlightthickness]] set newHeight [expr [winfo reqheight $itk_component(entry) ]-(2*$bw) - 2] $itk_component(arrowBtn) configure -width $newHeight -height $newHeight _drawArrow}# ------------------------------------------------------# PROTECTED METHOD: _selectCmd## Called when list item is selected to insert new text # in entry, and call user -command callback if defined.## ------------------------------------------------------body iwidgets::Combobox::_selectCmd {} { $itk_component(entry) configure -state normal set _currItem [$itk_component(list) curselection] set item [$itk_component(list) getcurselection] clear entry $itk_component(entry) insert 0 $item switch -- $itk_option(-editable) { 0 - false - no - off { $itk_component(entry) configure -state disabled } } # execute user command if {$itk_option(-selectioncommand) != ""} { uplevel #0 $itk_option(-selectioncommand) }}# ------------------------------------------------------# PROTECTED METHOD: _toggleList## Post or unpost the dropdown listbox (toggle).## ------------------------------------------------------body iwidgets::Combobox::_toggleList {} { if {[winfo ismapped $itk_component(popup)] } { _unpostList } else { _postList }}# ------------------------------------------------------# PROTECTED METHOD: _unpostList## Unmap the listbox (pop it down).## ------------------------------------------------------body iwidgets::Combobox::_unpostList {} { # Determine if event occured in the scrolledlistbox and, if it did, # don't unpost it. (A selection in the list unposts it correctly and # in the scrollbar we don't want to unpost it.) set x [winfo x $itk_component(list)] set y [winfo y $itk_component(list)] set w [winfo width $itk_component(list)] set h [winfo height $itk_component(list)] wm withdraw $itk_component(popup) grab release $itk_component(popup) set _isPosted false $itk_component(list) selection clear 0 end if {$_currItem != {}} { $itk_component(list) selection set $_currItem $_currItem $itk_component(list) activate $_currItem } switch -- $itk_option(-editable) { 1 - true - yes - on { $itk_component(entry) configure -state normal } 0 - false - no - off { $itk_component(entry) configure -state disabled } } _drawArrow}# ------------------------------------------------------# PROTECTED METHOD: _commonBindings## Bindings that are used by both simple and dropdown# style Comboboxes.## ------------------------------------------------------body iwidgets::Combobox::_commonBindings {} { bind $itk_component(entry) <KeyPress-BackSpace> [code $this _bs] bind $itk_component(entry) <KeyRelease> [code $this _lookup %K] bind $itk_component(entry) <Down> [code $this _next] bind $itk_component(entry) <Up> [code $this _previous] bind $itk_component(entry) <Control-n> [code $this _next] bind $itk_component(entry) <Control-p> [code $this _previous] bind [_slbListbox] <Control-n> [code $this _next] bind [_slbListbox] <Control-p> [code $this _previous]}# ------------------------------------------------------# PROTECTED METHOD: _dropdownBindings## Bindings used only by the dropdown type Combobox.## ------------------------------------------------------body iwidgets::Combobox::_dropdownBindings {} { bind $itk_component(popup) <Escape> [code $this _unpostList] bind $itk_component(popup) <space> \ "[code $this _stateSelect]; [code $this _unpostList]" bind $itk_component(popup) <Return> \ "[code $this _stateSelect]; [code $this _unpostList]" bind $itk_component(popup) <ButtonRelease-1> \ [code $this _dropdownBtnRelease %W %x %y] bind $itk_component(list) <Map> \ [code $this _listShowing 1] bind $itk_component(list) <Unmap> \ [code $this _listShowing 0] # once in the listbox, we drop on the next release (unless in scrollbar) bind [_slbListbox] <Enter> \ [code $this _ignoreNextBtnRelease false] bind $itk_component(arrowBtn) <3> [code $this _next] bind $itk_component(arrowBtn) <Shift-3> [code $this _previous] bind $itk_component(arrowBtn) <Down> [code $this _next] bind $itk_component(arrowBtn) <Up> [code $this _previous] bind $itk_component(arrowBtn) <Control-n> [code $this _next] bind $itk_component(arrowBtn) <Control-p> [code $this _previous] bind $itk_component(arrowBtn) <Shift-Down> [code $this _toggleList] bind $itk_component(arrowBtn) <Shift-Up> [code $this _toggleList] bind $itk_component(arrowBtn) <Return> [code $this _toggleList] bind $itk_component(arrowBtn) <space> [code $this _toggleList] bind $itk_component(entry) <Configure> [code $this _resizeArrow] bind $itk_component(entry) <Shift-Down> [code $this _toggleList] bind $itk_component(entry) <Shift-Up> [code $this _toggleList]}# ------------------------------------------------------# PROTECTED METHOD: _simpleBindings## Bindings used only by the simple type Comboboxes.## ------------------------------------------------------body iwidgets::Combobox::_simpleBindings {} { bind [_slbListbox] <ButtonRelease-1> [code $this _stateSelect] # "[code $this _stateselect]; [code $this _selectCmd]" bind [_slbListbox] <space> [code $this _stateSelect] bind [_slbListbox] <Return> [code $this _stateSelect] bind $itk_component(entry) <Escape> "" bind $itk_component(entry) <Shift-Down> "" bind $itk_component(entry) <Shift-Up> "" bind $itk_component(entry) <Configure> ""}# ------------------------------------------------------# PROTECTED METHOD: _listShowing ?val?## Used instead of "tkwait visibility" to make sure that# the dropdown list is visible. Whenever the list gets# mapped or unmapped, this method is called to keep# track of it. When it is called with the value "-wait",# it waits for the list to be mapped.# ------------------------------------------------------body iwidgets::Combobox::_listShowing {{val ""}} { if {$val == ""} { return $_listShowing($this) } elseif {$val == "-wait"} { while {!$_listShowing($this)} { tkwait variable [scope _listShowing($this)] } return } set _listShowing($this) $val}# ------------------------------------------------------# PRIVATE METHOD: _slbListbox## Access the tk listbox window out of the scrolledlistbox.## ------------------------------------------------------body iwidgets::Combobox::_slbListbox {} { return [$itk_component(list) component listbox]}# ------------------------------------------------------# PRIVATE METHOD: _stateSelect## only allows a B1 release in the listbox to have an effect if -state is# normal.## ------------------------------------------------------body iwidgets::Combobox::_stateSelect {} { switch -- $itk_option(-state) { normal { [code $this _selectCmd] } }}# ------------------------------------------------------# PRIVATE METHOD: _bs## A part of the auto-completion code, this function sets a flag when the# Backspace key is hit and there is a selection in the entry field.# Note that it's probably buggy to assume that a selection being present# means that that selection came from auto-completion.## ------------------------------------------------------body iwidgets::Combobox::_bs {} { # # exit if completion is turned off # switch -- $itk_option(-completion) { 0 - no - false - off { return } } # # critical section flag. it ain't perfect, but for most usage it'll # keep us from being in this code "twice" at the same time # (auto-repeated keystrokes are a pain!) # if {$_inbs} { return } else { set _inbs 1 } # # set the _doit flag if there is a selection set in the entry field # set _doit 0 if [$itk_component(entry) selection present] { set _doit 1 } # # clear the semaphore and return # set _inbs 0}# ------------------------------------------------------# PRIVATE METHOD: _lookup## handles auto-completion of text typed (or insert'd) into the entry field.## ------------------------------------------------------body iwidgets::Combobox::_lookup {key} { # # exit if completion is turned off # switch -- $itk_option(-completion) { 0 - no - false - off { return } } # # critical section flag. it ain't perfect, but for most usage it'll # keep us from being in this code "twice" at the same time # (auto-repeated keystrokes are a pain!) # if {$_inlookup} { return } else { set _inlookup 1 } # # if state of megawidget is disabled, or the entry is not editable, # clear the semaphore and exit # if {$itk_option(-state) == "disabled" \ || [lsearch {on 1 true yes} $itk_option(-editable)] == -1} { set _inlookup 0 return } # # okay, *now* we can get to work # the _bs function is called on keyPRESS of BackSpace, and will set # the _doit flag if there's a selection set in the entryfield. If # there is, we're assuming that it's generated by completion itself # (this is probably a Bad Assumption), so we'll want to whack the # selected text, as well as the character immediately preceding the # insertion cursor. # if {$key == "BackSpace"} { if {$_doit} { set first [expr [$itk_component(entry) index insert] -1] $itk_component(entry) delete $first end $itk_component(entry) icursor $first } } # # get the text left in the entry field, and its length. if # zero-length, clear the selection in the listbox, clear the # semaphore, and boogie. # set text [get] set len [string length $text] if {$len == 0} { $itk_component(list) selection clear 0 end set _inlookup 0 return } # # okay, so we have to do a lookup. find the first match in the # listbox to the text we've got in the entry field (glob). # if one exists, clear the current listbox selection, and set it to # the one we just found, making that one visible in the listbox. # then, pick off the text from the listbox entry that hadn't yet been # entered into the entry field. we need to tack that text onto the # end of the entry field, select it, and then set the insertion cursor # back to just before the point where we just added that text. # if one didn't exist, then just clear the listbox selection # set item [lsearch [$itk_component(list) get 0 end] "$text*" ] if {$item != -1} { $itk_component(list) selection clear 0 end $itk_component(list) selection set $item $item see $item set remainder [string range [$itk_component(list) get $item] \ $len end] $itk_component(entry) insert end $remainder $itk_component(entry) selection range $len end $itk_component(entry) icursor $len } else { $itk_component(list) selection clear 0 end } # # clear the semaphore and return # set _inlookup 0 return}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -