Proposal for fixing the GimpStatusbar API
This discussion is connected to the gimp-developer-list.gnome.org mailing list which is provided by the GIMP developers and not related to gimpusers.com.
This is a read-only list on gimpusers.com so this discussion thread is read-only, too.
Proposal for fixing the GimpStatusbar API | Raphaël Quinet | 13 Jan 17:50 |
Proposal for fixing the GimpStatusbar API | Michael Natterer | 13 Jan 18:15 |
Proposal for fixing the GimpStatusbar API | Raphaël Quinet | 13 Jan 19:03 |
Proposal for fixing the GimpStatusbar API | Raphaël Quinet | 14 Jan 11:29 |
Proposal for fixing the GimpStatusbar API | Michael Natterer | 14 Jan 11:34 |
Proposal for fixing the GimpStatusbar API | Raphaël Quinet | 14 Jan 13:16 |
Proposal for fixing the GimpStatusbar API | Sven Neumann | 14 Jan 13:25 |
Proposal for fixing the GimpStatusbar API | Raphaël Quinet | 14 Jan 14:09 |
Proposal for fixing the GimpStatusbar API
I would like to fix several bugs related to the usage of the status bar in the image windows. There is bug #120175 proposing to update the GimpStatusbar API, and bugs #51108 and #124040 that could be easily solved by displaying help messages for all tools in the status bar (like the path tool does now). The first issue is to fix the API because the best way to fix the other bugs would be to use a better GimpStatusbar API.
I have checked a bit how the status bar is used in the current code and tried to find a way to solve the problem described in bug #120175, which applies not only to plug-ins but also makes it very hard or even impossible to see the coordinates when you are moving a selection. I don't think that the current model using gimp_statusbar_push() and gimp_statusbar_pop() (inherited from GtkStatusbar) is the best solution. Adding just one function gimp_statusbar_replace() could improve it a bit (if the context_id is known by all parts of the code that need it), but it would be better to reconsider the model.
I propose to change the GimpStatusbar model so that instead of using a variable stack, it uses several pre-defined priority levels (using some global enum, e.g. GimpStatusbarType). Each part of code that wants to update the status bar would just set or clear the message for its own level and there would be no push/pop. The status bar would always display the message that has the highest importance. A part of the code could update a low-priority message (e.g., help for the current tool) while another message of higher priority is still being displayed (e.g., progress for a plug-in). As soon as that message is cleared, the low-priority one would become visible. This is not possible with the current implementation. Another advantage of using pre-defined priority levels is that all parts of the code could use them directly instead of having to pass a context_id or something similar to different parts of the code.
Here are the priority levels that we need, 1 being the highest
priority:
1) Messages from interactive operations (short duration) such as the
size or offsets displayed by the selection tools, move tool, crop
tool, blend tool or measure tool.
2) Messages from plug-ins processing the image.
3) Default messages, which would be the help messages for the current
tool. This would replace the custom messages showing the layer
name, size, etc.
Alternatively, we could use 3) for tool-specific help messages only when the image window has the input focus, and 4) for the user-defined status messages, shown only when the image window is not the active one.
Regarding the implementation, the GimpStatusbar would keep an array containing the message for each priority level. If we still want to derive from GtkStatusbar, then the code in gimpstatusbar.c would take care of calling gtk_statusbar_push()/_pop() when necessary, i.e. when the visible message (highest priority) changes.
Is it a reasonable proposal or am I completely off-track? If this proposal is acceptable, then I could work on it and also propose a list of help messages for all tools in order to solve bugs #51108 and #124040.
-Raphaël
Proposal for fixing the GimpStatusbar API
Raphaël Quinet writes:
I would like to fix several bugs related to the usage of the status bar in the image windows. There is bug #120175 proposing to update the GimpStatusbar API, and bugs #51108 and #124040 that could be easily solved by displaying help messages for all tools in the status bar (like the path tool does now). The first issue is to fix the API because the best way to fix the other bugs would be to use a better GimpStatusbar API.
I have checked a bit how the status bar is used in the current code and tried to find a way to solve the problem described in bug #120175, which applies not only to plug-ins but also makes it very hard or even impossible to see the coordinates when you are moving a selection. I don't think that the current model using gimp_statusbar_push() and gimp_statusbar_pop() (inherited from GtkStatusbar) is the best solution. Adding just one function gimp_statusbar_replace() could improve it a bit (if the context_id is known by all parts of the code that need it), but it would be better to reconsider the model.
I propose to change the GimpStatusbar model so that instead of using a variable stack, it uses several pre-defined priority levels (using some global enum, e.g. GimpStatusbarType). Each part of code that wants to update the status bar would just set or clear the message for its own level and there would be no push/pop. The status bar would always display the message that has the highest importance. A part of the code could update a low-priority message (e.g., help for the current tool) while another message of higher priority is still being displayed (e.g., progress for a plug-in). As soon as that message is cleared, the low-priority one would become visible. This is not possible with the current implementation. Another advantage of using pre-defined priority levels is that all parts of the code could use them directly instead of having to pass a context_id or something similar to different parts of the code.
Here are the priority levels that we need, 1 being the highest priority:
1) Messages from interactive operations (short duration) such as the size or offsets displayed by the selection tools, move tool, crop tool, blend tool or measure tool. 2) Messages from plug-ins processing the image. 3) Default messages, which would be the help messages for the current tool. This would replace the custom messages showing the layer name, size, etc.Alternatively, we could use 3) for tool-specific help messages only when the image window has the input focus, and 4) for the user-defined status messages, shown only when the image window is not the active one.
Regarding the implementation, the GimpStatusbar would keep an array containing the message for each priority level. If we still want to derive from GtkStatusbar, then the code in gimpstatusbar.c would take care of calling gtk_statusbar_push()/_pop() when necessary, i.e. when the visible message (highest priority) changes.
Is it a reasonable proposal or am I completely off-track? If this proposal is acceptable, then I could work on it and also propose a list of help messages for all tools in order to solve bugs #51108 and #124040.
Actually, I would keep the API, copy the implementation from GtkStatusbar to GimpStatusbar, rip what we don't need and add one single new function: gimp_statusbar_replace(), which would replace the message with the given ID and keep the stacking order of the statusbar intact.
The reason why we won't get away with fixed priorities is that we can't know them beforehand. E.g. the GimpEditSelectionTool would want to push its messages on top of everything that is already there (e.g. the GimpMoveTool message on top of the default message).
The only problem with the current API is that it's impossible to exchange messages without pulling them to the top of the stack. The API is fine otherwise and fits our needs.
This simple approach also has the advantage that it will most probably not break anything because the code is tested and the API won't change except for the s/gtk_statusbar/gimp_statusbar/.
ciao, --mitch
Proposal for fixing the GimpStatusbar API
On Tue, 13 Jan 2004 18:15:38 +0100, Michael Natterer wrote:
Raphaël Quinet writes:
Here are the priority levels that we need, 1 being the highest priority:
1) Messages from interactive operations (short duration) such as the size or offsets displayed by the selection tools, move tool, crop tool, blend tool or measure tool. 2) Messages from plug-ins processing the image. 3) Default messages, which would be the help messages for the current tool. This would replace the custom messages showing the layer name, size, etc.Alternatively, we could use 3) for tool-specific help messages only when the image window has the input focus, and 4) for the user-defined status messages, shown only when the image window is not the active one.
[...]
Actually, I would keep the API, copy the implementation from GtkStatusbar to GimpStatusbar, rip what we don't need and add one single new function: gimp_statusbar_replace(), which would replace the message with the given ID and keep the stacking order of the statusbar intact.
I considered that (because that's what you suggested in bug #120175) but it would require all parts of the code to have the correct context_id and I don't think that it would work better than what I proposed. Why should we use a dynamic stack if we know in advance how many slots it would have? Also, my proposal allows the following scenario to work as the user would expect: - start with the initial default message; - run a plug-in that displays some progress information; - while the plug-in is running, use the measure tool to check something in the image and keep the mouse button down: the info from the measure tool replaces the plug-in info; - the plug-in ends: the cancel button is back to normal, but the info displayed is still from the measure tool; - release the mouse button: the default message is back, there is no conflict with the info from the plug-in. A pure stack model would not work well in this case.
The reason why we won't get away with fixed priorities is that we can't know them beforehand. E.g. the GimpEditSelectionTool would want to push its messages on top of everything that is already there (e.g. the GimpMoveTool message on top of the default message).
The point of my proposal is that I believe that we _do_ known the priorities in advance, so we do not need a dynamic stack to be exposed in the GimpStatusbar. Unless I missed something, all messages that fit in the same category would simply replace each other. In the case that you describe, you would simply replace the level 1 message instead of pushing another one on top of it. The user can only perform one interactive operation at a time (typically, an operation during which the mouse is grabbed, such as when you are dragging something) so it makes sense to simply replace the level 1 message when the current operation changes. And as soon as it is finished, then you get back to the level 2, 3 or 4. Unless you immediately start another operation that changes the level 1 message.
-Raphaël
Proposal for fixing the GimpStatusbar API
A little addition to what I wrote yesterday...
The stack model for the GimpStatusbar is well suited for plug-ins because they have a strict nesting order, but it does not work well when this has to be mixed with changes that can happen asynchronously because this would require messages to be pushed or popped above or below the current element, so this would break the strict stacking order. I wouldn't mind if we could keep some of the existing API because that would minimize the changes to the code (and also because Mitch would probably do the work and I wouldn't have to implement my proposal so that would be less work for me ;-)). But I don't think that the addition of a simple ..._replace() function would be sufficient if we have to break the stacking order.
The API that I propose would look as follows. The details such as the names (_set() or _update()) could change and there would still be a function for updating the coords, although its parameters could be a bit different from the current ones.
typedef enum
{
GIMP_STATUS_INTERACTIVE = 1, /* interactive (modal) operations */
GIMP_STATUS_PROGRESS = 2, /* progress from plug-ins, etc. */
GIMP_STATUS_TOOLHELP = 3, /* description of current tool */
GIMP_STATUS_DEFAULT = 4 /* customizable message */
} GimpStatusbarType;
void gimp_statusbar_set (GimpStatusbar *statusbar, GimpStatusbarType message_type, const gchar *message, guint duration);
void gimp_statusbar_clear (GimpStatusbar *statusbar, GimpStatusbarType message_type);
The duration parameter could be used to specify that a message should be cleared automatically after N milliseconds, unless another message has already replaced it (at that priority level). This would allow the caller to display a message for up to 3 seconds (for example) without having to care about when to clear it. This could be used for the GIMP_STATUS_TOOLHELP messages if we want to display the help for the current tool during a few seconds (renewed each time one switches tools or changes the tool mode, etc.) and still allow the default messages to be shown after a while. Another option would be to clear the GIMP_STATUS_TOOLHELP messages when the window loses the input focus, as I suggested yesterday. Then we would not need to limit the duration of these messages.
This mechanism based on priority levels could be extended easily. For example, let's say that we want to add another type of messages that have a very high priority and are only displayed for a brief moment. This could be used for warning messages such as: "Swapped 666 MB of tile data to disk - memory low". This could be done by adding a new value GIMP_STATUS_SYSTEM = 0 in the enum above. These messages could then be displayed briefly (short duration) while a plug-in or some other memory-consuming task is running. Using fixed priority levels instead of a stack allows these asynchronous messages to be displayed without having to care about the number of push/pop calls in the lower levels while that message is displayed or updated.
If we still want to use a stack model in order to minimize the API changes, then a solution could be to use more than one stack or to use special cases for the interactive messages in order to allow them to be updated regardless of what happens with the stack of messages from plug-ins, etc. That could also solve the problem of asynchronous updates.
Anyway, the API and even the model are not very important, as long as the functionality is there. So I am open to other suggestions. But I would like the API to be available soon so that I can work on fixing the bugs that require the updated GimpStatusbar API.
-Raphaël
Proposal for fixing the GimpStatusbar API
Raphaël Quinet writes:
On Tue, 13 Jan 2004 18:15:38 +0100, Michael Natterer wrote:
Raphaël Quinet writes:
Here are the priority levels that we need, 1 being the highest priority:
1) Messages from interactive operations (short duration) such as the size or offsets displayed by the selection tools, move tool, crop tool, blend tool or measure tool. 2) Messages from plug-ins processing the image. 3) Default messages, which would be the help messages for the current tool. This would replace the custom messages showing the layer name, size, etc.Alternatively, we could use 3) for tool-specific help messages only when the image window has the input focus, and 4) for the user-defined status messages, shown only when the image window is not the active one.
[...]
Actually, I would keep the API, copy the implementation from GtkStatusbar to GimpStatusbar, rip what we don't need and add one single new function: gimp_statusbar_replace(), which would replace the message with the given ID and keep the stacking order of the statusbar intact.
I considered that (because that's what you suggested in bug #120175) but it would require all parts of the code to have the correct context_id and I don't think that it would work better than what I proposed.
Look at the current code. Nobody has to remember the status ID. That's exactly the state I want to keep.
Why should we use a dynamic stack if we know in advance how many slots it would have?
As I explained in my previous mail we do *not* know how man slots we need. Also having a static array instead of a dynamic list sounds more than unelegant. We try to hack widgets in a more general manner to enable gimp-like apps to be built on them in the future.
Also, my proposal allows the
following scenario to work as the user would expect: - start with the initial default message; - run a plug-in that displays some progress information; - while the plug-in is running, use the measure tool to check something in the image and keep the mouse button down: the info from the measure tool replaces the plug-in info; - the plug-in ends: the cancel button is back to normal, but the info displayed is still from the measure tool; - release the mouse button: the default message is back, there is no conflict with the info from the plug-in. A pure stack model would not work well in this case.
As I said, that what the new gimp_statusbar_replace() API would be for. I'm aware of the stacking problem. It's exactly the issue we want to resolve here.
The reason why we won't get away with fixed priorities is that we can't know them beforehand. E.g. the GimpEditSelectionTool would want to push its messages on top of everything that is already there (e.g. the GimpMoveTool message on top of the default message).
The point of my proposal is that I believe that we _do_ known the priorities in advance, so we do not need a dynamic stack to be exposed in the GimpStatusbar.
Limiting ourselves to what we need now is always a bad idea.
Unless I missed something, all
messages that fit in the same category would simply replace each other.
No they won't. My GimpEditSelectionTool example from the previous mail explains why.
In the case that you describe, you would simply replace the level 1 message instead of pushing another one on top of it. The user can only perform one interactive operation at a time (typically, an operation during which the mouse is grabbed, such as when you are dragging something) so it makes sense to simply replace the level 1 message when the current operation changes. And as soon as it is finished, then you get back to the level 2, 3 or 4. Unless you immediately start another operation that changes the level 1 message.
What you propose doesn't even cover the current use cases of the status bar API, let alone stuff we might not even think about now.
ciao,
--mitch
Proposal for fixing the GimpStatusbar API
On Wed, 14 Jan 2004 11:34:04 +0100, Michael Natterer wrote:
Raphaël Quinet writes:
Also, my proposal allows the
following scenario to work as the user would expect: - start with the initial default message; - run a plug-in that displays some progress information; - while the plug-in is running, use the measure tool to check something in the image and keep the mouse button down: the info from the measure tool replaces the plug-in info; - the plug-in ends: the cancel button is back to normal, but the info displayed is still from the measure tool; - release the mouse button: the default message is back, there is no conflict with the info from the plug-in. A pure stack model would not work well in this case.As I said, that what the new gimp_statusbar_replace() API would be for. I'm aware of the stacking problem. It's exactly the issue we want to resolve here.
I don't understand how the gimp_statusbar_replace() API would solve the problem, because one or several other messages from the plug-in would have to be pushed or popped _under_ the message from the measure tool because the interactive actions from the tools should always be visible. I may have misunderstood how you are planning to implement this, but I think that a stack model would cause the messages from the tool to disappear either when a new progress message is pushed by the plug-in (e.g., because it has called another plug-in) or when it wants to pop its message from the stack while the interactive message is still displayed.
The point of my proposal is that I believe that we _do_ known the priorities in advance, so we do not need a dynamic stack to be exposed in the GimpStatusbar.
Limiting ourselves to what we need now is always a bad idea.
As I explained in my last message, the priorities could be extended easily if necessary. So we are not really limited.
Unless I missed something, all
messages that fit in the same category would simply replace each other.No they won't. My GimpEditSelectionTool example from the previous mail explains why.
Then I failed to understand why. As far as I can see, the GimpEditSelectionTool message is simply a priority 1 message (GIMP_STATUS_INTERACTIVE in my proposal) that would replace what is there, and would in turn be replaced when the action ends and the control goes back to another part of the code. How would that conflict with the model that I proposed?
In the case that you describe, you would simply replace the level 1 message instead of pushing another one on top of it. The user can only perform one interactive operation at a time (typically, an operation during which the mouse is grabbed, such as when you are dragging something) so it makes sense to simply replace the level 1 message when the current operation changes. And as soon as it is finished, then you get back to the level 2, 3 or 4. Unless you immediately start another operation that changes the level 1 message.
What you propose doesn't even cover the current use cases of the status bar API, let alone stuff we might not even think about now.
I do not see why it doesn't. I had a look at the different parts of the code using the status bar and I think that my proposal covers them fairly well. But I may be wrong, of course.
As I said in my last message, I do not insist on having this implemented in the way that I proposed. Any solution is welcome as long as it solves the problems that we have now. So if you have a better solution that allows messages to be added, removed or replaced asynchronously, then I would be happy to use it. It would be nice if you could explain how your solution would solve these problems, though.
-Raphaël
Proposal for fixing the GimpStatusbar API
Hi,
Raphaël Quinet writes:
I don't understand how the gimp_statusbar_replace() API would solve the problem, because one or several other messages from the plug-in would have to be pushed or popped _under_ the message from the measure tool because the interactive actions from the tools should always be visible.
I don't think that the tool status always being visible is mandatory. IMO it would be sufficient to be able to replace messages. Tools will set the statusbar every so often anyway. At this point we are not seeking for a perfect solution but for a quick fix for 2.0. The proposal that needs the smallest amount of changes should definitely be favored at this point.
Sven
Proposal for fixing the GimpStatusbar API
On 14 Jan 2004 13:25:44 +0100, Sven Neumann wrote:
Raphaël Quinet writes:
I don't think that the tool status always being visible is mandatory. IMO it would be sufficient to be able to replace messages. Tools will set the statusbar every so often anyway.
That's right. It would still be a problem if the interactive message from the tool has to compete with a plug-in updating the message showing its progress, but this is not a very serious issue for the moment.
At this point we are not
seeking for a perfect solution but for a quick fix for 2.0. The proposal that needs the smallest amount of changes should definitely be favored at this point.
OK, I agree. Let's use a quick fix for 2.0 and then see how the API can be improved later (e.g., for 2.2). So I will try to work on bug #124040, assuming that bug #120175 could be fixed soon.
-Raphaël