Ernst Lippe <[EMAIL PROTECTED]> writes:
> On 01 Mar 2003 17:39:56 +0100
> Sven Neumann <[EMAIL PROTECTED]> wrote:
> > Hi,
> > Ernst Lippe <[EMAIL PROTECTED]> writes:
> > > A set of previews that you want to synchronize is an example of a
> > > constraint based system where you want to solve a set of constraints
> > > among multiple objects. The naive implementation of such a system is
> > > to let each object synchronize with all others when its value is changed.
> > > In general this is not a very good architecture:
> > > * It is expensive, you need at least n * (n - 1) synchronizations.
> > > * It frequently leads to oscillatory behaviour.
> > >
> > > As an example where you could get funny behavior, take two previews that
> > > show the area around a certain point at different magnifications.
> > > Assume that the user scrolls in preview A. Now A will update the
> > > position of B. Because B is updated it will attempt to update
> > > A's position. In all implementations that I can think of there
> > > are choices for the scale factor such that the new position for
> > > A is different from the position that was set by the user.
> > > So A's position changes again and A will try to update B a
> > > second time. Eventually, this will probably stabilize, but
> > > when there are 3 previews with different magnifications there
> > > are probably cases where the oscillations never stabilize.
> > >
> > > The standard solution for these problems is to have some
> > > central arbitrator that makes global decisions for all objects.
> > >
> > > When you have a seperate signal for user operations this is
> > > a nice hook for such an arbitrator.
> > > It is of course possible to implement an arbitrator without these
> > > signals but its implementation seems a lot messier. Probably
> > > you would need some global arbitration flag and change the way
> > > that "value-changed" signals are handled based on the value of
> > > this flag. You would also have to be careful about subsequent
> > > operations by the user before the arbitration computations
> > > are finished.
> > we usually solve this problem blocking the signal handlers when doing
> > the update:
> > http://developer.gnome.org/doc/API/2.0/gobject/gobject-Signals.html#g-signal-handlers-block-by-func
> > This is IMO cleaner and simpler than adding an extra signal.
> But blocking the signals on a GtkAdjustment only prevents the propagation of
> signals, it does not prevent an update of the underlying value. When
> the signal handlers are not sufficiently fast it is possible that the
> user has scrolled or zoomed while the signal handlers were blocked.
Again, you should understand how GObject signals work. They operate
purely synchronously. A signal handler cannot be "too slow" because
the only thing your program is doing while emitting the signal is
emitting the signal. When the call to g_signal_emit() returns all
handlers have been called in order of connection.
> In that case the underlying adjustment of the preview in which the user
> performed the operation will be updated but other components will not
> be notified. With scrolling this might be acceptable but with zooming
> the differences in magnification between multiple, supposedly synchronized,
> previews are very obvious. The only fundamental solution would be to block all
> updates by the user to each preview adjustment. I don't think that that
> this can be done on the adjustements themselves, the only solution I can
> see at the moment is to "freeze" all GUI components that could modify
> these adjustments.
The solution I propose is simply updating the preview in an idle
function. This way you can change the underlying model as often
as you like and the idle logic will make sure subsequent changes
are compressed into a single update of the GUI.
Actually, the preview should update itself when it gets exposed. GTK
already compresses and idles updates of the GUI, so everything that
should be needed is calling gtk_widget_queue_draw() or
gtk_widget_queue_draw_area() on the parts of the preview you want to
update and the "expose" handler will do it's job of re-rendering at
just the right time, namely immediately before the stuff is drawn to
All the complications you mention above are IMHO no-issues given
the provided GTK idle draw logic and GSignal features are used
the right way.
Gimp-developer mailing list