RaXmToggleButtonSetState(w, True, True): { XEvent event; event.xbutton.type = ButtonRelease; event.xbutton.x_root = 0; event.xbutton.y_root = 0; XtCallActionProc(w,"Arm",&event,0,NULL) XtCallActionProc(w,&qu
Hi there,
I'm having a problem with 3 radio buttons in my GUI. The bank of radio
buttons is a radioBox widget with three toggleButton children that
each have ONE_OF_MANY set.
Here's how the toggle buttons are intended to work: The user is allowed
to make a selection but if it doesn't work out (he selected something
that turns out to not work out), the valueChangedCallback for the
toggle set by the user displays a pop-up error to the user and resets
the default toggle button as the selected button.
Here is the problem: I'll call the three radio buttons "A", "B", and
"C". First A is selected (the default) then the user selects B, this
works. But "B's" valueChangedCallback determines (on-the-fly) that "B"
won't work out and then attempts to set "A" programmatically. "A" now
*appears* to be set but now every time the user attempts to reselect
"B", its Arm callback is called and its Disarm callback is called but
its valueChangedCallback is NOT called. "B" still thinks its selected
and refuses to be selected, even though it doesn't appear to be
selected and "A" does appear to be selected.
Normally, I would just call:
XmToggleButtonSetState(p_playbackinit->A, True, True)
from the valueChangedCallback for "B" to unset "B" and set "A. But
this doesn't work because I am using Motif 2.2.1, which has a bug when
a toggle button is set programmatically. So I'm using this workaround
code from a previous post to this group by Fred Kleinschmidt:
XmToggleButtonSetState(p_playbackinit->A, True, True);
event.xbutton.type = ButtonRelease;
event.xbutton.x_root = 0;
event.xbutton.y_root = 0;
/* turn on A */
XtCallActionProc(p_playbackinit->A, "Arm", &event, NULL, 0);
XtCallActionProc(p_playbackinit->A, "Select", &event, NULL,0);
XtCallActionProc(p_playbackinit->A, "Disarm", &event, NULL,0);
Unfortunately, this workaround is not working for me. It still acts as
though "B" is selected although "A" looks selected.
I even tried telling the radioBox parent which one was set:
XtVaSetValues(p_playbackinit->radioBox, XmNmenuHistory,
p_playbackinit->A, NULL);
But this didn't help either.
With print statements, I can see that when I try to select "B" when it
already thinks it's selected (but "A" looks selected), B's Arm callback
and Disarm callback are both called but the valueChangedCallback is not
called (I guess because "B" isn't aware its value is being changed!)
The only way I can reselect "B" is if I select "C" first, then the
radioBox seems to know that "C" is selected and allows me to reselect
"B".
This is pretty crazy so thought I'd post and see if anyone has any
insight?
Thank you!
Julie
Re: RaXmToggleButtonSetState(w, True, True):
Julie wrote:
[color=blue]
> Normally, I would just call:
>
> XmToggleButtonSetState(p_playbackinit->A, True, True)
>
> from the valueChangedCallback for "B" to unset "B" and set "A. But
> this doesn't work because I am using Motif 2.2.1, which has a bug when[/color]
Indeed, Motif 2.2.1 is notoriously buggy and should never ever be used
in a production environment. If you really can't get 2.1.30 or 2.2.3,
you should declare that the environment is not usable for Motif
applications. Yes, really.
--
Per Espen Hagen
Re: RaXmToggleButtonSetState(w, True, True): { XEvent event; event.xbutton.type = ButtonRelease; event.xbutton.x_root = 0; event.xbutton.y_root = 0; XtCallActionProc(w,"Arm",&event,0,NULL) XtCallActionProc(w
"Julie" <jrsugar@comcast.net> wrote in message
news:1148505875.177808.54350@j55g2000cwa.googlegroups.com...[color=blue]
> Hi there,
> I'm having a problem with 3 radio buttons in my GUI. The bank of radio
> buttons is a radioBox widget with three toggleButton children that
> each have ONE_OF_MANY set.
>
> Here's how the toggle buttons are intended to work: The user is allowed
> to make a selection but if it doesn't work out (he selected something
> that turns out to not work out), the valueChangedCallback for the
> toggle set by the user displays a pop-up error to the user and resets
> the default toggle button as the selected button.
>
> Here is the problem: I'll call the three radio buttons "A", "B", and
> "C". First A is selected (the default) then the user selects B, this
> works. But "B's" valueChangedCallback determines (on-the-fly) that "B"
> won't work out and then attempts to set "A" programmatically. "A" now
> *appears* to be set but now every time the user attempts to reselect
> "B", its Arm callback is called and its Disarm callback is called but
> its valueChangedCallback is NOT called. "B" still thinks its selected
> and refuses to be selected, even though it doesn't appear to be
> selected and "A" does appear to be selected.
>
> Normally, I would just call:
>
> XmToggleButtonSetState(p_playbackinit->A, True, True)
>
> from the valueChangedCallback for "B" to unset "B" and set "A. But
> this doesn't work because I am using Motif 2.2.1, which has a bug when
> a toggle button is set programmatically. So I'm using this workaround
> code from a previous post to this group by Fred Kleinschmidt:
>
> XmToggleButtonSetState(p_playbackinit->A, True, True);
> event.xbutton.type = ButtonRelease;
> event.xbutton.x_root = 0;
> event.xbutton.y_root = 0;
>
>
> /* turn on A */
> XtCallActionProc(p_playbackinit->A, "Arm", &event, NULL, 0);
> XtCallActionProc(p_playbackinit->A, "Select", &event, NULL,0);
> XtCallActionProc(p_playbackinit->A, "Disarm", &event, NULL,0);
>
> Unfortunately, this workaround is not working for me. It still acts as
> though "B" is selected although "A" looks selected.
>
> I even tried telling the radioBox parent which one was set:
>
> XtVaSetValues(p_playbackinit->radioBox, XmNmenuHistory,
> p_playbackinit->A, NULL);
>
> But this didn't help either.
>
> With print statements, I can see that when I try to select "B" when it
> already thinks it's selected (but "A" looks selected), B's Arm callback
> and Disarm callback are both called but the valueChangedCallback is not
> called (I guess because "B" isn't aware its value is being changed!)
>
> The only way I can reselect "B" is if I select "C" first, then the
> radioBox seems to know that "C" is selected and allows me to reselect
> "B".
>
> This is pretty crazy so thought I'd post and see if anyone has any
> insight?
>
> Thank you!
> Julie
>[/color]
One thing you might try:
1. #include <ToggleBP.h> in order to get at the widget's internals
2. In the ArmCallback, explicitly set the state:
(XmToggleButtonWidget)tb = (XmToggleButton)w;
tb->toggle.set = False; /* the select() method toggles this value */
3. If this works, use a lot of comments saying this is a bugfix, not
recommended coding!
Another thing to try would be to completely modify the way things are done.
Use the RowColumn's callbacks instead of the button's. To do this, you
register an XmNentryCallback on the RowColumn radio box at creation time.
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project
Re: RaXmToggleButtonSetState(w, True, True): { XEvent event;event.xbutton.type = ButtonRelease; event.xbutton.x_root = 0;event.xbutton.y_root = 0; XtCallActionProc(w,"Arm",&event,0,NULL)XtCallActio nProc(w,"Select&quo
It is a mess. You can work around the bug by simulating a button press,
and avoid the widget entirely. Use a few calls XtCallActionProc,
passing in a fake event, and make sure the focus doesn't move.
Re: Toggle button setting problem
Thanks for the neat suggestion. For some reason, I have never thought
of doing that. Cool idea and I'll enjoy using that trick again to
easily get at widget internals.
Interestingly, I tried accessing tb->toggle.set for B as you suggest
above and I don't even have to force it to be set to False. The
toggle.set setting of B seems to be set to False automatically when I
programmatically set A. So the question is, why does B still seem to
think it is set if toggle.set is False?
At your suggestion, I am now printing out tb->toggle.set for B as soon
as I set A (and it's False), then I print it out again when B's
callback gets called again (when A is unset) and it's still False, then
I leave B's valueChangedCallback and it's still False. This is all
good.
At this point, B now appears to be unset which is good (A looks set)
but when I click on B, it turns Red (my select color) and the Arm()
callback is called and from there I also print out tb->toggle.set for B
and it's still False. But the valueChangedCallback is still not
getting called -- so it can never get set to True.
Could there be another widget setting that the toggle button could be
using to decide not to call its valueChangedCallback when selected? In
case there might be another widget setting causing this weirdness,
here's what the widget settings are in B's Arm callback, when it looks
unset (and toggle.set is False) but then refuses to call the
valueChangedCallback to become set:
(gdb) print *tb
$2 = {core = {self = 0x843a730, widget_class = 0x83715a0, parent =
0x8439af0, xrm_name = 283, being_destroyed = 0 '\0',
destroy_callbacks = 0x847f5b0, constraints = 0x843a8a4, x = 127, y
= 3, width = 121, height = 25, border_width = 0,
managed = 1 '\001', sensitive = 1 '\001', ancestor_sensitive = 1
'\001', event_table = 0x0, tm = {
translations = 0x83b84d8, proc_table = 0x843a900, current_state =
0x0, lastEventTime = 1371733579},
accelerators = 0x0, border_pixel = 0, border_pixmap = 2, popup_list
= 0x8457b80, num_popups = 1,
name = 0x83860dc "special_plbk", screen = 0x8389f68, colormap = 32,
window = 44040747, depth = 24,
background_pixel = 13026246, background_pixmap = 2, visible = 1
'\001', mapped_when_managed = 1 '\001'}, primitive = {
foreground = 0, shadow_thickness = 0, top_shadow_color = 15197927,
top_shadow_pixmap = 2,
bottom_shadow_color = 7170925, bottom_shadow_pixmap = 2,
highlight_thickness = 2, highlight_color = 0,
highlight_pixmap = 2, help_callback = 0x0, user_data = 0x0,
traversal_on = 1 '\001', highlight_on_enter = 0 '\0',
have_traversal = 1 '\001', unit_type = 0 '\0', navigation_type = 0
'\0', highlight_drawn = 1 '\001',
highlighted = 1 '\001', highlight_GC = 0x83addd8, top_shadow_GC =
0x83ade70, bottom_shadow_GC = 0x83adf08,
convert_callback = 0x0, popup_handler_callback = 0x0,
layout_direction = 206 '?'}, label = {_label = 0x843a6c0,
_acc_text = 0x0, mnemonic = 16777215, mnemonicCharset = 0x843a8e0
"FONTLIST_DEFAULT_TAG_STRING", accelerator = 0x0,
label_type = 2 '\002', alignment = 0 '\0', string_direction = 0
'\0', font = 0x843a8d0, margin_height = 2,
margin_width = 2, margin_left = 17, margin_right = 0, margin_top =
2, margin_bottom = 2, recompute_size = 1 '\001',
pixmap = 2, pixmap_insen = 2, normal_GC = 0x83afff8, insensitive_GC
= 0x83b0090, TextRect = {x = 21, y = 6, width = 96,
height = 13}, acc_TextRect = {x = 28872, y = 2115, width = 0,
height = 0}, skipCallback = 0 '\0', menu_type = 0 '\0',
computing_size = 0 '\0', acc_left_delta = 0, acc_right_delta = 0,
baselines = 0x0, check_set_render_table = 1 '\001'},
toggle = {ind_type = 2 '\002', visible = 1 '\001', spacing = 4,
indicator_dim = 13, indicator_set = 0 '\0',
on_pixmap = 2, insen_pixmap = 2, set = 0 '\0', visual_set = 1
'\001', ind_on = 1 '\001', fill_on_select = 1 '\001',
select_color = 16711680, select_GC = 0x83b8528, background_gc =
0x83b85c0, arm_GC = 0x10847,
value_changed_CB = 0x843a910, arm_CB = 0x843a930, disarm_CB =
0x843a920, Armed = 1 '\001', toggle_mode = 0 '\0',
reversed_select = 0 '\0', indeterminate_pixmap = 2,
indeterminate_insensitive_pixmap = 2, unselect_color = 13026246,
unselect_GC = 0x83b8788, indeterminate_GC = 0x83b8658,
indeterminate_box_GC = 0x83b86f0, ind_left_delta = 17,
ind_right_delta = 0, ind_top_delta = 2, ind_bottom_delta = 2,
detail_shadow_thickness = 2}}
(gdb)
Thanks again for your great suggestion. If you see no clues here, I'll
revert to your second suggestion, letting the radioBox widget control
everything.
I appreciate your help,
Julie
Re: Toggle button setting problem
"Julie" <jrsugar@comcast.net> wrote in message
news:1148588762.303079.166650@i40g2000cwc.googlegroups.com...[color=blue]
> Thanks for the neat suggestion. For some reason, I have never thought
> of doing that. Cool idea and I'll enjoy using that trick again to
> easily get at widget internals.
>
> Interestingly, I tried accessing tb->toggle.set for B as you suggest
> above and I don't even have to force it to be set to False. The
> toggle.set setting of B seems to be set to False automatically when I
> programmatically set A. So the question is, why does B still seem to
> think it is set if toggle.set is False?
>
> At your suggestion, I am now printing out tb->toggle.set for B as soon
> as I set A (and it's False), then I print it out again when B's
> callback gets called again (when A is unset) and it's still False, then
> I leave B's valueChangedCallback and it's still False. This is all
> good.
>
> At this point, B now appears to be unset which is good (A looks set)
> but when I click on B, it turns Red (my select color) and the Arm()
> callback is called and from there I also print out tb->toggle.set for B
> and it's still False. But the valueChangedCallback is still not
> getting called -- so it can never get set to True.
>
> Could there be another widget setting that the toggle button could be
> using to decide not to call its valueChangedCallback when selected? In
> case there might be another widget setting causing this weirdness,
> here's what the widget settings are in B's Arm callback, when it looks
> unset (and toggle.set is False) but then refuses to call the
> valueChangedCallback to become set:
>
> (gdb) print *tb
> $2 = {core = {self = 0x843a730, widget_class = 0x83715a0, parent =
> 0x8439af0, xrm_name = 283, being_destroyed = 0 '\0',
> destroy_callbacks = 0x847f5b0, constraints = 0x843a8a4, x = 127, y
> = 3, width = 121, height = 25, border_width = 0,
> managed = 1 '\001', sensitive = 1 '\001', ancestor_sensitive = 1
> '\001', event_table = 0x0, tm = {
> translations = 0x83b84d8, proc_table = 0x843a900, current_state =
> 0x0, lastEventTime = 1371733579},
> accelerators = 0x0, border_pixel = 0, border_pixmap = 2, popup_list
> = 0x8457b80, num_popups = 1,
> name = 0x83860dc "special_plbk", screen = 0x8389f68, colormap = 32,
> window = 44040747, depth = 24,
> background_pixel = 13026246, background_pixmap = 2, visible = 1
> '\001', mapped_when_managed = 1 '\001'}, primitive = {
> foreground = 0, shadow_thickness = 0, top_shadow_color = 15197927,
> top_shadow_pixmap = 2,
> bottom_shadow_color = 7170925, bottom_shadow_pixmap = 2,
> highlight_thickness = 2, highlight_color = 0,
> highlight_pixmap = 2, help_callback = 0x0, user_data = 0x0,
> traversal_on = 1 '\001', highlight_on_enter = 0 '\0',
> have_traversal = 1 '\001', unit_type = 0 '\0', navigation_type = 0
> '\0', highlight_drawn = 1 '\001',
> highlighted = 1 '\001', highlight_GC = 0x83addd8, top_shadow_GC =
> 0x83ade70, bottom_shadow_GC = 0x83adf08,
> convert_callback = 0x0, popup_handler_callback = 0x0,
> layout_direction = 206 '?'}, label = {_label = 0x843a6c0,
> _acc_text = 0x0, mnemonic = 16777215, mnemonicCharset = 0x843a8e0
> "FONTLIST_DEFAULT_TAG_STRING", accelerator = 0x0,
> label_type = 2 '\002', alignment = 0 '\0', string_direction = 0
> '\0', font = 0x843a8d0, margin_height = 2,
> margin_width = 2, margin_left = 17, margin_right = 0, margin_top =
> 2, margin_bottom = 2, recompute_size = 1 '\001',
> pixmap = 2, pixmap_insen = 2, normal_GC = 0x83afff8, insensitive_GC
> = 0x83b0090, TextRect = {x = 21, y = 6, width = 96,
> height = 13}, acc_TextRect = {x = 28872, y = 2115, width = 0,
> height = 0}, skipCallback = 0 '\0', menu_type = 0 '\0',
> computing_size = 0 '\0', acc_left_delta = 0, acc_right_delta = 0,
> baselines = 0x0, check_set_render_table = 1 '\001'},
> toggle = {ind_type = 2 '\002', visible = 1 '\001', spacing = 4,
> indicator_dim = 13, indicator_set = 0 '\0',
> on_pixmap = 2, insen_pixmap = 2, set = 0 '\0', visual_set = 1
> '\001', ind_on = 1 '\001', fill_on_select = 1 '\001',
> select_color = 16711680, select_GC = 0x83b8528, background_gc =
> 0x83b85c0, arm_GC = 0x10847,
> value_changed_CB = 0x843a910, arm_CB = 0x843a930, disarm_CB =
> 0x843a920, Armed = 1 '\001', toggle_mode = 0 '\0',
> reversed_select = 0 '\0', indeterminate_pixmap = 2,
> indeterminate_insensitive_pixmap = 2, unselect_color = 13026246,
> unselect_GC = 0x83b8788, indeterminate_GC = 0x83b8658,
> indeterminate_box_GC = 0x83b86f0, ind_left_delta = 17,
> ind_right_delta = 0, ind_top_delta = 2, ind_bottom_delta = 2,
> detail_shadow_thickness = 2}}
> (gdb)
>
> Thanks again for your great suggestion. If you see no clues here, I'll
> revert to your second suggestion, letting the radioBox widget control
> everything.
>
> I appreciate your help,
> Julie
>[/color]
I can't see anything here that is obvious. Perhaps try another way:
Instead of modifying the selection in your valueChangedCallback,
register a timeout (0 m/s) and do it there.
Note you always have to be careful about re-entries, since changing the
selected button will usually call your valueChangedCallback on button B
to say it is changing to unselected, then on Button A to say it is being
selected.
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project
Re: Toggle button setting problem
I think you are right. The fact that it's not working likely has
something to do with the fact I am changing the selection in the
valueChangedCallback of another selection. In the other bank of
radiobuttons where I used the workaround and it works perfectly, I
change the selection in a separate callback (a Cancel button). That is
the only difference I can see between where the workaround works and
where it's not working.
I'll try that.
Thanks *very much* for all your help.
Julie
Re: Toggle button setting problem
"Julie" <jrsugar@comcast.net> wrote in message
news:1148647270.711689.37930@y43g2000cwc.googlegroups.com...[color=blue]
>I think you are right. The fact that it's not working likely has
> something to do with the fact I am changing the selection in the
> valueChangedCallback of another selection. In the other bank of
> radiobuttons where I used the workaround and it works perfectly, I
> change the selection in a separate callback (a Cancel button). That is
> the only difference I can see between where the workaround works and
> where it's not working.
>
> I'll try that.
>
> Thanks *very much* for all your help.
>
> Julie
>[/color]
Here's another possible solution: Do all of this in the ArmCallback,
not the valueChangedCallback. In the ArmCallback (if you decide
that the situation does not allow this selection):
1. Set tb->toggle.Armed = False
2. Set tb->toggle.set = False
3. Set tb->toggle->visual_set = True
4. Do NOT call any action procs of other buttons
Presumably (1) above will cause the Select() action to return
immediately without doing anything; (2) and (3) will cause
the Disarm() action to redraw the button as unset.
By not doing anything else (4), the originally set button
will remain set.
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project
Re: Toggle button setting problem
That's a good idea. I'll try it.
I was trying an entry callback for the entire radio box (and commenting
out all the valueChangedCallbacks) but that's not working yet since
when I try to do a XtVaGetValues on the menuHistory item, it first
comes back with the one that was originally set then seems to
immediately get called again reporting the new selection:
plbkInitChoiceBArm_cb: called! toggle setting=0
plbkInitTypeRadiobox_cb: ChoiceA selected
plbkInitTypeRadiobox_cb: ChoiceB selected
plbkInitChoiceBDisarm_cb: called! toggle setting=1
Maybe menuHistory is not the right setting for me to look at.
I'm going to try your new suggestion and see how that goes.
Thanks again,
Julie
Re: Toggle button setting problem
Fred,
Your suggestion to handle everything in the Arm callback works! Thank
you!!!
The only tiny thing yet to solve is the fact that the little box
(probably for keyboard traversal?) around the toggle button the user
selected remains after the selection reverts back. A small price to
pay.
THANK YOU AGAIN!
Julie
Re: Toggle button setting problem
"Julie" <jrsugar@comcast.net> wrote in message
news:1148658647.125294.134180@j55g2000cwa.googlegroups.com...[color=blue]
> Fred,
> Your suggestion to handle everything in the Arm callback works! Thank
> you!!!
>
> The only tiny thing yet to solve is the fact that the little box
> (probably for keyboard traversal?) around the toggle button the user
> selected remains after the selection reverts back. A small price to
> pay.
>
> THANK YOU AGAIN!
> Julie
>[/color]
In the ArmCallback, get XmNmenuHistory - it should be the old selection.
Then, after denying the change, add a call to reset focus:
XmProcessTraversal( oldbutton, XmTRAVERSE_CURRENT );
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project
Re: Toggle button setting problem
Works perfectly now. Thank you!