[NEM] ''22Mar2004'' - This is an entry widget replacement that can contain multiple display lines (but only 1 logical line - so no newlines allowed). It automatically grows in height to fit the text being typed into it, up until the -maxheight option has been reached. After that it automatically displays a scrollbar. Works the other way too - will shrink down as stuff is deleted. Some limitations: * 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)... Oh well, warts and all, here's the code. Feel free to improve it. dbn 29 Sept 2009 - I think the problem mentioned in the first bullet is because the -highlightthickness needed to be accounted for when determining the widget's width; once I included that, it seemed to work more reliably. I updated the code below. ---- # 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] and [Multi-Line Text Entry Widget - With Entry Widget Like Field To Field Tabbing]. ---- [Category Widget]