• Re: I can't "break" a binding

    From Helmut Giese@21:1/5 to Luc on Sun May 14 20:13:17 2023
    Luc <[email protected]d> schrieb:

    Here is another problem I can't fix.

    bind $::w <Control-Left> {p.SwitchTabs "left"; break}
    bind $::w <Control-Right> {p.SwitchTabs "right"; break}

    The problem is, a treeview usually has the focus. So when I press ><Control-Left> or <Control-Right>, the tree selection changes as
    if I had just pressed the bare Left/Right key.

    I though "break" was supposed to prevent that. No?
    What works for me is
    return -code break
    HTH
    Helmut

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to All on Sun May 14 14:38:11 2023
    Here is another problem I can't fix.

    bind $::w <Control-Left> {p.SwitchTabs "left"; break}
    bind $::w <Control-Right> {p.SwitchTabs "right"; break}

    The problem is, a treeview usually has the focus. So when I press <Control-Left> or <Control-Right>, the tree selection changes as
    if I had just pressed the bare Left/Right key.

    I though "break" was supposed to prevent that. No?

    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to Helmut Giese on Sun May 14 19:19:11 2023
    On Sun, 14 May 2023 20:13:17 +0200, Helmut Giese wrote:

    Luc <[email protected]d> schrieb:

    Here is another problem I can't fix.

    bind $::w <Control-Left> {p.SwitchTabs "left";
    break} bind $::w <Control-Right> {p.SwitchTabs "right";
    break}

    The problem is, a treeview usually has the focus. So when I press ><Control-Left> or <Control-Right>, the tree selection changes as
    if I had just pressed the bare Left/Right key.

    I though "break" was supposed to prevent that. No?

    What works for me is
    return -code break
    HTH
    Helmut


    Thanks, but it doesn't work for me. The problem remains.


    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andreas Leitgeb@21:1/5 to Luc on Mon May 15 10:24:30 2023
    Luc <[email protected]d> wrote:
    Here is another problem I can't fix.

    bind $::w <Control-Left> {p.SwitchTabs "left"; break}
    bind $::w <Control-Right> {p.SwitchTabs "right"; break}

    The problem is, a treeview usually has the focus. So when I press
    <Control-Left> or <Control-Right>, the tree selection changes as
    if I had just pressed the bare Left/Right key.

    I though "break" was supposed to prevent that. No?

    The other reply about "return -code break" would have been relevant
    only, when called from the body of a procedure that would be called
    from the binding... e.g. if procedure p.SwitchTabs were yours,
    then from within that you'd do the return -code break.

    If break (directly in the binding) doesn't work for you, then the
    problem is elsewhere...

    First check would be, whether your break is even reached. make the
    binding look like: {p.SwitchTabs "left"; puts checkpoint; break}
    and check, if you get to see the checkpoint in the console.
    if you don't see it, put a second puts checkpoint2 before p.SwitchTabs.
    If you then see checkpoint2, but not checkpoint, then the procedure p.SwitchTabs seems to do some other return -code ... trick that would
    cause your break to not be executed.

    If you see the checkpoint, (or don't see the checkpoint2) then you need
    to check the "bindtags" for the widget $::w maybe in that sequence
    some other thing fires first, and already handes Right/Left, before it
    gets to your binding.

    Another hint: carefully read the documentation for "bindtags".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emiliano Gavilan@21:1/5 to Luc on Tue May 16 14:52:11 2023
    On Sun, 14 May 2023 14:38:11 -0300
    Luc <[email protected]d> wrote:

    Here is another problem I can't fix.

    bind $::w <Control-Left> {p.SwitchTabs "left"; break}
    bind $::w <Control-Right> {p.SwitchTabs "right"; break}

    The problem is, a treeview usually has the focus. So when I press <Control-Left> or <Control-Right>, the tree selection changes as
    if I had just pressed the bare Left/Right key.

    I though "break" was supposed to prevent that. No?
    --
    Luc

    Events are delivered to the widget which has the focus, and they are
    processed in the order given by the [bindtags] command. I pseudocode,
    a Tcl script implementing bindings does

    foreach tag [bindtags $win] {
    uplevel #0 [bind $tag $sequence]
    }

    By default, a wiget binding tags are, in order, its name, its class,
    its nearest toplevel up in the window hierarchy and the "all" tag.

    list $win [winfo class $win] [winfo toplevel $win] "all"

    In your case, I assume $::w is a toplevel widget, so it comes after
    the treeview class tag (Treeview), on which are set all the bindings
    that define treeview's default behaviour.

    So when your binding fires, the treeview already has changed the selection.
    The [break] command only avoids the firing of the "all" tag, should it
    have any binding set to <Control-Left> or right.

    As a workaround, you can try setting a more specific binding on Treeview (untested)

    bind Treeview <Control-Left> {# do nothing}
    bind Treeview <Control-Right> {# do nothing}

    --
    Emiliano Gavilan <[email protected]>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to Emiliano Gavilan on Tue May 16 21:33:09 2023
    On Tue, 16 May 2023 14:52:11 -0300, Emiliano Gavilan wrote:

    Events are delivered to the widget which has the focus, and they are processed in the order given by the [bindtags] command. I pseudocode,
    a Tcl script implementing bindings does

    foreach tag [bindtags $win] {
    uplevel #0 [bind $tag $sequence]
    }

    By default, a wiget binding tags are, in order, its name, its class,
    its nearest toplevel up in the window hierarchy and the "all" tag.

    list $win [winfo class $win] [winfo toplevel $win] "all"

    In your case, I assume $::w is a toplevel widget, so it comes after
    the treeview class tag (Treeview), on which are set all the bindings
    that define treeview's default behaviour.

    So when your binding fires, the treeview already has changed the
    selection. The [break] command only avoids the firing of the "all" tag, should it have any binding set to <Control-Left> or right.

    As a workaround, you can try setting a more specific binding on Treeview (untested)

    bind Treeview <Control-Left> {# do nothing}
    bind Treeview <Control-Right> {# do nothing}


    It works. Thank you!

    However,

    This doesn't work:

    bind Treeview <Control-Left> {break}
    bind Treeview <Control-Right> {break}
    bind $::w <Control-Left> {p.SwitchTabs "left"; break}
    bind $::w <Control-Right> {p.SwitchTabs "right"; break}


    But this works:

    bind Treeview <Control-Left> {break}
    bind Treeview <Control-Right> {break}
    bind Treeview <Control-Left> {p.SwitchTabs "left"; break}
    bind Treeview <Control-Right> {p.SwitchTabs "right"; break}

    So not only do I have to kill an existing binding, I have to redefine it
    even for a specific widget (Treeview) or else it won't work.

    Seeing that I intend to let the user select their own keyboard
    combinations for every action, I suspect this is going to be a bit of
    a lot of headache for me.


    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Wed May 17 01:48:39 2023
    From: Luc <[email protected]d>
    Date: Wed May 17 00:33:09 GMT 2023
    Subject: I can't "break" a binding

    The first two commands are not needed.

    But this works:

    bind Treeview <Control-Left> {break}
    bind Treeview <Control-Right> {break}

    The second two define (or redefine) the binding script.

    bind Treeview <Control-Left> {p.SwitchTabs "left"; break}
    bind Treeview <Control-Right> {p.SwitchTabs "right"; break}

    So not only do I have to kill an existing binding, I have to redefine it
    even for a specific widget (Treeview) or else it won't work.


    On my system (8.6.13 on Slackware 15)
    defining a binding on the treeview window that ends with a break command
    hides a binding defined on the Treeview class that would match the same event.

    For example:

    package require Tk

    destroy .tv

    pack [ttk::treeview .tv]

    # build tree
    .tv insert {} end -id A -text a
    .tv insert {A} end -id A1 -text a1
    .tv insert {A} end -id A2 -text a2

    .tv insert {} end -id B -text b
    .tv insert {B} end -id B1 -text b1
    .tv insert {B} end -id B2 -text b2
    .tv insert {B} end -id B3 -text b3


    # Note bindtags .tv returns: .tv Treeview . all

    # The Treeview bindings for Left and Right open and close the nested entries
    # (neither Control or Shift have any effect)

    # However after executing tvbc to bind the Control-Left and Control-Right

    proc tvbc {} {
    bind .tv <Control-Key-Left> {puts "ctl-left"; break}
    bind .tv <Control-Key-Right> {puts "ctl-right"; break}
    }

    Control-Left or Control-Right will only display the message, the treeview remains unchanged.
    while a Left Right Shift-Left or Shift-Right open and close the nested entries as before.
    The .tv window bindings (with a break) hide any Treeview bindings that might match the same event.

    Is'nt this what you want?

    Dave B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Luc on Wed May 17 02:15:35 2023
    Luc <[email protected]d> wrote:
    On Tue, 16 May 2023 14:52:11 -0300, Emiliano Gavilan wrote:

    Events are delivered to the widget which has the focus, and they are
    processed in the order given by the [bindtags] command. I pseudocode,
    a Tcl script implementing bindings does

    foreach tag [bindtags $win] {
    uplevel #0 [bind $tag $sequence]
    }

    By default, a wiget binding tags are, in order, its name, its class,
    its nearest toplevel up in the window hierarchy and the "all" tag.

    list $win [winfo class $win] [winfo toplevel $win] "all"

    In your case, I assume $::w is a toplevel widget, so it comes after
    the treeview class tag (Treeview), on which are set all the bindings
    that define treeview's default behaviour.

    So when your binding fires, the treeview already has changed the
    selection. The [break] command only avoids the firing of the "all" tag,
    should it have any binding set to <Control-Left> or right.

    As a workaround, you can try setting a more specific binding on Treeview
    (untested)

    bind Treeview <Control-Left> {# do nothing}
    bind Treeview <Control-Right> {# do nothing}


    It works. Thank you!

    However,

    This doesn't work:

    bind Treeview <Control-Left> {break}
    bind Treeview <Control-Right> {break}

    Changing the binding to 'break' is *very* different from changing it to
    a 'comment' (which does nothing). Alternately, an empty string
    completely removes the existing binding.

    bind $::w <Control-Left> {p.SwitchTabs "left"; break}
    bind $::w <Control-Right> {p.SwitchTabs "right"; break}

    Because the bindtags execute first, and because you changed to 'break',
    you prevented your binding on $::w from firing, because the 'break' in
    the bindtags stopped further execution of additional bindings for the event.

    But this works:

    bind Treeview <Control-Left> {break}
    bind Treeview <Control-Right> {break}
    bind Treeview <Control-Left> {p.SwitchTabs "left"; break}
    bind Treeview <Control-Right> {p.SwitchTabs "right"; break}

    Your second two replace your first two, so the above is exactly
    identical to this:

    bind Treeview <Control-Left> {p.SwitchTabs "left"; break}
    bind Treeview <Control-Right> {p.SwitchTabs "right"; break}

    Which means you have replaced the existing default binding with your
    own. And without a 'break' messing things up, your bindings get
    executed.

    So not only do I have to kill an existing binding, I have to redefine it
    even for a specific widget (Treeview) or else it won't work.

    Redefining it is exactly "killing an existing binding". There's no
    'two step' process here. You don't have to 'first kill' then
    'redefine'. Just bind a new script (with no + prefix), and that
    replaces the old script.

    Another poster in a different thread suggested you "carefully read the
    bind manpage" -- you really *do* need to do so.

    Seeing that I intend to let the user select their own keyboard
    combinations for every action, I suspect this is going to be a bit of
    a lot of headache for me.

    Building anything that is super flexible (such as user selection of
    their own keyboard bindings) is always going to be a "bit of a headache
    for you".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)