A -quick done- first step towards the addition of a smart selection tool.
Require the gegl:paint-select workshop operation.
Still LOT of work to do (wip):
- fluctuations removal (GEGL side)
- multilevels pyramid approach + banded graphcut for instant result on large
image (GEGL ? GIMP ?)
- Gaussian Mixtures for color models (GEGL side)
- drawable offsets (GIMP side)
- undo / redo (GIMP side)
- scribbles edition mode (GIMP side)
- dedicated icons
- ...
- New GimpLabelIntWidget which is a label associated to any widget with
an integer "value" property.
- New gimp_procedure_dialog_get_int_combo() which creates a labeled
combo box from an integer property of the GimpProcedureConfig.
- Renamed gimp_procedure_dialog_populate*() with
gimp_procedure_dialog_fill*(). Naming is hard! I hesitated using
_pack() as well (similarly to GtkBox API).
- New gimp_procedure_dialog_fill_flowbox*() functions to create a
GtkFlowBox filled with property widgets (or other container widgets as
we can pack them one in another). This is an alternative way to build
your GUI with sane defaults, with list of property names.
So the minor fix on commit 3e35fe4d80 was not so minor after all, and I
should have looked more in details into its contents.
GET_PRIVATE() macro uses the `priv` pointer value hence had to be called
after gimp_chain_button_get_instance_private(). Thus the order was
important; the initialization and assignment values were actually
different. Simply let's get rid of the previous initialization of
`private` (make it declaration-only) to avoid cppcheck to (wrongfully)
complain about double variable assignment to the same value.
There is currently no property widget which just creates a
GimpSpinButton with a label. Just as the GimpScaleEntry was needed, this
one is as well.
I am creating a GimpLabeled abstract class which will represent various
widgets with a label. While this may seem a bit over-engineered for such
a basic feature, this will actually bring some consistency and a common
parent. In particular this can be used to get the GtkLabel with a common
interface to add them all in a common GtkSizeGroup when generating
dialogs automatically, hence make dialogs with properly aligned labels
and edition widgets.
… gimp_scale_entry_set_bounds().
I realized that this function may look like the set() opposite for
gimp_scale_entry_get_range(), which it is not at all. The get_range() is
for getting back the GtkRange widget packed in the GimpScaleEntry,
whereas the set_range() is to change the minimum and maximum allowed
values.
I had recently renamed the former, and could just rename it back into
gimp_scale_entry_get_scale() as it was, but since the class we rely on
is actually called GtkRange (GtkScale is a subclass), I think it could
be misleading. So in the end, let's rather rename the function setting
the widget minimum and maximum as gimp_scale_entry_set_bounds() instead.
Hopefully this is even more understandable. Naming is hard!
Renaming the temporary function gimp_scale_entry_new2() into
gimp_scale_entry_new() now that the original code is entirely gone. This
is now a fully-fledged widget with a nice and proper introspectable API.
Former gimp_color_scale_entry_new() is finally replaced by the
GimpColorScaleEntry implementation.
Both places which used it (GimpColorScales and compose plug-in) now use
the new widget.
Also making "upper" and "lower" properties of GimpScaleEntry into
construction properties, and create the main GtkAjustment at init, so
that we are sure that lower and upper bounds are properly set before we
set the value (when setting all properties at once, we cannot ensure
that these limit properties are set before the "value" one).
I updated GimpScaleEntry and GimpColorScaleEntry header to use
respectively the macros G_DECLARE_DERIVABLE_TYPE and
G_DECLARE_FINAL_TYPE.
Though having the `priv` structure directly in the object data is
extremely comfortable for developing (hence we don't want to use this
macro on core code as it makes coding a bit more bothersome), it is true
that it does not make for a very pretty public interface (showing a
`priv` member which nobody can actually use, and a private type which
has no associated functions). So it might be a good idea to use these
macros at least on libgimp side.
I am still not sure though if it is a good idea so we could say it's an
experiment. At least the docs says that using G_DECLARE_FINAL_TYPE does
not affect ABI stability as it can later be changed into a
G_DECLARE_DERIVABLE_TYPE because the class structure stays private. So
at least that's one good point.
P.S.: also reordering gimpwidgets.def.
Similarly to GimpScaleEntry, this is meant to replace usage of
gimp_color_scale_entry_new() by having a proper widget. This is a child
class of GimpScaleEntry which simply replaces the GtkScale by a
GimpColorScale by adding a GimpScaleEntry class method to create the
scale widget (only restriction: it must be a GtkRange subtype).
This also triggers me to rename gimp_scale_entry_get_scale() into
gimp_scale_entry_get_range() (as well as the 2 plug-ins already using
this function).
I got rid of gimp_scale_entry_set_sensitive(), as we can now use the
generic gtk_widget_set_sensitive(), and I ported the 2 plug-ins using
this function.
I also created gimp_scale_entry_set_value() to set the value (nicer than
setting object properties).
For very small ranges, just dividing by 10 and 100 is not very good. You
could end up with weird step values. It is often better to use 10^(-x)
values just below your range.
I.e for a 0.5 range, a step of 0.1 and page of 0.01 are probably fine
(better than 0.05 and 0.005).
Of course as usual these are default values only and setting custom
increments is possible through available API.
Also fixing a small bug in gimp_scale_entry_set_increments() added in
commit 0f05825a29.
Instead of setting always manually the step and page increments when
creating a GimpScaleEntry, let's just generate some common cases
automatically. Indeed the increments are rarely something you want to
care about. The algorithm used is:
- For a range under 1.0, use a hundredth and a tenth (typically a [0,
1.0] range will step-increment of 0.01 and page-increment of 0.1).
- For small ranges (under 40), step-increment by 1, page-increment by 2.
- For bigger ranges, step-increment by 1, page-increment by 10.
For use cases when you absolutely want specific increment values, I add
the gimp_scale_entry_set_increments() function. It is much better to
have a small and understandable constructor call followed by
configuration calls (only when needed) rather than a constructor with a
crazy amount of parameters. Hence gimp_scale_entry_new() went from 17
arguments (absolutely unreadable calls) to now 5.
* Add a gimp_scale_entry_get_value() because if we don't do a property
widget, getting the value of the widget easily is a main point.
* Move gimp_scale_entry_(set|get)_logarithmic() to the new class API.
* Internally edit the GtkSpinButton width depending on min/max values,
place digits, and possible value sign.
* Emit a "value-changed" signal (similarly to other widgets with a
value), for cases when just binding the "value" property is not
enough.
* Finally use the new API in palette-import-dialog.
Instead of the gimp_scale_entry_new() which creates several bound yet
independant widgets, and in the same time pack them into an existing
grid and return a GtkAdjustment (while heavily relying on GObject data
to link widgets), let's have a proper custom widget with its own clean
API.
This also simplifies the gimp_prop_scale_entry_new() property widget
variant.
First advantage is that we don't force the usage of a grid to use this
widget (there are a few pieces of code which create a GtkGrid with only
this inside just to be able to use this feature).
Second thing is that I am creating a much simpler API.
gimp_scale_entry_new() had 17 parameters! How crazy is that? So I
removed all the grid packing related parameters. Also I moved the spin
button/scale unconstraining parameters into their separate function,
because the constrained behavior is the most common use case, so it's
stupid to add 3 permanent dummy parameters for most calls. Instead the
few times where we'll want different ranges for the spin button and the
scale, we'll call the separate API gimp_scale_entry_set_range().
Thirdly the tooltip can be set directly with gimp_help_set_help_data()
since this is now its own widget. No need to have dedicated logics
anymore, better stay generic. Similarly no need of a custom function to
switch sensitivitivy (instead of generic gtk_widget_set_sensitive()).
Fourth thing is that we should not use macros for the public API, but
proper functions, because macros are not properly introspected for
binding.
For future improvements, maybe we could even make this widget implement
GtkOrientable interface, in order to be able to use it vertically.
Note: right now, I created a separate gimp_scale_entry_new2() and only
modified the property widget API to use this new code. Eventually I will
remove fully the old gimp_scale_entry_new() function (and the new code
will replace it).
There was a /* FIXME MOVE TO PRIVATE */ and anyway it makes sense to not
leave such data in the public API.
I note that the whole widget declaration is between #ifndef
GIMP_DISABLE_DEPRECATED macros so maybe we should just delete it
altogether for GIMP 3, but it might still have a usage. Maybe it could
also be interesting to experiment with the file portal on such widget
for plug-in usage? Let's see.
… GimpIntComboBox "value" property.
For this, I connect to the "changed" signal, which is equivalent anyway.
Otherwise the link was not bidirectionnal, so selecting a new item in
the combo list was not actually changing the internal value, hence the
binding set by gimp_prop_int_combo_box_new() was not complete either.
Not sure how I missed that. Hopefully not missing anything else!
… and have gimp_prop_int_combo_box_new() bind to "value" instead of
"active".
The "active" property is defined by GtkComboBox and is the index of the
combo box, not its values, whereas with gimp_prop_int_combo_box_new(),
we want to bind an int property to the combobox value. Therefore the
commit 0828a371c2 was only properly working when we were creating a
combo box with values starting at 0 and incremented by 1.
By adding a "value" property to GimpIntComboBox, I allow binding any
property to the int value rather than the index.
See also !265 where the issue was raised as it affected our HEIF
plug-in.
Looking further at this widget, many things are not right. Here are the
changes:
- Use binary prefixes (i.e. kibibyte, mebibyte and gibibyte) instead of
decimal ones. We are making binary shifts so we were actually showing
the wrong units.
- Round the value to the closest integer when showing it, not towards 0.
Otherwise I had cases where it was showing 7GiB for an actual value of
7.69GiB (default as computed by GIMP from my actual physical memory).
Note that I am actually unsure even rounding makes sense. Shouldn't we
rather show double values with a few digits after the decimal points?
For such values, I think it would make sense.
- Do not edit the internally saved accurate value when the entry is
edited to the same less accurate value as our saved value would be
shown too. In particular when changing the display unit to a bigger
one, we don't want to lose accuracy. This is especially true for low
values. Say you don't have a lot of memory and you set the Tile cache
size to 1.5GiB (1536MiB), you certainly don't want it to become either
1 or 2GiB when switching display unit to GiB. Now even if the number
will still display with less accuracy, the internal value will stay
accurate.
This bug doesn't happen when setting value through the GUI as in such
case, the unit never changed. It happened when setting a value which
could not be properly displayed by current unit (typically smaller than
1 in this unit, or with remainder).
In such a case, we should not manually set private->shift before
gimp_int_combo_box_set_active(), or the callback was failing to
reconfigure the GtkAdjustement, in particular min and max values.
As a consequence, hitting a Preferences reset, with a GimpMemSizeEntry
in Gigabytes, it got reset to Kilobytes with the max values capped at
4096. So I realized a Reset ended me with a Tile cache size of 4096 KB
in particular, which is of course ridiculously small and would be a
problem if one doesn't notice the issue immediately.
In GimpSpinButton, don't propagate Enter key-press events if
updating the spin-button's value in response changes the entered
text. This prevents confirming dialogs when hitting Enter after
entering a math expression in size entries, updating their value
instead.
Likewise, don't propagate Escape key-press events if a new value
was entered, and restore the original value instead.
`gimp_unit_store_get_value()` clashes with the `get_value()` method of
its parent class GtkTreeStore. This means trouble for bindings, as seen
here in some pseudocode:
```vala
var unit_store = new Gimp.UnitStore();
// Which function are we referencing here, the one from GtkTreeStore or
// the one from GimpUnitStore? Worse, they both have different arguments
unit_store.get_value( ... )
```
GtkHBox is a deprecated version of GtkBox, which we don't even use
anymore. It confuses the gtk-doc a build though, so let's fix it to get
rid of another warning.