I want to have such a thing:
This operation needs yet another "item" to perform this operation. So when I
click this button, the application should request the user to click on the
listbox in order to select the second "argument" for this operation, then
return to the normal work.
I cannot do it on "multiple selection" because the order of arguments is
fixed.
So far, I knew that I should "grab" the pointer for the listbox window and
temporarily bind the <Button-1>, however I cannot imagine that - I don't know
if I should wait for something and somehow ensure that the window will be
correctly refreshed. It would be then something like
grab .f.l
bind .f.l <Button-1> item_selected
proc item_selected {} {
set ::g_selection [.f.l curselection]
grab release .f.l
?? how to release bind ??
}
But after that "bind" the execution must return to the event looping, right?
Is that correct what I'm trying to do?
--
// _ ___ Michal "Sektor" Malecki <sektor(whirl)kis.p.lodz.pl>
\\ L_ |/ `| /^\ ,() <ethourhs(O)wp.pl>
// \_ |\ \/ \_/ /\ C++ bez cholesterolu: http://www.intercon.pl/~sektor/cbx
"I am allergic to Java because programming in Java reminds me casting spells"
Hope this helps,
Aleks
Example code:
proc lb {} {
package require Tk
toplevel .t
listbox .t.lb -height 20 -selectmode single
pack .t.lb
.t.lb insert end 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
.t.lb selection set 7
}
proc move {} {
set sel [.t.lb curselection]
set vwaitVar 0
bind .t.lb <Button-1> "set vwaitVar 1"
vwait vwaitVar
set new [.t.lb curselection]
# Insert first selection after second selection
if { $new > $sel } {
.t.lb insert [expr $new+1] [.t.lb get $sel]
.t.lb delete $sel
} else {
.t.lb insert [expr $new+1] [.t.lb get $sel]
.t.lb delete [expr $sel+1]
}
bind .t.lb <Button-1> "set vwaitVar 1"
}
lb
move
> Hope this helps,
> Aleks
> Example code:
Looks fine; I forgot that I can just set the variable and vwait for it.
Thankx.
Be aware that vwaits nest. That is, while you're vwaiting it might be
possible for the user to cause the vwait to happen again, causing two
vwaits. They will unroll in reverse order.
In short: vwait should only rarely be used, and only if you fully
understand the ramifications.
Your original solution sounded better to me -- do a grab on a widget
that only has a button binding. All other user events will be ignored.
Simply release the grab after the first button press.
By grabbing the mouse to the listbox, you might prevent the
user from scrolling in his intended item, if it is not
currently visible, because the scrollbar is a different widget.
You can set a special flag when user clicks first item,
then ask him (e.g. through a label in the status-bar) to
select argument item, and in the normal click-handler
you recognize the previously set flag, and handle the
new click as an "argument-click".
Of course there should be ways to reset that flag through
some cancel-feature, and furthermore a way to correct a
wrong (mis-targetted click). This is necessary, since often
a user has to click into the listbox first, just to set the
focus on it and to be able to scroll it with mouse-wheel or
cursor-keys, and only then he'll scroll to right position
and then click what he really wanted to click.
Acting on the first click in the listbox is very user-unfriendly.
> By grabbing the mouse to the listbox, you might prevent the
> user from scrolling in his intended item, if it is not
> currently visible, because the scrollbar is a different widget.
Yes, that's correct. Despite I can scroll by mouse wheel, clicking the
scrollbar causes that... some item has been selected.
> You can set a special flag when user clicks first item,
> then ask him (e.g. through a label in the status-bar) to
> select argument item,
That's obvious ;)
> and in the normal click-handler
> you recognize the previously set flag, and handle the
> new click as an "argument-click".
Hmm... the local state?
Sounds good ;)
> Of course there should be ways to reset that flag through
> some cancel-feature,
Yes.
"Please select destination branch (Esc to cancel)"
> and furthermore a way to correct a
> wrong (mis-targetted click). This is necessary, since often
> a user has to click into the listbox first, just to set the
> focus on it and to be able to scroll it with mouse-wheel or
> cursor-keys, and only then he'll scroll to right position
> and then click what he really wanted to click.
After it is selected there will be displayed some modal window, which will
show the user's selection to confirm and maybe with additional options.
Ok, I'll precise: this is a small tool for ClearCase. It has to provide two
capabilities the ClearCase (sucking!) GUIs lack: delete multiple versions and
merging versions with also possible selection of the base version for the
source version. So after the user clicks the destination version he will be
asked for confirmation and also possible selection of the base version (again
one click).
Looxlike also I would have to provide it as a generic facility to make it
possible to perform a "requested click".
> Acting on the first click in the listbox is very user-unfriendly.
However I expect problems. When I request selection, the user should be not
able to, for example, click another button, exit the application (although it
wouldn't be harmful) and other such things (this application does not have any
menu, but only buttons; however if it had, the menu should be disabled as
well).
That is a good point. One work-around is to do the grab on the scrollbar
instead of the listbox. Add an additional binding on the scrollbar for
<1> that checks whether the click happened on the scrollbar or on the
listbox, and ignore anything that's on the scrollbar. If the click is
over the listbox, figure out which item is under the listbox and Do The
Right Thing.
Another solution which would likely work just as well, is to temporarily
remove all bindtags from all widgets except the listbox and scrollbar.
When you get the extra click, restore all the bindtags (*)
I'm sure there are other solutions. The best solution might be to
redesign the UI such that it doesn't require this mode where everything
is locked up between two mouse clicks.