Version 4 of Behavior of break for text tag bindings

Updated 2003-01-01 12:25:55

The break command in a text widget tag binding does not prevent widget and class level bindings from firing. See the c.l.t discussion at [L1 ].

Here is a session that shows break doesn't stop the widget and class bindings from firing:

 % text .t
 .t
 % pack .t
 % .t insert 1.0 "some text" myTextTag
 % bind Text <1> "puts Text"
 % bind .t <1> "puts .t"
 % .t tag bind myTextTag <1> "puts myTextTag; break"
 % # Now click on the text
 myTextTag
 .t
 Text

This behavior is undesirable in cases where the text tag binding changes some state (such as the insertion cursor location) and then the Text class binding changes the same state, thereby undoing what the tag binding did.

One workaround is to add an entry to the binding chain before the Text class that will execute break if the event happened at an index containing the text tag. The following shows how to block the Text class binding for a mouse button-1 event that happens on a text tag called myTextTag:

 bind mySpecialBindings <1> {if {[lsearch [%W tag names @%x,%y] myTextTag] >= 0} break}
 bindtags .t {.t mySpecialBindings Text . all}

ulis, 2003-01-01:

Here is my explanation of what occurred. Can somebody correct it if it's not correct?

  • Before, I change sligthly the code to add a second text binding:
  text .t
  pack .t
  .t insert 1.0 "some text" {myTextTag1 myTextTag2}
  bind Text <1> "puts Text"
  bind .t <1> "puts .t"
  .t tag bind myTextTag1 <1> "puts myTextTag1; break"
  .t tag bind myTextTag2 <1> "puts myTextTag2"
  • Then, I put here the relevant sections of the Tk 8.4 manual.

Text binding:

It is possible for the current character to have multiple tags, and for each of them to have a binding for a particular event sequence. When this occurs, one binding is invoked for each tag, in order from lowest-priority to highest priority. If there are multiple matching bindings for a single tag, then the most specific binding is chosen (see the manual entry for the bind command for details). continue and break commands within binding scripts are processed in the same way as for bindings created with the bind command.

If bindings are created for the widget as a whole using the bind command, then those bindings will supplement the tag bindings. The tag bindings will be invoked first, followed by bindings for the window as a whole.

Widget binding:

It is possible for several bindings to match a given X event. If the bindings are associated with different tag's, then each of the bindings will be executed, in order. By default, a binding for the widget will be executed first, followed by a class binding, a binding for its toplevel, and an all binding. The bindtags command may be used to change this order for a particular window or to associate additional binding tags with the window.

The continue and break commands may be used inside a binding script to control the processing of matching scripts. If continue is invoked, then the current binding script is terminated but Tk will continue processing binding scripts associated with other tag's. If the break command is invoked within a binding script, then that script terminates and no other scripts will be invoked for the event.

  • Here is my explanation.

.t has two widget binding tags that match <1>: Text and .t. By default, .t bindtags list is: {.t Text . all}. At the occurrence of <1>, the fired widget binding tags sequence will be: .t, then Text.

"some text" has two text binding tags: myTextTag1 and myTextTag2, in that order. At the occurrence of <1> inside "some text", the fired text binding tags sequence will be: myTextTag1, then myTextTag2.

The text bindings will be fired BEFORE the widget bindings. (if the <1> is fired for .t; that is: is not intercepted before)

So, at the <1> event inside "some text":

  1. we should see the result of the binding of the myTextTag1 text tag,
  2. we shouldn't see the result of the binding of the myTextTag2 text tag (because of the break inside the script associated to the myTextTag1 text binding tag),
  3. we should see the result of the binding of the .t widget tag,
  4. we should see the result of the binding of the Text widget tag.

A break inside the script associated with the .t widget tag would prevent the firing of the script associated to the Text widget tag.

It appears that a break inside the script of a text binding tag DOES NOT prevent the firing of a script associated to the widget.