gimp/app/dialogs/resize-dialog.c

853 lines
29 KiB
C
Raw Normal View History

/* GIMP - The GNU Image Manipulation Program
1997-11-25 06:05:25 +08:00
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software: you can redistribute it and/or modify
1997-11-25 06:05:25 +08:00
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
1997-11-25 06:05:25 +08:00
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1997-11-25 06:05:25 +08:00
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
Makefile.am configure.in added new directory libgimpbase/ 2001-05-21 Michael Natterer <mitch@gimp.org> * Makefile.am * configure.in * gimptool-1.4.in: added new directory libgimpbase/ * app/Makefile.am: link against the new lib. * app/appenums.h: removed the PDB enums which are in libgimpbase/gimpbasetypes.h now. They are all "Gimp" prefixed. * app/apptypes.h: #include "libgimpbase/gimpbasetypes.h" * app/[lots] * app/core/[of] * app/gui/[files] * app/tools/: changed includes and all PDB types. * app/pdb/*: regenerated. * libgimp/Makefile.am: don't build libgimpi.a uglyness any more. * libgimp/gimpenv.[ch] * libgimp/gimplimits.[hh] * libgimp/gimpparasite.[ch] * libgimp/gimpparasiteio.[ch] * libgimp/gimpprotocol.[ch] * libgimp/gimpsignal.[ch] * libgimp/gimpunit.h * libgimp/gimputils.[ch] * libgimp/gimpwire.[ch]: removed... * libgimpbase/*: ...and added here as new library. * libgimp/gimp.[ch] * libgimp/gimpdrawable.[ch] * libgimp/gimpenums.h * libgimp/gimpimage.[ch] * libgimp/gimptile.c * libgimp/gimptypes.h * libgimp/gimpunit.c: changed accordingly. Added the gimp_*_add_new_parasite to gimp.[ch], gimpdrawable.[ch] and gimpimage.[ch]. * libgimpwidgets/gimppatheditor.c * libgimpwidgets/gimpquerybox.c * libgimpwidgets/gimpsizeentry.c * libgimpwidgets/gimpunitmenu.c * libgimpwidgets/gimpwidgets.c * libgimpwidgets/gimpwidgetstypes.h: changed includes accordingly. * plug-ins/*/Makefile.am * plug-ins/common/mkgen.pl: link against libgimpbase. * tools/pdbgen/Makefile.am: scan libgimpbase/gimpbasetypes.h, so the enums are known to pdbgen... * tools/pdbgen/enumcode.pl: ...but don't write them out to libgimp/gimpenums.h * tools/pdbgen/app.pl: include libgimp/gimpbase.h in all *_cmds.c files. Added GIMP_ to the type names ganerated in app/. * tools/pdbgen/enums.pl: regenerated. * tools/pdbgen/pdb.pl * tools/pdbgen/pdb/fileops.pdb * tools/pdbgen/pdb/procedural_db.pdb * tools/pdbgen/pdb/unit.pdb: changed includes.
2001-05-21 21:58:46 +08:00
#include "libgimpbase/gimpbase.h"
#include "libgimpmath/gimpmath.h"
Makefile.am configure.in added the new library below. 2001-01-24 Michael Natterer <mitch@gimp.org> * Makefile.am * configure.in * gimptool.in: added the new library below. * libgimpwidgets/Makefile.am * libgimpwidgets/gimpchainbutton.[ch] * libgimpwidgets/gimpcolorarea.[ch] * libgimpwidgets/gimpcolorbutton.[ch] * libgimpwidgets/gimpdialog.[ch] * libgimpwidgets/gimpfileselection.[ch] * libgimpwidgets/gimphelpui.[ch] * libgimpwidgets/gimppatheditor.[ch] * libgimpwidgets/gimppixmap.[ch] * libgimpwidgets/gimpquerybox.[ch] * libgimpwidgets/gimpsizeentry.[ch] * libgimpwidgets/gimpunitmenu.[ch] * libgimpwidgets/gimpwidgets.[ch] * libgimpwidgets/gimpwidgets.def * libgimpwidgets/gimpwidgetstypes.h: new shared library. Currently there are some ugly dependencies into libgimp. These will be removed and go to a "libgimpglue" library which will be a library for functions which share a common interface between plug-ins and the app but have different implementations. Include "libgimp/gimpunit.h" from "libgimpwidgets/gimpwidgetstypes.h" to simulate this upcoming separation. * libgimp/Makefile.am * libgimp/gimpchainbutton.[ch] * libgimp/gimpcolorarea.[ch] * libgimp/gimpcolorbutton.[ch] * libgimp/gimpdialog.[ch] * libgimp/gimpfileselection.[ch] * libgimp/gimphelpui.[ch] * libgimp/gimppatheditor.[ch] * libgimp/gimppixmap.[ch] * libgimp/gimpquerybox.[ch] * libgimp/gimpsizeentry.[ch] * libgimp/gimpunitmenu.[ch] * libgimp/gimpwidgets.[ch]: removed from here. * libgimp/gimpui.h * libgimp/gimpuitypes.h * libgimp/makefile.mingw.in * libgimp/makefile.msc: changed accordingly. * app/[all ui files] * app/pdb/palette_cmds.c * app/pdb/tools_cmds.c * tools/pdbgen/pdb/palette.pdb * tools/pdbgen/pdb/tools.pdb: #include "libgimpwidgets/gimpwidgets.h" and removed useless includes. * app/apptypes.h: #include "libgimpwidgets/gimpwidgetstypes.h" * app/Makefile.am * plug-ins/[all makefiles which link against libgimpui]: link against libgimpwidgets.la * po-libgimp/POTFILES.in: changed file locations.
2001-01-25 06:36:18 +08:00
#include "libgimpwidgets/gimpwidgets.h"
configure.in added new directory app/dialogs and link libappdialogs.c into 2004-09-13 Michael Natterer <mitch@gimp.org> * configure.in * app/Makefile.am: added new directory app/dialogs and link libappdialogs.c into the gimp binary. * app/gui/Makefile.am * app/gui/gui-types.h * app/gui/gui-vtable.c * app/gui/gui.c * app/gui/about-dialog.[ch] * app/gui/authors.h * app/gui/color-notebook.[ch] * app/gui/convert-dialog.[ch] * app/gui/dialogs-constructors.[ch] * app/gui/dialogs.[ch] * app/gui/file-dialog-utils.[ch] * app/gui/file-new-dialog.[ch] * app/gui/file-open-dialog.[ch] * app/gui/file-open-location-dialog.[ch] * app/gui/file-save-dialog.[ch] * app/gui/grid-dialog.[ch] * app/gui/info-dialog.[ch] * app/gui/info-window.[ch] * app/gui/module-browser.[ch] * app/gui/offset-dialog.[ch] * app/gui/palette-import-dialog.[ch] * app/gui/preferences-dialog.[ch] * app/gui/quit-dialog.[ch] * app/gui/resize-dialog.[ch] * app/gui/resolution-calibrate-dialog.[ch] * app/gui/stroke-dialog.[ch] * app/gui/tips-dialog.[ch] * app/gui/tips-parser.[ch] * app/gui/user-install-dialog.[ch]: removed these files... * app/dialogs/Makefile.am * app/dialogs/dialogs-types.h * app/dialogs/*.[ch]: ...and added them here. Changed some filenames like module-browser -> module-dialog. * app/app_procs.c * app/actions/actions-types.h * app/actions/actions.c * app/actions/dialogs-actions.c * app/actions/dialogs-commands.c * app/actions/dockable-commands.c * app/actions/drawable-commands.c * app/actions/edit-commands.c * app/actions/file-commands.c * app/actions/gradient-editor-commands.c * app/actions/image-commands.c * app/actions/layers-commands.c * app/actions/palettes-commands.c * app/actions/select-commands.c * app/actions/templates-commands.c * app/actions/templates-commands.h * app/actions/vectors-commands.c * app/actions/view-commands.c * app/display/gimpdisplayshell-cursor.c * app/display/gimpdisplayshell-title.c * app/display/gimpdisplayshell.[ch] * app/tools/gimpcroptool.c * app/tools/gimpperspectivetool.c * app/tools/gimprotatetool.c * app/tools/gimpscaletool.c * app/tools/gimpsheartool.c * app/tools/gimptransformtool.[ch] * app/tools/gimpvectortool.c * app/widgets/gimpcolormapeditor.[ch] * app/widgets/gimpcolorpanel.c * app/widgets/gimpgradienteditor.[ch] * app/widgets/gimppaletteeditor.[ch] * app/widgets/gimptoolbox-color-area.c * menus/toolbox-menu.xml.in * tools/authorsgen/authorsgen.pl: changed accordingly.
2004-09-13 23:15:23 +08:00
#include "dialogs-types.h"
#include "core/gimp.h"
added GimpContext parameters and create the GimpView with that context. 2006-09-01 Michael Natterer <mitch@gimp.org> * app/widgets/gimpviewabledialog.[ch]: added GimpContext parameters and create the GimpView with that context. * app/widgets/gimpcolordialog.[ch] * app/dialogs/convert-dialog.[ch] * app/dialogs/desaturate-dialog.[ch] * app/dialogs/grid-dialog.[ch] * app/dialogs/image-properties-dialog.[ch] * app/dialogs/layer-add-mask-dialog.[ch] * app/dialogs/offset-dialog.[ch] * app/dialogs/print-size-dialog.[ch] * app/dialogs/resize-dialog.[ch] * app/dialogs/scale-dialog.[ch] * app/dialogs/stroke-dialog.[ch] * app/dialogs/template-options-dialog.[ch] * app/dialogs/vectors-options-dialog.[ch]: added GimpContext parameters here too and pass them to gimp_viewable_dialog_new(). * app/actions/colormap-editor-commands.c * app/actions/drawable-commands.c * app/actions/gradient-editor-commands.c * app/actions/image-commands.c * app/actions/layers-commands.c * app/actions/palette-editor-commands.c * app/actions/select-commands.c * app/actions/vectors-commands.c * app/actions/view-commands.c * app/dialogs/channel-options-dialog.c * app/dialogs/dialogs-constructors.c * app/dialogs/image-merge-layers-dialog.c * app/dialogs/image-scale-dialog.c * app/dialogs/layer-options-dialog.c * app/display/gimpdisplayshell-filter-dialog.c * app/display/gimpdisplayshell-scale.c * app/tools/gimpcolorpickertool.c * app/tools/gimpimagemaptool.c * app/tools/gimpmeasuretool.c * app/tools/gimptexttool.c * app/tools/gimptransformtool.c * app/tools/gimpvectortool.c * app/widgets/gimpcolorpanel.c * app/widgets/gimpcontrollereditor.c * app/widgets/gimpcontrollerlist.c * app/widgets/gimptoolbox-color-area.c: pass contexts to above dialog constructors.
2006-09-01 19:26:54 +08:00
#include "core/gimpcontext.h"
#include "core/gimpimage.h"
#include "core/gimplayer.h"
#include "core/gimptemplate.h"
#include "widgets/gimpcontainercombobox.h"
app/widgets/Makefile.am new file defining the available help topics. Work 2003-08-21 Michael Natterer <mitch@gimp.org> * app/widgets/Makefile.am * app/widgets/gimphelp-ids.h: new file defining the available help topics. Work in progress and totally unusable for matching to the help system. Stay tuned... * app/gui/about-dialog.c * app/gui/brushes-menu.c * app/gui/buffers-menu.c * app/gui/channels-commands.[ch] * app/gui/channels-menu.c * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/gradients-commands.c * app/gui/gradients-menu.c * app/gui/image-menu.c * app/gui/layers-commands.[ch] * app/gui/layers-menu.c * app/gui/module-browser.c * app/gui/offset-dialog.c * app/gui/palettes-menu.c * app/gui/patterns-menu.c * app/gui/resize-dialog.c * app/gui/select-commands.c * app/gui/templates-menu.c * app/gui/tips-dialog.c * app/gui/toolbox-menu.c * app/gui/vectors-commands.[ch] * app/gui/vectors-menu.c: replaced literal HTML file paths by help IDs from gimphelp-ids.h. Renamed some menu callbacks to be consistent with similar ones. This is just an intermediate commit and not finished. While browsing all the menus, I noticed that our "x to selection" functions are not consistent at all. They should all offer the REPLACE,ADD,SUBTRACT,INTERSECT options: * app/core/gimpchannel.[ch]: added new function gimp_channel_new_from_alpha(). Removed gimp_channel_layer_alpha() and gimp_channel_layer_mask(). * app/core/gimpimage-mask.[ch]: added gimp_image_mask_select_alpha() and gimp_image_mask_select_component() which offer the full set of operation, feather and feather_radius parameters as the other selection functions. * app/core/gimpimage-mask-select.[ch]: removed gimp_image_mask_layer_alpha() and gimp_image_mask_layer_mask(). * app/gui/channels-commands.c (channels_channel_to_selection): use gimp_image_mask_select_component() instead of implementing it here. * app/gui/image-menu.c * app/gui/layers-commands.[ch]: offer the full choice of REPLACE,ADD,SUBTRACT,INTERSECT with "Alpha to Selection" and "Mask to Selection". * tools/pdbgen/pdb/selection.pdb: changed accordingly. * app/pdb/selection_cmds.c: regenerated.
2003-08-21 23:54:47 +08:00
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpsizebox.h"
#include "widgets/gimpviewabledialog.h"
#include "widgets/gimpwidgets-constructors.h"
#include "resize-dialog.h"
#include "gimp-intl.h"
app/Makefile.am app/channel_pvt.h app/drawable_pvt.h app/gdisplayF.h 2000-12-29 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/channel_pvt.h * app/drawable_pvt.h * app/gdisplayF.h * app/gimpdrawableP.h * app/gimpimageP.h * app/layer_pvt.h * app/toolsF.h: removed these files. * app/apptypes.h * tools/pdbgen/enums.pl: added tons of opaque typedefs and enums. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/channel.pdb * tools/pdbgen/pdb/color.pdb * tools/pdbgen/pdb/convert.pdb * tools/pdbgen/pdb/display.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/fileops.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/help.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/tools.pdb * app/*: chainsaw #include cleanup: - Never (never!!) include stuff in header files except where we need access to structures' contents (like derived objects). - Added prototypes and proper formating in many files. - The #include order in *all* *.c files is as follows: #include "config.h" #include <system stuff> #include <gtk/gtk.h> #include "apptypes.h" #include "gimp stuff" #include "libgimp stuff" #include "libgimp/gimpintl.h" By following this scheme we can easily see a file's dependencies from it's #include's and can grep for the inclusion to find out where a file is used. * tools/pdbgen/app.pl: changed to follow the include scheme above. * libgimp/Makefile.am * libgimp/gimpuitypes.h: new file, included from libgimp/gimpui.h and from app/apptypes.h. * libgimp/gimpcolorbutton.[ch] * libgimp/gimpdialog.[ch] * libgimp/gimphelpui.[ch] * libgimp/gimpparasite.[ch] * libgimp/gimppatheditor.[ch] * libgimp/gimpprotocol.c * libgimp/gimpquerybox.[ch] * libgimp/gimpsizeentry.[ch] * libgimp/gimptypes.h * libgimp/gimpui.h * libgimp/gimpunit.h * libgimp/gimpunitmenu.[ch] * libgimp/gimpwidgets.[ch]: changed accordingly. * plug-ins/FractalExplorer/Dialogs.c * plug-ins/gdyntext/message_window.c * plug-ins/imagemap/imap_default_dialog.c * plug-ins/imagemap/imap_file.c: these files used to include "libgimp/gimpui.h" without including "libgimp/gimp.h". This is no longer possible because the libgimpui headers don't inlcude "libgimp/gimpunit.h" any more.
2000-12-29 23:22:01 +08:00
#define RESPONSE_RESET 1
2004-10-29 02:27:04 +08:00
#define SB_WIDTH 8
typedef struct _ResizeDialog ResizeDialog;
struct _ResizeDialog
{
GimpViewable *viewable;
GimpContext *context;
GimpContext *parent_context;
GimpFillType fill_type;
GimpItemSet layer_set;
gboolean resize_text_layers;
GimpResizeCallback callback;
gpointer user_data;
gdouble old_xres;
gdouble old_yres;
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
GimpUnit *old_res_unit;
gint old_width;
gint old_height;
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
GimpUnit *old_unit;
GimpFillType old_fill_type;
GimpItemSet old_layer_set;
gboolean old_resize_text_layers;
GtkWidget *box;
GtkWidget *offset;
GtkWidget *area;
GtkWidget *layer_set_combo;
GtkWidget *fill_type_combo;
GtkWidget *text_layers_button;
GtkWidget *ppi_box;
GtkWidget *ppi_image;
GtkWidget *ppi_template;
GimpTemplate *template;
};
/* local function prototypes */
static void resize_dialog_free (ResizeDialog *private);
static void resize_dialog_response (GtkWidget *dialog,
gint response_id,
ResizeDialog *private);
static void resize_dialog_reset (ResizeDialog *private);
static void size_notify (GimpSizeBox *box,
GParamSpec *pspec,
ResizeDialog *private);
2004-10-29 02:27:04 +08:00
static void offset_update (GtkWidget *widget,
ResizeDialog *private);
2004-10-29 02:27:04 +08:00
static void offsets_changed (GtkWidget *area,
gint off_x,
gint off_y,
ResizeDialog *private);
2004-10-29 02:27:04 +08:00
static void offset_center_clicked (GtkWidget *widget,
ResizeDialog *private);
2004-10-29 02:27:04 +08:00
static void template_changed (GimpContext *context,
GimpTemplate *template,
ResizeDialog *private);
static void reset_template_clicked (GtkWidget *button,
ResizeDialog *private);
static void ppi_select_toggled (GtkWidget *radio,
ResizeDialog *private);
/* public function */
GtkWidget *
resize_dialog_new (GimpViewable *viewable,
added GimpContext parameters and create the GimpView with that context. 2006-09-01 Michael Natterer <mitch@gimp.org> * app/widgets/gimpviewabledialog.[ch]: added GimpContext parameters and create the GimpView with that context. * app/widgets/gimpcolordialog.[ch] * app/dialogs/convert-dialog.[ch] * app/dialogs/desaturate-dialog.[ch] * app/dialogs/grid-dialog.[ch] * app/dialogs/image-properties-dialog.[ch] * app/dialogs/layer-add-mask-dialog.[ch] * app/dialogs/offset-dialog.[ch] * app/dialogs/print-size-dialog.[ch] * app/dialogs/resize-dialog.[ch] * app/dialogs/scale-dialog.[ch] * app/dialogs/stroke-dialog.[ch] * app/dialogs/template-options-dialog.[ch] * app/dialogs/vectors-options-dialog.[ch]: added GimpContext parameters here too and pass them to gimp_viewable_dialog_new(). * app/actions/colormap-editor-commands.c * app/actions/drawable-commands.c * app/actions/gradient-editor-commands.c * app/actions/image-commands.c * app/actions/layers-commands.c * app/actions/palette-editor-commands.c * app/actions/select-commands.c * app/actions/vectors-commands.c * app/actions/view-commands.c * app/dialogs/channel-options-dialog.c * app/dialogs/dialogs-constructors.c * app/dialogs/image-merge-layers-dialog.c * app/dialogs/image-scale-dialog.c * app/dialogs/layer-options-dialog.c * app/display/gimpdisplayshell-filter-dialog.c * app/display/gimpdisplayshell-scale.c * app/tools/gimpcolorpickertool.c * app/tools/gimpimagemaptool.c * app/tools/gimpmeasuretool.c * app/tools/gimptexttool.c * app/tools/gimptransformtool.c * app/tools/gimpvectortool.c * app/widgets/gimpcolorpanel.c * app/widgets/gimpcontrollereditor.c * app/widgets/gimpcontrollerlist.c * app/widgets/gimptoolbox-color-area.c: pass contexts to above dialog constructors.
2006-09-01 19:26:54 +08:00
GimpContext *context,
const gchar *title,
const gchar *role,
GtkWidget *parent,
GimpHelpFunc help_func,
const gchar *help_id,
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
GimpUnit *unit,
GimpFillType fill_type,
GimpItemSet layer_set,
gboolean resize_text_layers,
GimpResizeCallback callback,
gpointer user_data)
{
ResizeDialog *private;
GtkWidget *dialog;
GtkWidget *main_vbox;
GtkWidget *vbox;
GtkWidget *center_hbox;
GtkWidget *center_left_vbox;
GtkWidget *center_right_vbox;
GtkWidget *frame;
GtkWidget *button;
GtkWidget *spinbutton;
GtkWidget *entry;
GtkWidget *hbox;
GtkWidget *combo;
GtkWidget *label;
GtkWidget *template_selector;
GtkWidget *ppi_image;
GtkWidget *ppi_template;
GtkAdjustment *adjustment;
GdkPixbuf *pixbuf;
GtkSizeGroup *size_group = NULL;
GimpImage *image = NULL;
const gchar *size_title = NULL;
const gchar *layers_title = NULL;
gint width, height;
gdouble xres, yres;
g_return_val_if_fail (GIMP_IS_VIEWABLE (viewable), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
g_return_val_if_fail (callback != NULL, NULL);
if (GIMP_IS_IMAGE (viewable))
{
image = GIMP_IMAGE (viewable);
width = gimp_image_get_width (image);
height = gimp_image_get_height (image);
size_title = _("Canvas Size");
layers_title = _("Layers");
}
else if (GIMP_IS_ITEM (viewable))
{
GimpItem *item = GIMP_ITEM (viewable);
image = gimp_item_get_image (item);
width = gimp_item_get_width (item);
height = gimp_item_get_height (item);
size_title = _("Layer Size");
layers_title = _("Fill With");
}
else
{
g_return_val_if_reached (NULL);
}
private = g_slice_new0 (ResizeDialog);
private->parent_context = context;
private->context = gimp_context_new (context->gimp,
"resize-dialog",
context);
gimp_image_get_resolution (image, &xres, &yres);
private->old_xres = xres;
private->old_yres = yres;
private->old_res_unit = gimp_image_get_unit (image);
private->viewable = viewable;
private->fill_type = fill_type;
private->layer_set = layer_set;
private->resize_text_layers = resize_text_layers;
private->callback = callback;
private->user_data = user_data;
private->old_width = width;
private->old_height = height;
private->old_unit = unit;
private->old_fill_type = private->fill_type;
private->old_layer_set = private->layer_set;
private->old_resize_text_layers = private->resize_text_layers;
gimp_context_set_template (private->context, NULL);
dialog = gimp_viewable_dialog_new (g_list_prepend (NULL, viewable), context,
title, role, GIMP_ICON_OBJECT_RESIZE, title,
parent,
help_func, help_id,
_("Re_set"), RESPONSE_RESET,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Resize"), GTK_RESPONSE_OK,
NULL);
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
RESPONSE_RESET,
GTK_RESPONSE_OK,
GTK_RESPONSE_CANCEL,
-1);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
g_object_weak_ref (G_OBJECT (dialog),
(GWeakNotify) resize_dialog_free, private);
g_signal_connect (dialog, "response",
G_CALLBACK (resize_dialog_response),
private);
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
main_vbox, TRUE, TRUE, 0);
gtk_widget_show (main_vbox);
/* template selector */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
label = gtk_label_new_with_mnemonic (_("_Template:"));
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
template_selector = g_object_new (GIMP_TYPE_CONTAINER_COMBO_BOX,
"container", context->gimp->templates,
"context", private->context,
"view-size", 16,
"view-border-width", 0,
"ellipsize", PANGO_ELLIPSIZE_NONE,
"focus-on-click", FALSE,
NULL);
gtk_box_pack_start (GTK_BOX (hbox), template_selector, TRUE, TRUE, 0);
gtk_widget_show (template_selector);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), template_selector);
g_signal_connect (private->context,
"template-changed",
G_CALLBACK (template_changed),
private);
/* reset template button */
button = gimp_icon_button_new (GIMP_ICON_RESET, NULL);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_image_set_from_icon_name (GTK_IMAGE (gtk_bin_get_child (GTK_BIN (button))),
GIMP_ICON_RESET, GTK_ICON_SIZE_MENU);
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
g_signal_connect (button,
"clicked",
G_CALLBACK (reset_template_clicked),
private);
gimp_help_set_help_data (button,
_("Reset the template selection"),
NULL);
/* ppi selector box */
private->ppi_box = vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
label = gtk_label_new (_("Template and image print resolution don't match.\n"
"Choose how to scale the canvas:"));
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
gtk_widget_show (hbox);
/* actual label text is set inside template_change fn. */
ppi_image = gtk_radio_button_new_with_label (NULL, "");
ppi_template = gtk_radio_button_new_with_label (NULL, "");
private->ppi_image = ppi_image;
private->ppi_template = ppi_template;
gtk_radio_button_join_group (GTK_RADIO_BUTTON (ppi_template),
GTK_RADIO_BUTTON (ppi_image));
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (ppi_image), FALSE);
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (ppi_template), FALSE);
gtk_box_pack_start (GTK_BOX (hbox), ppi_image, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), ppi_template, FALSE, FALSE, 0);
gtk_widget_show (ppi_image);
gtk_widget_show (ppi_template);
g_signal_connect (G_OBJECT (ppi_image),
"toggled",
G_CALLBACK (ppi_select_toggled),
private);
g_signal_connect (G_OBJECT (ppi_template),
"toggled",
G_CALLBACK (ppi_select_toggled),
private);
/* For space gain, organize the main widgets in both vertical and
* horizontal layout.
* The size and offset fields are on the center left, while the
* preview and the "Center" button are on center right.
*/
center_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
gtk_box_pack_start (GTK_BOX (main_vbox), center_hbox, FALSE, FALSE, 0);
gtk_widget_show (center_hbox);
center_left_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
gtk_box_pack_start (GTK_BOX (center_hbox), center_left_vbox, FALSE, FALSE, 0);
gtk_widget_show (center_left_vbox);
center_right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_box_pack_start (GTK_BOX (center_hbox), center_right_vbox, FALSE, FALSE, 0);
gtk_widget_show (center_right_vbox);
/* size select frame */
frame = gimp_frame_new (size_title);
gtk_box_pack_start (GTK_BOX (center_left_vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
/* size box */
private->box = g_object_new (GIMP_TYPE_SIZE_BOX,
"width", width,
"height", height,
"unit", unit,
"xresolution", xres,
"yresolution", yres,
"keep-aspect", FALSE,
"edit-resolution", FALSE,
NULL);
gtk_container_add (GTK_CONTAINER (frame), private->box);
gtk_widget_show (private->box);
/* offset frame */
frame = gimp_frame_new (_("Offset"));
gtk_box_pack_start (GTK_BOX (center_left_vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
2011-09-30 17:29:11 +08:00
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
2004-10-29 02:27:04 +08:00
gtk_container_add (GTK_CONTAINER (frame), vbox);
gtk_widget_show (vbox);
/* the offset sizeentry */
adjustment = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
spinbutton = gimp_spin_button_new (adjustment, 1.0, 2);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
2004-10-29 02:27:04 +08:00
gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), SB_WIDTH);
private->offset = entry = gimp_size_entry_new (1, unit, "%n",
2004-10-29 02:27:04 +08:00
TRUE, FALSE, FALSE, SB_WIDTH,
GIMP_SIZE_ENTRY_UPDATE_SIZE);
gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
GTK_SPIN_BUTTON (spinbutton), NULL);
gtk_grid_attach (GTK_GRID (entry), spinbutton, 1, 0, 1, 1);
2004-10-29 02:27:04 +08:00
gtk_widget_show (spinbutton);
gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry),
_("_X:"), 0, 0, 0.0);
gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry),_("_Y:"), 1, 0, 0.0);
gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
gtk_widget_show (entry);
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 0, xres, FALSE);
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 1, yres, FALSE);
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (entry), 0, 0, 0);
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (entry), 1, 0, 0);
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 0, 0);
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 1, 0);
g_signal_connect (entry, "value-changed",
2004-10-29 02:27:04 +08:00
G_CALLBACK (offset_update),
private);
2004-10-29 02:27:04 +08:00
frame = gtk_frame_new (NULL);
gtk_widget_set_halign (frame, GTK_ALIGN_CENTER);
2004-10-29 02:27:04 +08:00
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (center_right_vbox), frame, FALSE, FALSE, 0);
gtk_style_context_add_class (gtk_widget_get_style_context (frame),
"gimp-offset-area-frame");
gtk_widget_show (frame);
2004-10-29 02:27:04 +08:00
private->area = gimp_offset_area_new (width, height);
gtk_container_add (GTK_CONTAINER (frame), private->area);
gtk_widget_show (private->area);
gimp_viewable_get_preview_size (viewable, 200, TRUE, TRUE, &width, &height);
added GimpContext parameters and create the GimpView with that context. 2006-09-01 Michael Natterer <mitch@gimp.org> * app/widgets/gimpviewabledialog.[ch]: added GimpContext parameters and create the GimpView with that context. * app/widgets/gimpcolordialog.[ch] * app/dialogs/convert-dialog.[ch] * app/dialogs/desaturate-dialog.[ch] * app/dialogs/grid-dialog.[ch] * app/dialogs/image-properties-dialog.[ch] * app/dialogs/layer-add-mask-dialog.[ch] * app/dialogs/offset-dialog.[ch] * app/dialogs/print-size-dialog.[ch] * app/dialogs/resize-dialog.[ch] * app/dialogs/scale-dialog.[ch] * app/dialogs/stroke-dialog.[ch] * app/dialogs/template-options-dialog.[ch] * app/dialogs/vectors-options-dialog.[ch]: added GimpContext parameters here too and pass them to gimp_viewable_dialog_new(). * app/actions/colormap-editor-commands.c * app/actions/drawable-commands.c * app/actions/gradient-editor-commands.c * app/actions/image-commands.c * app/actions/layers-commands.c * app/actions/palette-editor-commands.c * app/actions/select-commands.c * app/actions/vectors-commands.c * app/actions/view-commands.c * app/dialogs/channel-options-dialog.c * app/dialogs/dialogs-constructors.c * app/dialogs/image-merge-layers-dialog.c * app/dialogs/image-scale-dialog.c * app/dialogs/layer-options-dialog.c * app/display/gimpdisplayshell-filter-dialog.c * app/display/gimpdisplayshell-scale.c * app/tools/gimpcolorpickertool.c * app/tools/gimpimagemaptool.c * app/tools/gimpmeasuretool.c * app/tools/gimptexttool.c * app/tools/gimptransformtool.c * app/tools/gimpvectortool.c * app/widgets/gimpcolorpanel.c * app/widgets/gimpcontrollereditor.c * app/widgets/gimpcontrollerlist.c * app/widgets/gimptoolbox-color-area.c: pass contexts to above dialog constructors.
2006-09-01 19:26:54 +08:00
pixbuf = gimp_viewable_get_pixbuf (viewable, context,
Changed GimpViewable preview rendering to have a context to get 2006-08-29 Michael Natterer <mitch@gimp.org> Changed GimpViewable preview rendering to have a context to get FG/BG/whatever from. Use the context to enable dynamic FG/BG colors in gradients. Fixes bug #127676 and bug #352214. Addresses bug #128367 (doesn't fix it because there's no loading/saving and no GUI yet). * app/core/core-enums.[ch]: added enum GimpGradientColor to enable specifying gradient colors in terms of foreground and background. * app/core/gimpgradient.[ch]: added color_type members to the GimpGradientSegment struct and honor them in gimp_gradient_get_color_at(). Added GimpContext parameters to all functions which finally call get_color_at(). * app/core/gimp-gradients.c: use the new method to implement the builtin gradients. * app/core/gimpviewable.[ch]: added GimpContext parameters to all get_preview() and get_pixbuf() functions. * app/core/gimpbrush.c * app/core/gimpbuffer.c * app/core/gimpdrawable-preview.[ch] * app/core/gimpgradient.c * app/core/gimpimage-preview.[ch] * app/core/gimpimagefile.c * app/core/gimppalette.c * app/core/gimppattern.c * app/core/gimpundo.[ch] * app/text/gimpfont.c * app/vectors/gimpvectors-preview.[ch]: changed ::get_preview() and ::get_pixbuf() implementations accordingly. * app/core/gimpdrawable-blend.c * app/core/gimppalette-import.[ch] * app/dialogs/dialogs-constructors.c * app/dialogs/palette-import-dialog.c * app/dialogs/resize-dialog.c * app/display/gimpdisplayshell-layer-select.c * app/display/gimpdisplayshell.c * app/display/gimpnavigationeditor.c * app/paint/gimppaintoptions.c * app/tools/gimpeditselectiontool.c * app/tools/gimptexttool.c * app/actions/gradient-editor-commands.c * app/widgets/gimpaction.c * app/widgets/gimpbrusheditor.[ch] * app/widgets/gimpbufferview.c * app/widgets/gimpcellrendererviewable.c * app/widgets/gimpchanneltreeview.c * app/widgets/gimpclipboard.c * app/widgets/gimpcoloreditor.c * app/widgets/gimpcomponenteditor.c * app/widgets/gimpcontainerbox.c * app/widgets/gimpcontainercombobox.c * app/widgets/gimpcontainereditor.c * app/widgets/gimpcontainerentry.c * app/widgets/gimpcontainergridview.c * app/widgets/gimpcontainertreeview.[ch] * app/widgets/gimpdataeditor.[ch] * app/widgets/gimpdevicestatus.c * app/widgets/gimpdnd.[ch] * app/widgets/gimpdrawabletreeview.c * app/widgets/gimpfiledialog.c * app/widgets/gimpgradienteditor.[ch] * app/widgets/gimpgradientselect.c * app/widgets/gimpitemtreeview.c * app/widgets/gimplayertreeview.c * app/widgets/gimppaletteeditor.[ch] * app/widgets/gimppropwidgets.[ch] * app/widgets/gimpselectioneditor.c * app/widgets/gimpthumbbox.[ch] * app/widgets/gimptoolbox-image-area.c * app/widgets/gimptoolbox-indicator-area.c * app/widgets/gimptooloptionseditor.c * app/widgets/gimpundoeditor.c * app/widgets/gimpvectorstreeview.c * app/widgets/gimpview-popup.[ch] * app/widgets/gimpview.[ch] * app/widgets/gimpviewablebutton.c * app/widgets/gimpviewabledialog.c * app/widgets/gimpviewrenderer.[ch] * app/widgets/gimpviewrenderer-frame.c * app/widgets/gimpviewrendererbrush.c * app/widgets/gimpviewrendererbuffer.c * app/widgets/gimpviewrendererdrawable.c * app/widgets/gimpviewrenderergradient.c * app/widgets/gimpviewrendererimage.c * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/gradient.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/image.pdb: added tons of GimpContext members and parameters, implement GimpDocked::set_context() in many widgets. Pass these locally remembered contexts to GimpViewable functions. Did some minor cleanups on the way. There are still some minor FIXMEs around where the code uses a NULL context (which is allowed by the APIs) * app/pdb/drawable_cmds.c * app/pdb/gradient_cmds.c * app/pdb/gradients_cmds.c * app/pdb/image_cmds.c: regenerated.
2006-08-30 05:44:51 +08:00
width, height);
2004-10-29 02:27:04 +08:00
if (pixbuf)
gimp_offset_area_set_pixbuf (GIMP_OFFSET_AREA (private->area), pixbuf);
2004-10-29 02:27:04 +08:00
g_signal_connect (private->area, "offsets-changed",
2004-10-29 02:27:04 +08:00
G_CALLBACK (offsets_changed),
private);
2004-10-29 02:27:04 +08:00
g_signal_connect (private->box, "notify",
G_CALLBACK (size_notify),
private);
2004-10-29 02:27:04 +08:00
/* Button to center the image on canvas just below the preview. */
button = gtk_button_new_with_mnemonic (_("C_enter"));
gtk_box_pack_start (GTK_BOX (center_right_vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
g_signal_connect (button, "clicked",
G_CALLBACK (offset_center_clicked),
private);
frame = gimp_frame_new (layers_title);
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_container_add (GTK_CONTAINER (frame), vbox);
gtk_widget_show (vbox);
if (GIMP_IS_IMAGE (viewable))
{
GtkWidget *label;
size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
2011-09-30 17:29:11 +08:00
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
label = gtk_label_new_with_mnemonic (_("Resize _layers:"));
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
gtk_size_group_add_widget (size_group, label);
private->layer_set_combo = combo =
gimp_enum_combo_box_new (GIMP_TYPE_ITEM_SET);
gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
gtk_widget_show (combo);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
private->layer_set,
G_CALLBACK (gimp_int_combo_box_get_active),
&private->layer_set, NULL);
}
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
private->fill_type_combo = combo =
gimp_enum_combo_box_new (GIMP_TYPE_FILL_TYPE);
gtk_box_pack_end (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
gtk_widget_show (combo);
gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
private->fill_type,
G_CALLBACK (gimp_int_combo_box_get_active),
&private->fill_type, NULL);
if (GIMP_IS_IMAGE (viewable))
{
GtkWidget *label;
label = gtk_label_new_with_mnemonic (_("_Fill with:"));
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
gtk_size_group_add_widget (size_group, label);
private->text_layers_button = button =
gtk_check_button_new_with_mnemonic (_("Resize _text layers"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
private->resize_text_layers);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
g_signal_connect (button, "toggled",
G_CALLBACK (gimp_toggle_button_update),
&private->resize_text_layers);
gimp_help_set_help_data (button,
_("Resizing text layers will make them uneditable"),
NULL);
g_object_unref (size_group);
}
return dialog;
}
/* private functions */
static void
resize_dialog_free (ResizeDialog *private)
{
g_object_unref (private->context);
g_slice_free (ResizeDialog, private);
}
static void
resize_dialog_response (GtkWidget *dialog,
gint response_id,
ResizeDialog *private)
{
GimpSizeEntry *entry = GIMP_SIZE_ENTRY (private->offset);
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
GimpUnit *unit;
gint width;
gint height;
gdouble xres;
gdouble yres;
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
GimpUnit *res_unit;
switch (response_id)
{
case RESPONSE_RESET:
resize_dialog_reset (private);
break;
case GTK_RESPONSE_OK:
g_object_get (private->box,
"width", &width,
"height", &height,
"unit", &unit,
"xresolution", &xres,
"yresolution", &yres,
"resolution-unit", &res_unit,
NULL);
private->callback (dialog,
private->viewable,
private->parent_context,
width,
height,
unit,
gimp_size_entry_get_refval (entry, 0),
gimp_size_entry_get_refval (entry, 1),
xres,
yres,
res_unit,
private->fill_type,
private->layer_set,
private->resize_text_layers,
private->user_data);
break;
default:
gtk_widget_destroy (dialog);
break;
}
}
static void
resize_dialog_reset (ResizeDialog *private)
{
g_object_set (private->box,
"keep-aspect", FALSE,
NULL);
g_object_set (private->box,
"unit", private->old_unit,
"xresolution", private->old_xres,
"yresolution", private->old_yres,
"resolution-unit", private->old_res_unit,
NULL);
/**
* reset width and height after the other properties to avoid the problems
* noted in issue #10225
**/
g_object_set (private->box,
"width", private->old_width,
"height", private->old_height,
NULL);
if (private->layer_set_combo)
gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (private->layer_set_combo),
private->old_layer_set);
gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (private->fill_type_combo),
private->old_fill_type);
if (private->text_layers_button)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (private->text_layers_button),
private->old_resize_text_layers);
gimp_context_set_template (private->context, NULL);
gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (private->offset),
private->old_unit);
}
static void
size_notify (GimpSizeBox *box,
GParamSpec *pspec,
ResizeDialog *private)
{
gint diff_x = box->width - private->old_width;
gint diff_y = box->height - private->old_height;
gimp_offset_area_set_size (GIMP_OFFSET_AREA (private->area),
box->width, box->height);
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (private->offset), 0,
MIN (0, diff_x), MAX (0, diff_x));
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (private->offset), 1,
MIN (0, diff_y), MAX (0, diff_y));
1997-11-25 06:05:25 +08:00
}
static gint
resize_bound_off_x (ResizeDialog *private,
gint offset_x)
1997-11-25 06:05:25 +08:00
{
GimpSizeBox *box = GIMP_SIZE_BOX (private->box);
1997-11-25 06:05:25 +08:00
if (private->old_width <= box->width)
return CLAMP (offset_x, 0, (box->width - private->old_width));
1997-11-25 06:05:25 +08:00
else
return CLAMP (offset_x, (box->width - private->old_width), 0);
1997-11-25 06:05:25 +08:00
}
static gint
resize_bound_off_y (ResizeDialog *private,
gint off_y)
1997-11-25 06:05:25 +08:00
{
GimpSizeBox *box = GIMP_SIZE_BOX (private->box);
1997-11-25 06:05:25 +08:00
if (private->old_height <= box->height)
return CLAMP (off_y, 0, (box->height - private->old_height));
1997-11-25 06:05:25 +08:00
else
return CLAMP (off_y, (box->height - private->old_height), 0);
1997-11-25 06:05:25 +08:00
}
static void
2004-10-29 02:27:04 +08:00
offset_update (GtkWidget *widget,
ResizeDialog *private)
1997-11-25 06:05:25 +08:00
{
GimpSizeEntry *entry = GIMP_SIZE_ENTRY (private->offset);
2004-10-29 02:27:04 +08:00
gint off_x;
gint off_y;
off_x = resize_bound_off_x (private,
2004-10-29 02:27:04 +08:00
RINT (gimp_size_entry_get_refval (entry, 0)));
off_y = resize_bound_off_y (private,
2004-10-29 02:27:04 +08:00
RINT (gimp_size_entry_get_refval (entry, 1)));
gimp_offset_area_set_offsets (GIMP_OFFSET_AREA (private->area), off_x, off_y);
}
1997-11-25 06:05:25 +08:00
static void
2004-10-29 02:27:04 +08:00
offsets_changed (GtkWidget *area,
gint off_x,
gint off_y,
ResizeDialog *private)
1997-11-25 06:05:25 +08:00
{
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->offset), 0, off_x);
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->offset), 1, off_y);
1997-11-25 06:05:25 +08:00
}
static void
2004-10-29 02:27:04 +08:00
offset_center_clicked (GtkWidget *widget,
ResizeDialog *private)
1997-11-25 06:05:25 +08:00
{
GimpSizeBox *box = GIMP_SIZE_BOX (private->box);
2004-10-29 02:27:04 +08:00
gint off_x;
gint off_y;
off_x = resize_bound_off_x (private, (box->width - private->old_width) / 2);
off_y = resize_bound_off_y (private, (box->height - private->old_height) / 2);
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->offset), 0, off_x);
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->offset), 1, off_y);
g_signal_emit_by_name (private->offset, "value-changed", 0);
}
static void
template_changed (GimpContext *context,
GimpTemplate *template,
ResizeDialog *private)
{
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
GimpUnit *unit = private->old_unit;
private->template = template;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (private->ppi_image), TRUE);
gtk_widget_hide (private->ppi_box);
if (template != NULL)
{
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
gdouble xres;
gdouble yres;
GimpUnit *res_unit;
gboolean resolution_mismatch;
unit = gimp_template_get_unit (template);
xres = gimp_template_get_resolution_x (template);
yres = gimp_template_get_resolution_y (template);
res_unit = gimp_template_get_resolution_unit (template);
resolution_mismatch = xres != private->old_xres ||
yres != private->old_yres ||
res_unit != private->old_res_unit;
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
if (resolution_mismatch && unit != gimp_unit_pixel ())
{
gchar *text;
text = g_strdup_printf (_("Scale template to %.2f ppi"),
private->old_xres);
gtk_button_set_label (GTK_BUTTON (private->ppi_image), text);
g_free (text);
text = g_strdup_printf (_("Set image to %.2f ppi"),
xres);
gtk_button_set_label (GTK_BUTTON (private->ppi_template), text);
g_free (text);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (private->ppi_image),
TRUE);
gtk_widget_show (private->ppi_box);
}
}
ppi_select_toggled (NULL, private);
gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (private->offset), unit);
}
static void
ppi_select_toggled (GtkWidget *radio,
ResizeDialog *private)
{
gint width;
gint height;
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
GimpUnit *unit;
gdouble xres;
gdouble yres;
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
GimpUnit *res_unit;
GtkToggleButton *image_button;
gboolean use_image_ppi;
width = private->old_width;
height = private->old_height;
xres = private->old_xres;
yres = private->old_yres;
res_unit = private->old_res_unit;
unit = private->old_unit;
image_button = GTK_TOGGLE_BUTTON (private->ppi_image);
use_image_ppi = gtk_toggle_button_get_active (image_button);
if (private->template != NULL)
{
width = gimp_template_get_width (private->template);
height = gimp_template_get_height (private->template);
unit = gimp_template_get_unit (private->template);
xres = gimp_template_get_resolution_x (private->template);
yres = gimp_template_get_resolution_y (private->template);
res_unit = gimp_template_get_resolution_unit (private->template);
}
Issue #8900 and #9923: reimplementing GimpUnit as a proper class. This fixes all our GObject Introspection issues with GimpUnit which was both an enum and an int-derived type of user-defined units *completing* the enum values. GIR clearly didn't like this! Now GimpUnit is a proper class and units are unique objects, allowing to compare them with an identity test (i.e. `unit == gimp_unit_pixel ()` tells us if unit is the pixel unit or not), which makes it easy to use, just like with int, yet adding also methods, making for nicer introspected API. As an aside, this also fixes #10738, by having all the built-in units retrievable even if libgimpbase had not been properly initialized with gimp_base_init(). I haven't checked in details how GIR works to introspect, but it looks like it loads the library to inspect and runs functions, hence triggering some CRITICALS because virtual methods (supposed to be initialized with gimp_base_init() run by libgimp) are not set. This new code won't trigger any critical because the vtable method are now not necessary, at least for all built-in units. Note that GimpUnit is still in libgimpbase. It could have been moved to libgimp in order to avoid any virtual method table (since we need to keep core and libgimp side's units in sync, PDB is required), but too many libgimpwidgets widgets were already using GimpUnit. And technically most of GimpUnit logic doesn't require PDB (only the creation/sync part). This is one of the reasons why user-created GimpUnit list is handled and stored differently from other types of objects. Globally this simplifies the code a lot too and we don't need separate implementations of various utils for core and libgimp, which means less prone to errors.
2024-07-26 02:55:21 +08:00
if (private->template != NULL && unit != gimp_unit_pixel ())
{
if (use_image_ppi)
{
width = ceil (width * (private->old_xres / xres));
height = ceil (height * (private->old_yres / yres));
xres = private->old_xres;
yres = private->old_yres;
}
g_object_set (private->box,
"xresolution", xres,
"yresolution", yres,
"resolution-unit", res_unit,
NULL);
}
else
{
g_object_set (private->box,
"xresolution", private->old_xres,
"yresolution", private->old_yres,
"resolution-unit", private->old_res_unit,
NULL);
}
g_object_set (private->box,
"width", width,
"height", height,
"unit", unit,
NULL);
}
static void
reset_template_clicked (GtkWidget *button,
ResizeDialog *private)
{
gimp_context_set_template (private->context, NULL);
}