Re: MVC and GTK



Paul Barton-Davis <pbd op net> writes:

> >Here's how to do it, cleanly, with existing GTK+:
> 
>   [ ... ]
> 
> Owen, having worked hard to find an example that would contradict
> yours, plus having used the same basic method as you suggest quite a
> lot, I broadly agree with you. But the toggle button case needs a
> correction.
> 
> I still have a bad feeling about all this, but perhaps there really is
> no cleaner way to do MVC. After all, the whole idea of a "silent"
> change in the state of an object that others have a registered
> interest in seems very dangerous.
> 
> Anyway, here's a revised walk through the toggle button example to
> show how I handle this these days:
> 
> void
> my_data_set_state (MyData *my_data, gboolean new_state)
> {
>      if (my_data->state == new_state)
>          return;
>  
>      my_data->state = new_state;
>      // generic C/C++ psuedocode
>      signal_emit (SIGNAL_OBJECT(my_data),"state-changed"); 
> }
> 
> void
> state_change_handler (MyData *my_data)
> 
> {
>    gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(button));
> 					    
>    if (my_data->state != active) {
>           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), 
>                                         my_data->state);
>    }
> }
> 
> void
> toggled_handler (GtkWidget *button, gpointer data)
> {
>   MyData *my_data = data;
>   gboolean new_state = 
>      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
>  
>   if (my_data->state != new_state)
>       my_data_set_state (my_data, new_state);
> }
> 
> So far, so good.
> 
> but now lets get a little more precise. the role of the toggle button
> is to both *initiate* a change in the state and also to *display* the
> current state. the initiation of the change doesn't guarantee that the
> state will change or when it will change, and the button shouldn't
> change its appearance until the state has really altered.
> 
> so using "toggled" doesn't really work at all, since by the time its
> been emitted, the button has already (effectively) been modified. 

If you want to simulate this, just change the state of the button
back. There will be a tiny flicker, but since the user pressed
the button and expected something to happen that isn't a problem.

  if (my_data->state != new_state)
    {
       my_data_set_state (my_data, new_state);
       if (my_data->state != new_state)
         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), 
                                       my_data->state);
    }

Of course, doing this sort of thing isn't quite as conceptually
clean as deriving from some sort of "boolean state object"
with a set() / ::changed interface, but for normal uses of
toggle buttons, the standard GTK+ interface is a whole lot
more convenient.

Remember, that in any case, this sort of thing is a horrible UI for
the user. If the button is sensitive, then they should be allowed to
change it.  The only excuse for wanting to do this would be if the act
of changing the button encountered an error.
 
> instead, we have to use button_press_event and stop propagation of the
> event for the time being. so now we have:
> 
> gint
> button_press_handler (GtkWidget *widget, GdkEventButton *ev, gpointer *data)
> 
> {
> 	MyData *my_data = (My_Data *) data;
> 	gboolean old_state = 
> 	   gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget));
> 						
>         if (my_data->state == old_state) {
> 
> 	      [ initiate change to !old_state, which may take a while
> 	        to be carried out and may happen in another thread ]
>         }
> 
>         gtk_signal_emit_stop_by_name (GTK_OBJECT(button), 
> 				      "button_press_event");
> }
> 
> then we have a handler for the state change as shown above. 

This is absolutely evil. Don't do it. If you doubt me on that,
in your app, tab to the button and hit the space bar...

However, that there is no way of doing this, I consider somewhat
of a problem so I just entered:

 http://bugzilla.gnome.org/show_bug.cgi?id=40239

This is _not_ to say that I think you should do this, or anybody
should do this, but it should be possible to do this.
  
> it works. so we have to avoid using "toggled" at all, since it comes
> too late in the game. And thats the key for toggle buttons. Even so,
> this is pretty "deep" GTK coding, in the sense that its totally
> unintuitive for the newish GTK user.

IMO, alternative ways of setting up togglebuttons would add
a lot of complexity that isn't needed, except in some sense
of ideological purity, and would be less convenient for the
common case.

An observation I've heard about Swing is that Model-View is convenient
for the big widgets, and a pain for the little widgets.

For GTK+-2.0, we'll be introducing Model-View widgets for 
the multi-line text edit and list/tree widgets, but I don't
see making things like GtkToggleButton Model-View.

Regards,
                                        Owen




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