- The algorithm for calculating the number of lines in the text widget is slightly flawed, and doesn't always work correctly (out by a few chars occassionally). If someone can spot the problem, please fix it!
- Works better for fixed-width fonts. Proportional fonts work, but it makes more errors in the algorithm (which, as I say, is flawed).
- Doesn't take into account -wrap settings, so only use with -wrap char. It sort of works with -wrap word, but is generally quite wrong. -wrap none won't work at all for obvious reasons (you don't need this if you don't want to wrap!)
- Oh, and I haven't yet implemented some of the entry options (like -textvariable and such)...
# multientry.tcl --
#
# A multi-line entry widget. This is a version of the text widget that
# automatically expands its height to fit the text it is displaying. When
# the height reaches a maximum value (-maxheight option; default=4 lines)
# then a scrollbar is created. This is the behaviour of (for instance) the
# To: and Cc: entry fields in some mail applications/newsreaders.
#
# http://wiki.tcl.tk/11152
# By Neil Madden.
# Public Domain.
package require Tcl 8.4
package require Tk 8.4
package require snit 0.91
package provide multientry 0.1
namespace eval multientry {
namespace export multientry
}
# multientry --
#
# The entry widget replacement. Automatically grows in height until the
# -maxheight level has been reached, and then adds a scrollbar. Works
# shrinking too. The algorithm is not perfect, and you may occasionally type
# extra characters before the entry grows, or sometimes, too few. I'm sure
# I'm just missing something simple here. Doesn't work very well.
snit::widget multientry::multientry {
delegate method * to text
delegate option * to text
variable scrolled 0
constructor {args} {
install text using multientry::mtext $win.t -parent $self \
-height 1 -borderwidth 1 \
-relief sunken -yscrollcommand [list $win.vsb set]
scrollbar $win.vsb -orient vertical -command [list $win.t yview]
grid $win.t -row 0 -column 0 -sticky nsew
grid columnconfigure $win 0 -weight 1
$self configurelist $args
}
method IsScrolled {} { return $scrolled }
method AddScrollbar {} {
grid $win.vsb -row 0 -column 1 -sticky ns
set scrolled 1
}
method RemoveScrollbar {} {
grid forget $win.vsb
set scrolled 0
}
}
# Helper widget - a text widget which handles it's own resizing. Calls back to
# the parent widget if it decides it needs a scrollbar. Not to be used
# directly, only via the multientry widget (below).
snit::widgetadaptor multientry::mtext {
delegate method Insert to hull as insert
delegate method Delete to hull as delete
delegate method * to hull
delegate option * to hull
option -parent ""
option -maxheight 4
constructor {args} {
installhull using text
$self configurelist $args
}
method insert {index args} {
set arglist [list]
# Remove newlines - only one line allowed!
foreach {str tags} $args {
lappend arglist [string map {\n ""} $str] $tags
}
eval [list $self Insert $index] $arglist
$self AdjustHeight
}
method delete {args} {
eval [list $self Delete] $args
$self AdjustHeight
}
method AdjustHeight {} {
# Adjust height if needed
set tw [font measure [$self cget -font] -displayof $win \
[$self get 1.0 end-1c]]
# Calculate the actual size of the text widget internals
set sw [expr {[winfo width $win]-
(2*[$self cget -borderwidth]
+ 2*[$self cget -selectborderwidth]
+ 2*[$self cget -highlightthickness])}]
set h [expr {$tw/$sw + 1}]
if {$h != [$self cget -height]} {
if {$h <= $options(-maxheight)} {
if {[$options(-parent) IsScrolled]} {
$options(-parent) RemoveScrollbar
}
$self configure -height $h
} else {
if {![$options(-parent) IsScrolled]} {
$options(-parent) AddScrollbar
}
}
}
return
}
}And some demo code (if needed!):
pack [multientry::multientry .me -maxheight 6] -fill both -expand 1
escargo 22 Mar 2004 - Does it really require Snit 0.92? 0.91 is more commonly available....LES: I have ActiveTcl 8.4.4 and snit is 0.82. Doesn't work.NEM 0.91 should do. Simple typo. I guess snit changed between 0.82 and 0.91 (as it's pre-1.0 release stuff the API seems to change quite frequently).
See also:
- LabelText -A Multi Line Entry Widget
- Multi-Line Text Entry Widget - With Entry Widget Like Field To Field Tabbing

