Ernst Lippe <[EMAIL PROTECTED]> writes:

> On 26 Feb 2003 17:29:37 +0100
> Sven Neumann <[EMAIL PROTECTED]> wrote:
> > Hi,
> > 
> > Ernst Lippe <[EMAIL PROTECTED]> writes:
> > 
> > > The point is the following. In the current implementation the preview
> > > widget consists of the following components from top to bottom: the image, 
> > > the progress bar and the zoom controls. When scrollbars should be added
> > > the horizontal scrollbar should be located between the progress bar and
> > > the image. So it is not possible to add scrollbars by simply wrapping
> > > the entire current preview but the preview itself must be modified.
> > > Adding scrollbars makes the layout algorithm more complex.
> > 
> > IMO the preview widget should only be the preview, nothing else. If
> > possible it should expose two adjustments so that you can easily add
> > scrollbars. Progress-bar, zoom-control and scrollbars don't belong to
> > the preview widget itself. They can be added by a composite widget.
> That is already in my current design. There is a bare preview widget
> that can do scaling and scrolling but has no GUI for these operations.
> There is another composite widget that can include a progress bar and
> zoom buttons. Having a standard composite widget makes life easier for
> developers and gives more uniformity among the plug-ins.
> > > > Actually if you go for two adjustments and
> > > > expose them in your API you don't need to deal with signals at all
> > > > since it should be sufficient to connect to the "value_changed" and
> > > > "changed" signals of the two adjustments.
> > >
> > > The reason for a separate signal is that this makes it possible to
> > > distinguish between between modifications that are initiated by the
> > > user via the preview GUI and modifications that were initiated
> > > programmatically via the API.  When this distinction is never
> > > important the requirement could be dropped.
> > 
> > Why should a widget behave differently if changed by the user or
> > programmatically via the API? That sounds like a broken concept.
> Why? This is simply a method to get a hook for trapping operations that
> the user has performed on the GUI of the widget. 
> 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.

You should make yourself familiar with what's actually possible
when using GObject signals correctly.

The canonical way to solve the issue you mentioned is to let
the widget itself perform it's operation in the signal's
default handler (remember signals are just especially mighty
virtual functions) and register the signal with G_SIGNAL_RUN_LAST.
This way user signal connections are performed *before* the
widget's default implementation and the user callback can choose
to stop the signal or do whever voodoo it likes.

All the "hooks" and "central arbitrators" your are telking about are
already implemented in the GSignal system.

BTW, the example of synchronizing two preview's scrolling offsets is
rather an example of higher level logic than something the widgets
themselves should provide. The "arbitrator" looks very much like a
common signal handler that has some simple


/* do stuff */


stuff to sync the views. That's something implemented in the
GIMP dozens of times and really nothing we have to worry about.

Gimp-developer mailing list

Reply via email to