Re: GtkButtons and RUN_FIRST/RUN_LAST



On 26 Oct 2001, Owen Taylor wrote:

> ::clicked is notification that the button was activated. For GtkButton
> it does nothing. 

it is not pure notification though, many derived widgets do stuff in the
::clicked handler (talking third party derivation here as well).
just the base widget not implementing a default handler doesn't make
a signal pure notification.

> For GtkToggleButton and descendents, there is a default handler for
> this which updates the state of the widget. If you want notification
> on the state of the widget, you should connect to the ::toggled 
> signal which is notification of a change to the state.

there's lots of code out there that evals toggle_button->state in a
::clicked handler, which is why ::clicked is RUN_FIRST.
those code portions actually steem (through lots of c'n'p generations)
from one of peter's first togglebutton examples (i think it was actually
testgtk where this first appeared).

> Connecting to ::clicked to get notification of the change is as
> conceptually broken as connecting to ::button_release_event.

nope, ::button_release_event is a completely different matter.
::clicked is the canonical signal on buttons to connect to, how often
have you told people to _not_ connect to ::pressed, ::released or
::button_press_event on buttons?
making it RUN_FIRST, so that derivatives can update state is done
to preserve this simple rule for derivative widgets, which are still
"buttons", as well.

> > if so, a compelling reason would be, to update a widget's state before
> > arbitrary user code is being run, which is the case for the button handlers.
> 
> Well, if this was really a compelling reason, then there would be
> a much more compelling reason to make all event signals RUN_FIRST,
> since they update widget internal state in much more complex ways
> than clicked.

no, especially ::*_event signals may need to be intercepted to tweak a
widget's behaviour which is in general done in gtk through connections,
since derivation and method overloading is so hard.

> > so, is there anything holding off restauration to the original behaviour?
> 
> Well, if you want to do proper model-view-controller with GtkToggleButton, 
> then you only want to change the state of the togglebutton in response
> to changes in the model, not because the user clicked on the
> toggle button. Clicking on the togglebutton should call a method
> on the model to toggle the model.

> In order to do this with RUN_FIRST, what you have to do is
> connect to ::toggled (or ::clicked) and change the state back.
> Which is highly gross. 

heh, togglebutton is still moderately easy to use in this regard, since
you can simply toggle it back to the sate your modell has.
for radiobuttons, things get really complicated, since what you want is:

1) emit: radio-clicked
2) radio-clicked-handler: activate radio option on modell
3) emit: model-changed
4) model-changed-handler: set radio state according to modell (might
   be the same radio state as before)

but this doesn't work with gtk at all, since radios in groups can't
be simply toggled according to model changes, at least not without
trigegring the model _again_. and ungrouped radio buttons can't
be toggled at all.
(i actually had to derive from radiobutton for beast to make it
a toggle button that looks like a radio, so it could display
model radio options)

> While I admit we may have to change this back to keep backwards
> compatibility, would agree that ::clicked _should_ be RUN_LAST?

if i were to create gtk from scratch, i'd probably do things
this way. in general, i'd change a lot of places where gtk currently
plays the model, at least partially. the buttons are just a pretty
simple and comparatively easy to circumvent example.
so ideally, ::clicked would be RUN_LAST, and GtkToggleButton.clicked()
would do nothing else than { set_state (!toggle_button->state); },
same for radio button, so it can be used as a differently drawn
toggle button.

> 
> Regards,
>                                              Owen

---
ciaoTJ




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]