Re: Comment and a question



>I have a GtkCheckMenuItem inside of my application's toplevel menu.
>It controls whether or not a certain widget in the application is
>displayed.  Internally, I have a gboolean which holds the current
>state of the widget.  When that gboolean is true, the widget is shown,
>and when it's not, it's not shown.  When I create the
>GtkCheckMenuItem, I do it with a special function that I pass the
>gboolean to, so that on application start up, the check button is
>pressed down if the gboolean was true, and is up if it was false for
>on/off.
>
>The problem is that there is another function which indirectly
>affects the value of the gboolean value (not some random side-affect,
>it's supposed to work that way) -- but how do I keep the
>GtkCheckMenuItem "in sync" with the current value of the gboolean
>value when more than just the signal function attached to the menu
>item has the power to change the value of that boolean?

You've got a classic case of MVC (Model-View-Controller)
design. You *must* propagate changes in the Model up to the View(s)
for this to work. There is simply no other way to do this. Now, how
you go about doing it offers some flexibility. The most obvious is:

1) you set the CheckMenuItem whenever you set the boolean value, and
2) in the handler for changes in the CheckMenuItem you do this:

   if (CheckMenuItem->state != boolean_value) {
        change boolean_value;
   }

My thanks to Owen for pointing this not-really-MVC-but-good-enough
approach. 

Another approach would be to drop the boolean value, use a
GtkAdjustment, and gtk_adjustment_set_value() to alter the setting,
then catch the "changed" signal to the adjustment. This will have a
slightly higher price in terms of cpu cycles, but if its not happening
in an inner loop, the convenience is probably worth it.

But one way or another, you break the MVC model if you don't propagate
something upwards when the value changes.

-------------------------------------------------------------

Now, of course, if you were using C++, then you use libsigc++, which
is specifically designed to let anonymous components of a system get
notified about various events. You'd do this:

class NotifyingBoolean : public SigC::Object
{
  public:
	Signal<void,gboolean> changed;

	gboolean value() { return _value; }

	void set(gboolean val) {
	   _value = val;
	   changed (_value);
	}

  private:	
	gboolean _value;
};

NotifyingBoolean the_boolean;

Other bits of code that needed to know about this would do:

      the_boolean.changed.connect (slot (some_object, &SomeObject::function));

or
      the_boolean.changed.connect (slot (some_function));

And voila, its done. Are you ready to talk C++ yet ? :)

--p (i luv libsigc++)





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