On Sat, 01 Mar 2003 12:46:57 +0100 Michael Natterer <mitch@xxxxxxxx> wrote: > Ernst Lippe <ernstl@xxxxxxxxx> writes: > > > On 26 Feb 2003 17:29:37 +0100 > > Sven Neumann <sven@xxxxxxxx> wrote: > > > > > Hi, > > > > > > Ernst Lippe <ernstl@xxxxxxxxx> 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 > > g_signal_handlers_block() > > /* do stuff */ > > g_signal_handlers_unblock() > > stuff to sync the views. That's something implemented in the > GIMP dozens of times and really nothing we have to worry about. I believe you are proposing a similar solution as Sven. Please see my reply to his post, for the reason why I am not really comfortable with this proposal. greetings, Ernst