From: thf@zelator.in-berlin.de (Thomas Funke)
Subject: Re: Can <Tab> be used to change focus in forms?
Reply-To: thf@zelator.in-berlin.de (Thomas Funke)
Organization: NNU Corp. - NeXT is Not UN*X
Date: Thu, 19 Nov 1992 18:09:39 GMT

In article <1992Nov18.044237.24882@sinkhole.unf.edu> shite@sinkhole.unf.edu  
(Stephen Hite) writes:
> 
> Real beginner question (thanks in advance)...
> 
>     When creating a dialog using the Tk Toolkit (with wish), is
> it easy to get the <Tab> key to act as a focus changer so a user
> could easily go from one field to the next without using the
> mouse?  That is, I'm looking for the functionality you'd get in a dialog
> with Microsoft Windows.  

Well, not difficult, but you have to do it yourself. I include some code I used  
a while ago. Excuse the german comments.


-------------- cut here -----------------------------------------

# Erzeugt im Window w einen 'labelled Entry'. ReturnCommand ist
# das Kommando, welches bei Return ausgefuehrt wird, nextEntry
# ins das Widget, welches bei Tab selektiert wird
# Falls der 4, Parameter (check) angegeben ist,
# wird das darin befindliche Check-Kommando (mit Entry-Widget als 
# Parameter) aufgerufen,
# welches 0 liefern muss, wenn das Feld ok ist,
#
# Zu jedem Entry-Widget wird ein (globales) Array erzeugt
# mit folgenden Inhalten:
#
#	entry(check)	- 	Checkfunktion fuer das Feld (oder leer)
#	entry(next)	-	Naechstes Feld (fuer TAB)
#	entry(return)	-	Das Kommando, welches bei RET ausgefuehrt wird
#	entry(disabled) -	1 wenn das Feld disabled ist
#
proc entryWidget { w labelText returnCommand nextEntry {check ""}} {
    global $w.entry
    
    frame $w -borderwidth 5
    label $w.label -text $labelText
    entry $w.entry -width 100 -relief sunken
    bind $w.entry <Key-Tab> "entryTab $w.entry"
    bind $w.entry <Key-Return> "entryReturn $w.entry"
    set $w.entry(check) $check
    set $w.entry(next) $nextEntry.entry
    set $w.entry(disabled) 0
    set $w.entry(return) $returnCommand

    pack append $w $w.label { left } $w.entry {left fill frame e}
    return $w
}

# Wird bei Eingabe eines TAB's im Entry aufgerufen
# Falls das Check-Kommando des Widgets != 0 ergibt, wird
# nicht ins naechste Feld gesprungen !
proc entryTab {w} {
    global $w

    trimEntry $w
    if {[set [set w](check)] != ""} {
	if {[eval [set [set w](check)] $w] != 0} return
    }

    # Das naechste Feld
    set next [set [set w](next)]
    global $next

    while {[set [set next](disabled)]} {
	set next [set [set next](next)]
	global $next
    }
    
    focus $next
}

#wird bei RETURN im Entry aufgerufen
proc entryReturn {w} {
    global $w
    
    trimEntry $w
    if {[set [set w](check)] != ""} {
	if {[eval [set [set w](check)] $w] != 0} return
    }
    catch [set [set w](return)]
}

# ruft "focus $w" auf, wenn das aktuelle
# Entry die 'Check-Funktion' passiert hat
proc checkFocus {w} {
    set current [focus]
    global $current

    if {$w == $current} return
    if {[catch "set [set current](check)"] != 0} {
	focus $w
	return
    }
    
    set checkFunc [set [set current](check)]    
    if {($checkFunc != "") && [$checkFunc $current] != 0} return
    
    focus $w
}

# Prueft das aktuelle Feld, wo der Focus
# drauf ist und liefert 0 wenn ok, 
# ansonsten -1
proc checkCurrentFocus {} {
    
    set current [focus]
    global $current
    if { $current  != "none" } {
	if {[catch "set [set current](check)"] == 0} {
	    set checkFunc [set [set current](check)]
	    if {($checkFunc != "") && [$checkFunc $current] != 0} {
		return -1
	    }
	}
    }
    return 0
}



# Erlaubt keine Editierung fuer das angegebene Entry-Widget
proc disableEntry {w} {
    global $w
    
    bind $w <1> return
    $w configure -background bisque2
    $w delete 0 9999
    set [set w](disabled) 1
}

# Entry wieder fuer Eingaben enablen
proc enableEntry {w} {
    global $w
    
    bind $w <1> { 
	%W select clear; %W cursor @%x; 
	checkFocus %W; %W select from @%x
    }
    $w configure -background AntiqueWhite1
    set [set w](disabled) 0
}

# entfernt Blanks am Anfang und Ende des Entries
proc trimEntry {w} {
    set s [string trim [$w get]]
    $w delete 0 999
    $w insert 0 $s
}
------------------------------------------------------

-- 
------------------------------------------------------------------
Thomas Funke  ** E-mail: thf@zelator.in-berlin.de
NeXT-Developer * Unix-Consultant
------------------------------------------------------------------
Newsgroups: comp.lang.tcl