Version 2 of Multi-Line Entry Widget in Snit

Updated 2009-12-03 10:07:04 by adavis

jnc Dec 2, 2009 - Tk currently lacks a multiline entry widget. The text widget is a great widget but a bit complex if you just need a multiline plain text widget that acts like entry.

This is one of many solutions on the wiki. This solution includes support for:

  • -textvariable
  • attaching scroll bars (vertical by default)
  • handling Tab and Shift-Tab correctly
  • optionally allowing tabs inside of the widget with the -allowtab 1 option
  snit::widget multiline_entry {
    delegate option * to text
    delegate method * to text

    # On/Off options
    option -yscroll -default 1
    option -xscroll -default 0
    option -allowtab -default 0

    # Miscellaneous options
    option -textvariable -default 0

    constructor { args } {
        install text using text $win.txt
        grid $win.txt -row 0 -column 0 -sticky nswe

        $self configurelist $args

        if {[$win cget -yscroll] == 1} {
            $win.txt configure -yscrollcommand [list $win.vsb set]
            ttk::scrollbar $win.vsb -command [list $win.txt yview]
            grid $win.vsb -row 0 -column 1 -sticky nsw
        }

        if {[$win cget -xscroll] == 1} {
            $win.txt configure -xscrollcommand [list $win.hsb set]
            ttk::scrollbar $win.hsb -orient horizontal -command [list $win.txt xview]
            grid $win.hsb -row 1 -column 0 -sticky we
        }

        grid rowconfigure $win 0 -weight 1
        grid columnconfigure $win 0 -weight 1

        if {[$win cget -textvariable] != 0} {
            set varName [$win cget -textvariable]
            upvar 3 $varName v
            $win.txt insert 1.0 $v
            $win.txt mark set insert 1.0
            trace add variable v write [list $self setContent]
            trace add variable v read [list $self getContent]
        }

        bind $win <FocusIn> [list focus $win.txt]

        if {$options(-allowtab) == 0} {
            bind $win.txt <Shift-Tab> [list $self focusPrev]
            bind $win.txt <Tab> [list $self focusNext]
        }
    }

    method getTextWidget {} {
        return $win.txt
    }

    method focusPrev {} {
        focus [tk_focusPrev $win]
        return -code break
    }

    method focusNext {} {
        focus [tk_focusNext $win.txt]
        return -code break
    }

    method setContent { name element op} {
        upvar 1 $name x
        $win.txt delete 1.0 end
        $win.txt insert 1.0 $x
    }

    method getContent { name element op } {
        upvar 1 $name x
        set x [$win.txt get 1.0 "end-1 char"]
    }
  }

See also: Multiline expanding entry widget, Multi-Line Text Entry Widget - With Entry Widget Like Field To Field Tabbing and GRIDPLUS2.