From a018b06a96e96e202992901b69ce3cded0ac6857 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Thu, 3 Apr 2003 17:50:56 +0000 Subject: [PATCH] Added preliminary support for image templates. Not finished yet. Addresses 2003-04-03 Michael Natterer Added preliminary support for image templates. Not finished yet. Addresses bug #96059. Now we need a volunteer to create a nice collection of default templates... * app/core/Makefile.am * app/core/core-types.h * app/core/gimptemplate.[ch] * app/core/gimp-templates.[ch]: new files implementing the new GimpTemplate object and the list of available image templates. * app/core/gimp.[ch]: keep a container of templates around. * app/core/gimpimage-new.[ch]: ported to use GimpTemplate. Removed struct GimpImageNewValues. * app/widgets/gimpcontainermenuimpl.c: changed to show the "(none)" item for a NULL selection also, not only for an empty container. * app/widgets/gimppropwidgets.[ch]: added gimp_prop_size_entry_connect() which connects an externally created GimpSizeEntry to object properties. Fixed the size entry code to actually work. * app/gui/image-menu.c * app/gui/file-commands.[ch]: added "Save as Template" which creates a new template from any image's properties. * app/gui/file-new-dialog.c: use prop_widgets and GimpTemplate. Offer the available templates in a menu at the top of the dialog. --- ChangeLog | 33 +++ app/actions/file-commands.c | 48 ++- app/actions/file-commands.h | 3 + app/core/Makefile.am | 4 + app/core/core-types.h | 4 +- app/core/gimp-templates.c | 87 ++++++ app/core/gimp-templates.h | 27 ++ app/core/gimp.c | 41 ++- app/core/gimp.h | 3 +- app/core/gimpimage-new.c | 147 ++-------- app/core/gimpimage-new.h | 31 +- app/core/gimptemplate.c | 438 ++++++++++++++++++++++++++++ app/core/gimptemplate.h | 76 +++++ app/dialogs/image-new-dialog.c | 433 ++++++++++----------------- app/gui/file-commands.c | 48 ++- app/gui/file-commands.h | 3 + app/gui/file-new-dialog.c | 433 ++++++++++----------------- app/gui/image-menu.c | 4 + app/menus/image-menu.c | 4 + app/widgets/gimpcontainermenuimpl.c | 14 +- app/widgets/gimppropwidgets.c | 137 +++++---- app/widgets/gimppropwidgets.h | 9 + libgimpwidgets/gimppropwidgets.c | 137 +++++---- libgimpwidgets/gimppropwidgets.h | 9 + 24 files changed, 1338 insertions(+), 835 deletions(-) create mode 100644 app/core/gimp-templates.c create mode 100644 app/core/gimp-templates.h create mode 100644 app/core/gimptemplate.c create mode 100644 app/core/gimptemplate.h diff --git a/ChangeLog b/ChangeLog index 4b3cf32ef1..0ead866c2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2003-04-03 Michael Natterer + + Added preliminary support for image templates. Not finished + yet. Addresses bug #96059. Now we need a volunteer to create + a nice collection of default templates... + + * app/core/Makefile.am + * app/core/core-types.h + * app/core/gimptemplate.[ch] + * app/core/gimp-templates.[ch]: new files implementing the new + GimpTemplate object and the list of available image templates. + + * app/core/gimp.[ch]: keep a container of templates around. + + * app/core/gimpimage-new.[ch]: ported to use GimpTemplate. Removed + struct GimpImageNewValues. + + * app/widgets/gimpcontainermenuimpl.c: changed to show the + "(none)" item for a NULL selection also, not only for an empty + container. + + * app/widgets/gimppropwidgets.[ch]: added + gimp_prop_size_entry_connect() which connects an externally + created GimpSizeEntry to object properties. Fixed the size entry + code to actually work. + + * app/gui/image-menu.c + * app/gui/file-commands.[ch]: added "Save as Template" which + creates a new template from any image's properties. + + * app/gui/file-new-dialog.c: use prop_widgets and GimpTemplate. + Offer the available templates in a menu at the top of the dialog. + 2003-04-03 Michael Natterer * app/tools/gimpmovetool.c (gimp_move_tool_button_release): don't diff --git a/app/actions/file-commands.c b/app/actions/file-commands.c index df3a46177b..fae97ed6b9 100644 --- a/app/actions/file-commands.c +++ b/app/actions/file-commands.c @@ -18,6 +18,8 @@ #include "config.h" +#include + #include #include "libgimpwidgets/gimpwidgets.h" @@ -31,7 +33,7 @@ #include "core/gimpcontext.h" #include "core/gimpimage.h" #include "core/gimpimage-undo.h" -#include "core/gimpobject.h" +#include "core/gimptemplate.h" #include "file/file-open.h" #include "file/file-save.h" @@ -77,6 +79,9 @@ /* local function prototypes */ +static void file_new_template_callback (GtkWidget *widget, + gchar *name, + gpointer data); static void file_revert_confirm_callback (GtkWidget *widget, gboolean revert, gpointer data); @@ -264,6 +269,25 @@ file_save_a_copy_cmd_callback (GtkWidget *widget, file_save_a_copy_dialog_show (gdisp->gimage, global_menu_factory); } +void +file_save_template_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GimpDisplay *gdisp; + GtkWidget *qbox; + return_if_no_display (gdisp, data); + + qbox = gimp_query_string_box (_("Create New Template"), + gimp_standard_help_func, + "dialogs/new_template.html", + _("Enter a name for this template"), + NULL, + G_OBJECT (gdisp->gimage), "disconnect", + file_new_template_callback, gdisp->gimage); + gtk_widget_show (qbox); +} + void file_revert_cmd_callback (GtkWidget *widget, gpointer data, @@ -354,8 +378,30 @@ file_file_open_dialog (Gimp *gimp, file_open_dialog_show (gimp, NULL, uri, global_menu_factory); } + /* private functions */ +static void +file_new_template_callback (GtkWidget *widget, + gchar *name, + gpointer data) +{ + GimpTemplate *template; + GimpImage *gimage; + + gimage = (GimpImage *) data; + + if (! (name && strlen (name))) + name = _("(Unnamed Template)"); + + template = gimp_template_new (name); + gimp_template_set_from_image (template, gimage); + + gimp_container_add (gimage->gimp->templates, + GIMP_OBJECT (template)); + g_object_unref (template); +} + static void file_revert_confirm_callback (GtkWidget *widget, gboolean revert, diff --git a/app/actions/file-commands.h b/app/actions/file-commands.h index b2ad508d82..6f04b95437 100644 --- a/app/actions/file-commands.h +++ b/app/actions/file-commands.h @@ -52,6 +52,9 @@ void file_save_as_cmd_callback (GtkWidget *widget, void file_save_a_copy_cmd_callback (GtkWidget *widget, gpointer data, guint action); +void file_save_template_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); void file_revert_cmd_callback (GtkWidget *widget, gpointer data, diff --git a/app/core/Makefile.am b/app/core/Makefile.am index feade87ff9..000825a6ab 100644 --- a/app/core/Makefile.am +++ b/app/core/Makefile.am @@ -28,6 +28,8 @@ libappcore_a_sources = \ gimp-gradients.h \ gimp-parasites.c \ gimp-parasites.h \ + gimp-templates.c \ + gimp-templates.h \ gimpbrush.c \ gimpbrush.h \ gimpbrush-header.h \ @@ -156,6 +158,8 @@ libappcore_a_sources = \ gimppreviewcache.h \ gimpscanconvert.c \ gimpscanconvert.h \ + gimptemplate.c \ + gimptemplate.h \ gimptoolinfo.c \ gimptoolinfo.h \ gimpunit.c \ diff --git a/app/core/core-types.h b/app/core/core-types.h index 42095180a9..81ea265187 100644 --- a/app/core/core-types.h +++ b/app/core/core-types.h @@ -73,6 +73,8 @@ typedef struct _GimpToolOptions GimpToolOptions; /*< proxy-include >*/ typedef struct _GimpImagefile GimpImagefile; typedef struct _GimpDocumentList GimpDocumentList; +typedef struct _GimpTemplate GimpTemplate; + /* drawable objects */ @@ -122,8 +124,6 @@ typedef struct _GimpCoords GimpCoords; /*< proxy-include >*/ typedef struct _GimpGuide GimpGuide; -typedef struct _GimpImageNewValues GimpImageNewValues; - typedef struct _GimpProgress GimpProgress; typedef guint32 GimpTattoo; diff --git a/app/core/gimp-templates.c b/app/core/gimp-templates.c new file mode 100644 index 0000000000..82737c92b7 --- /dev/null +++ b/app/core/gimp-templates.c @@ -0,0 +1,87 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpbase/gimpbase.h" + +#include "core-types.h" + +#include "config/gimpconfig.h" + +#include "gimp.h" +#include "gimp-templates.h" +#include "gimplist.h" +#include "gimptemplate.h" + + +/* functions to load and save the gimp templates files */ + +void +gimp_templates_load (Gimp *gimp) +{ + gchar *filename; + GError *error = NULL; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + g_return_if_fail (GIMP_IS_LIST (gimp->templates)); + + filename = gimp_personal_rc_file ("templates"); + + if (!gimp_config_deserialize (G_OBJECT (gimp->templates), + filename, + NULL, + &error)) + { + if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT) + g_message (error->message); + g_error_free (error); + } + + g_free (filename); +} + +void +gimp_templates_save (Gimp *gimp) +{ + const gchar *header = + "GIMP templates\n" + "\n" + "This file will be entirely rewritten every time you quit the gimp."; + const gchar *footer = + "end of templates"; + + gchar *filename; + GError *error = NULL; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + g_return_if_fail (GIMP_IS_LIST (gimp->templates)); + + filename = gimp_personal_rc_file ("templates"); + + if (! gimp_config_serialize (G_OBJECT (gimp->templates), + filename, header, footer, NULL, &error)) + { + g_message (error->message); + g_error_free (error); + } + + g_free (filename); +} diff --git a/app/core/gimp-templates.h b/app/core/gimp-templates.h new file mode 100644 index 0000000000..dcca7593a2 --- /dev/null +++ b/app/core/gimp-templates.h @@ -0,0 +1,27 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_TEMPLATES_H__ +#define __GIMP_TEMPLATES_H__ + + +void gimp_templates_load (Gimp *gimp); +void gimp_templates_save (Gimp *gimp); + + +#endif /* __GIMP_TEMPLATES_H__ */ diff --git a/app/core/gimp.c b/app/core/gimp.c index 3509282903..f020f05dee 100644 --- a/app/core/gimp.c +++ b/app/core/gimp.c @@ -44,6 +44,7 @@ #include "gimp-documents.h" #include "gimp-gradients.h" #include "gimp-parasites.h" +#include "gimp-templates.h" #include "gimpbrush.h" #include "gimpbrushgenerated.h" #include "gimpbrushpipe.h" @@ -62,6 +63,7 @@ #include "gimppalette.h" #include "gimppattern.h" #include "gimpparasitelist.h" +#include "gimptemplate.h" #include "gimptoolinfo.h" #include "gimpunits.h" @@ -251,6 +253,9 @@ gimp_init (Gimp *gimp) gimp->documents = gimp_document_list_new (gimp); + gimp->templates = gimp_list_new (GIMP_TYPE_TEMPLATE, + GIMP_CONTAINER_POLICY_STRONG); + gimp->image_new_last_template = NULL; gimp->have_current_cut_buffer = FALSE; gimp->context_list = NULL; @@ -299,6 +304,18 @@ gimp_finalize (GObject *object) gimp->standard_context = NULL; } + if (gimp->image_new_last_template) + { + g_object_unref (gimp->image_new_last_template); + gimp->image_new_last_template = NULL; + } + + if (gimp->templates) + { + g_object_unref (gimp->templates); + gimp->templates = NULL; + } + if (gimp->documents) { g_object_unref (gimp->documents); @@ -466,7 +483,9 @@ gimp_get_memsize (GimpObject *object) memsize += (gimp_object_get_memsize (GIMP_OBJECT (gimp->tool_info_list)) + gimp_object_get_memsize (GIMP_OBJECT (gimp->standard_tool_info)) + - gimp_object_get_memsize (GIMP_OBJECT (gimp->documents))); + gimp_object_get_memsize (GIMP_OBJECT (gimp->documents)) + + gimp_object_get_memsize (GIMP_OBJECT (gimp->templates)) + + gimp_object_get_memsize (GIMP_OBJECT (gimp->image_new_last_template))); memsize += g_list_length (gimp->context_list) * sizeof (GList); @@ -487,6 +506,7 @@ gimp_real_exit (Gimp *gimp, gimp_data_factory_data_save (gimp->gradient_factory); gimp_data_factory_data_save (gimp->palette_factory); gimp_documents_save (gimp); + gimp_templates_save (gimp); gimp_parasiterc_save (gimp); gimp_unitrc_save (gimp); @@ -690,15 +710,8 @@ gimp_initialize (Gimp *gimp, /* Set the last values used to default values. */ - gimp->image_new_last_values.width = gimp->config->default_image_width; - gimp->image_new_last_values.height = gimp->config->default_image_height; - gimp->image_new_last_values.unit = gimp->config->default_unit; - gimp->image_new_last_values.xresolution = gimp->config->default_xresolution; - gimp->image_new_last_values.yresolution = gimp->config->default_yresolution; - gimp->image_new_last_values.res_unit = gimp->config->default_resolution_unit; - gimp->image_new_last_values.type = gimp->config->default_image_type; - gimp->image_new_last_values.fill_type = GIMP_BACKGROUND_FILL; - + gimp->image_new_last_template = gimp_template_new ("last values"); + gimp_template_set_from_config (gimp->image_new_last_template, gimp->config); gimp->have_current_cut_buffer = FALSE; gimp->standard_context = gimp_context_new (gimp, "Standard", NULL); @@ -762,15 +775,19 @@ gimp_restore (Gimp *gimp, gimp_data_factory_data_init (gimp->gradient_factory, no_data); /* initialize the list of gimp fonts */ - (* status_callback) (NULL, _("Fonts"), 0.75); + (* status_callback) (NULL, _("Fonts"), 0.70); gimp_container_freeze (gimp->fonts); gimp_font_list_restore (GIMP_FONT_LIST (gimp->fonts)); gimp_container_thaw (gimp->fonts); /* initialize the document history */ - (* status_callback) (NULL, _("Documents"), 0.90); + (* status_callback) (NULL, _("Documents"), 0.80); gimp_documents_load (gimp); + /* initialize the template list */ + (* status_callback) (NULL, _("Templates"), 0.90); + gimp_templates_load (gimp); + (* status_callback) (NULL, NULL, 1.00); gimp_modules_load (gimp); diff --git a/app/core/gimp.h b/app/core/gimp.h index 2e51bc4238..28777e7426 100644 --- a/app/core/gimp.h +++ b/app/core/gimp.h @@ -128,7 +128,8 @@ struct _Gimp GimpContainer *documents; /* image_new values */ - GimpImageNewValues image_new_last_values; + GimpContainer *templates; + GimpTemplate *image_new_last_template; gboolean have_current_cut_buffer; /* the list of all contexts */ diff --git a/app/core/gimpimage-new.c b/app/core/gimpimage-new.c index 927ec9a9dc..11ad62c202 100644 --- a/app/core/gimpimage-new.c +++ b/app/core/gimpimage-new.c @@ -20,94 +20,60 @@ #include -#include "libgimpbase/gimpbase.h" - #include "core-types.h" -#include "paint-funcs/paint-funcs.h" - -#include "config/gimpcoreconfig.h" +#include "config/gimpconfig.h" +#include "config/gimpconfig-utils.h" #include "gimp.h" #include "gimpbuffer.h" -#include "gimpdrawable.h" #include "gimpimage.h" #include "gimpimage-new.h" -#include "gimplayer.h" +#include "gimptemplate.h" #include "gimp-intl.h" -GimpImageNewValues * -gimp_image_new_values_new (Gimp *gimp, - GimpImage *gimage) +GimpTemplate * +gimp_image_new_template_new (Gimp *gimp, + GimpImage *gimage) { - GimpImageNewValues *values; + GimpTemplate *template; - values = g_new0 (GimpImageNewValues, 1); + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); + g_return_val_if_fail (gimage == NULL || GIMP_IS_IMAGE (gimage), NULL); + + template = gimp_template_new ("image new values"); if (gimage) - { - values->width = gimp_image_get_width (gimage); - values->height = gimp_image_get_height (gimage); - values->unit = gimp_image_get_unit (gimage); - - gimp_image_get_resolution (gimage, - &values->xresolution, - &values->yresolution); - - values->type = gimp_image_base_type (gimage); - - if (values->type == GIMP_INDEXED) - values->type = GIMP_RGB; /* no indexed images */ - - values->fill_type = GIMP_BACKGROUND_FILL; - } + gimp_template_set_from_image (template, gimage); else - { - *values = gimp->image_new_last_values; - } + gimp_config_copy_properties (G_OBJECT (gimp->image_new_last_template), + G_OBJECT (template)); if (gimp->global_buffer && gimp->have_current_cut_buffer) { - values->width = gimp_buffer_get_width (gimp->global_buffer); - values->height = gimp_buffer_get_height (gimp->global_buffer); + g_object_set (template, + "width", gimp_buffer_get_width (gimp->global_buffer), + "height", gimp_buffer_get_height (gimp->global_buffer), + NULL); } - return values; + return template; } void -gimp_image_new_set_default_values (Gimp *gimp, - GimpImageNewValues *values) +gimp_image_new_set_last_template (Gimp *gimp, + GimpTemplate *template) { - g_return_if_fail (values != NULL); - - gimp->image_new_last_values = *values; + g_return_if_fail (GIMP_IS_GIMP (gimp)); + g_return_if_fail (GIMP_IS_TEMPLATE (template)); + gimp_config_copy_properties (G_OBJECT (template), + G_OBJECT (gimp->image_new_last_template)); gimp->have_current_cut_buffer = FALSE; } -void -gimp_image_new_values_free (GimpImageNewValues *values) -{ - g_return_if_fail (values != NULL); - - g_free (values); -} - -gsize -gimp_image_new_calculate_memsize (GimpImageNewValues *values) -{ - gint channels; - - channels = ((values->type == GIMP_RGB ? 3 : 1) /* color */ + - (values->fill_type == GIMP_TRANSPARENT_FILL) /* alpha */ + - 1 /* selection */); - - return channels * values->width * values->height; -} - gchar * gimp_image_new_get_memsize_string (gsize memsize) { @@ -138,64 +104,13 @@ gimp_image_new_get_memsize_string (gsize memsize) } GimpImage * -gimp_image_new_create_image (Gimp *gimp, - GimpImageNewValues *values) +gimp_image_new_create_image (Gimp *gimp, + GimpTemplate *template) { - GimpImage *gimage; - GimpLayer *layer; - GimpImageType type; - gint width, height; + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); + g_return_val_if_fail (GIMP_IS_TEMPLATE (template), NULL); - g_return_val_if_fail (values != NULL, NULL); + gimp_image_new_set_last_template (gimp, template); - gimp_image_new_set_default_values (gimp, values); - - switch (values->fill_type) - { - case GIMP_FOREGROUND_FILL: - case GIMP_BACKGROUND_FILL: - case GIMP_WHITE_FILL: - type = (values->type == GIMP_RGB) ? GIMP_RGB_IMAGE : GIMP_GRAY_IMAGE; - break; - case GIMP_TRANSPARENT_FILL: - type = (values->type == GIMP_RGB) ? GIMP_RGBA_IMAGE : GIMP_GRAYA_IMAGE; - break; - default: - type = GIMP_RGB_IMAGE; - break; - } - - gimage = gimp_create_image (gimp, - values->width, values->height, - values->type, - TRUE); - - gimp_image_set_resolution (gimage, values->xresolution, values->yresolution); - gimp_image_set_unit (gimage, values->unit); - - width = gimp_image_get_width (gimage); - height = gimp_image_get_height (gimage); - - layer = gimp_layer_new (gimage, width, height, - type, _("Background"), - GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); - - if (layer) - { - gimp_image_undo_disable (gimage); - gimp_image_add_layer (gimage, layer, 0); - gimp_image_undo_enable (gimage); - - gimp_drawable_fill_by_type (GIMP_DRAWABLE (layer), - gimp_get_current_context (gimp), - values->fill_type); - - gimp_image_clean_all (gimage); - - gimp_create_display (gimp, gimage, 0x0101); - - g_object_unref (gimage); - } - - return gimage; + return gimp_template_create_image (gimp, template); } diff --git a/app/core/gimpimage-new.h b/app/core/gimpimage-new.h index caa0512b9d..2b29bf9653 100644 --- a/app/core/gimpimage-new.h +++ b/app/core/gimpimage-new.h @@ -20,33 +20,16 @@ #define __GIMP_IMAGE_NEW_H__ -struct _GimpImageNewValues -{ - gint width; - gint height; - GimpUnit unit; +GimpTemplate * gimp_image_new_template_new (Gimp *gimp, + GimpImage *gimage); - gdouble xresolution; - gdouble yresolution; - GimpUnit res_unit; - - GimpImageBaseType type; - GimpFillType fill_type; -}; +void gimp_image_new_set_last_template (Gimp *gimp, + GimpTemplate *template); +gchar * gimp_image_new_get_memsize_string (gsize memsize); -GimpImageNewValues * gimp_image_new_values_new (Gimp *gimp, - GimpImage *gimage); - -void gimp_image_new_set_default_values (Gimp *gimp, - GimpImageNewValues *values); -void gimp_image_new_values_free (GimpImageNewValues *values); - -gsize gimp_image_new_calculate_memsize (GimpImageNewValues *values); -gchar * gimp_image_new_get_memsize_string (gsize memsize); - -GimpImage * gimp_image_new_create_image (Gimp *gimp, - GimpImageNewValues *values); +GimpImage * gimp_image_new_create_image (Gimp *gimp, + GimpTemplate *template); #endif /* __GIMP_IMAGE_NEW__ */ diff --git a/app/core/gimptemplate.c b/app/core/gimptemplate.c new file mode 100644 index 0000000000..d535c48400 --- /dev/null +++ b/app/core/gimptemplate.c @@ -0,0 +1,438 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * gimptemplate.c + * Copyright (C) 2003 Michael Natterer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpbase/gimpbase.h" + +#include "core-types.h" + +#include "config/gimpconfig.h" +#include "config/gimpconfig-deserialize.h" +#include "config/gimpconfig-serialize.h" +#include "config/gimpconfig-params.h" +#include "config/gimpcoreconfig.h" + +#include "gimp.h" +#include "gimpimage.h" +#include "gimplayer.h" +#include "gimptemplate.h" + +#include "gimp-intl.h" + + +enum +{ + PROP_0, + PROP_WIDTH, + PROP_HEIGHT, + PROP_UNIT, + PROP_XRESOLUTION, + PROP_YRESOLUTION, + PROP_RESOLUTION_UNIT, + PROP_IMAGE_TYPE, + PROP_FILL_TYPE +}; + + +static void gimp_template_class_init (GimpTemplateClass *klass); +static void gimp_template_init (GimpTemplate *template); +static void gimp_template_config_iface_init (GimpConfigInterface *config_iface); + +static void gimp_template_finalize (GObject *object); +static void gimp_template_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_template_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gboolean gimp_template_serialize (GObject *object, + GimpConfigWriter *writer, + gpointer data); +static gboolean gimp_template_deserialize (GObject *object, + GScanner *scanner, + gint nest_level, + gpointer data); + + +static GimpViewableClass *parent_class = NULL; + + +GType +gimp_template_get_type (void) +{ + static GType template_type = 0; + + if (! template_type) + { + static const GTypeInfo template_info = + { + sizeof (GimpTemplateClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gimp_template_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpTemplate), + 0, /* n_preallocs */ + (GInstanceInitFunc) gimp_template_init, + }; + static const GInterfaceInfo config_iface_info = + { + (GInterfaceInitFunc) gimp_template_config_iface_init, + NULL, /* iface_finalize */ + NULL /* iface_data */ + }; + + template_type = g_type_register_static (GIMP_TYPE_VIEWABLE, + "GimpTemplate", + &template_info, 0); + + g_type_add_interface_static (template_type, + GIMP_TYPE_CONFIG_INTERFACE, + &config_iface_info); + } + + return template_type; +} + +static void +gimp_template_class_init (GimpTemplateClass *klass) +{ + GObjectClass *object_class; + GimpViewableClass *viewable_class; + + object_class = G_OBJECT_CLASS (klass); + viewable_class = GIMP_VIEWABLE_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gimp_template_finalize; + + object_class->set_property = gimp_template_set_property; + object_class->get_property = gimp_template_get_property; + + viewable_class->default_stock_id = "gimp-template"; + + GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_WIDTH, "width", + NULL, + 1, GIMP_MAX_IMAGE_SIZE, 256, + 0); + GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_HEIGHT, "height", + NULL, + 1, GIMP_MAX_IMAGE_SIZE, 256, + 0); + GIMP_CONFIG_INSTALL_PROP_UNIT (object_class, PROP_UNIT, "unit", + NULL, + FALSE, GIMP_UNIT_INCH, + 0); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_XRESOLUTION, + "xresolution", + NULL, + GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION, + 72.0, + 0); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_YRESOLUTION, + "yresolution", + NULL, + GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION, + 72.0, + 0); + GIMP_CONFIG_INSTALL_PROP_UNIT (object_class, PROP_RESOLUTION_UNIT, + "resolution-unit", + NULL, + FALSE, GIMP_UNIT_INCH, + 0); + + GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_IMAGE_TYPE, + "image-type", + NULL, + GIMP_TYPE_IMAGE_BASE_TYPE, GIMP_RGB, + 0); + GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_FILL_TYPE, + "fill-type", + NULL, + GIMP_TYPE_FILL_TYPE, GIMP_BACKGROUND_FILL, + 0); +} + +static void +gimp_template_init (GimpTemplate *template) +{ +} + +static void +gimp_template_config_iface_init (GimpConfigInterface *config_iface) +{ + config_iface->serialize = gimp_template_serialize; + config_iface->deserialize = gimp_template_deserialize; +} + +static void +gimp_template_finalize (GObject *object) +{ + GimpTemplate *template; + + template = GIMP_TEMPLATE (object); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_template_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpTemplate *template; + + template = GIMP_TEMPLATE (object); + + switch (property_id) + { + case PROP_WIDTH: + template->width = g_value_get_int (value); + break; + case PROP_HEIGHT: + template->height = g_value_get_int (value); + break; + case PROP_UNIT: + template->unit = g_value_get_int (value); + break; + case PROP_XRESOLUTION: + template->xresolution = g_value_get_double (value); + break; + case PROP_YRESOLUTION: + template->yresolution = g_value_get_double (value); + break; + case PROP_RESOLUTION_UNIT: + template->resolution_unit = g_value_get_int (value); + break; + case PROP_IMAGE_TYPE: + template->image_type = g_value_get_enum (value); + break; + case PROP_FILL_TYPE: + template->fill_type = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_template_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpTemplate *template; + + template = GIMP_TEMPLATE (object); + + switch (property_id) + { + case PROP_WIDTH: + g_value_set_int (value, template->width); + break; + case PROP_HEIGHT: + g_value_set_int (value, template->height); + break; + case PROP_UNIT: + g_value_set_int (value, template->unit); + break; + case PROP_XRESOLUTION: + g_value_set_double (value, template->xresolution); + break; + case PROP_YRESOLUTION: + g_value_set_double (value, template->yresolution); + break; + case PROP_RESOLUTION_UNIT: + g_value_set_int (value, template->resolution_unit); + break; + case PROP_IMAGE_TYPE: + g_value_set_enum (value, template->image_type); + break; + case PROP_FILL_TYPE: + g_value_set_enum (value, template->fill_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gboolean +gimp_template_serialize (GObject *object, + GimpConfigWriter *writer, + gpointer data) +{ + return gimp_config_serialize_properties (object, writer); +} + +static gboolean +gimp_template_deserialize (GObject *object, + GScanner *scanner, + gint nest_level, + gpointer data) +{ + return gimp_config_deserialize_properties (object, scanner, nest_level, FALSE); +} + + +/* public functions */ + +GimpTemplate * +gimp_template_new (const gchar *name) +{ + g_return_val_if_fail (name != NULL, NULL); + + return g_object_new (GIMP_TYPE_TEMPLATE, + "name", name, + NULL); +} + +void +gimp_template_set_from_config (GimpTemplate *template, + GimpCoreConfig *config) +{ + g_return_if_fail (GIMP_IS_TEMPLATE (template)); + g_return_if_fail (GIMP_IS_CORE_CONFIG (config)); + + g_object_set (template, + "width", config->default_image_width, + "height", config->default_image_height, + "unit", config->default_unit, + "xresolution", config->default_xresolution, + "yresolution", config->default_yresolution, + "resolution-unit", config->default_resolution_unit, + "image-type", config->default_image_type, + NULL); +} + +void +gimp_template_set_from_image (GimpTemplate *template, + GimpImage *gimage) +{ + gdouble xresolution; + gdouble yresolution; + GimpImageBaseType image_type; + + g_return_if_fail (GIMP_IS_TEMPLATE (template)); + g_return_if_fail (GIMP_IS_IMAGE (gimage)); + + gimp_image_get_resolution (gimage, &xresolution, &yresolution); + + image_type = gimp_image_base_type (gimage); + + if (image_type == GIMP_INDEXED) + image_type = GIMP_RGB; + + g_object_set (template, + "width", gimp_image_get_width (gimage), + "height", gimp_image_get_height (gimage), + "unit", gimp_image_get_unit (gimage), + "xresolution", xresolution, + "yresolution", yresolution, + "image-type", image_type, + NULL); +} + +gsize +gimp_template_calc_memsize (GimpTemplate *template) +{ + gint channels; + + g_return_val_if_fail (GIMP_IS_TEMPLATE (template), 0); + + channels = ((template->image_type == GIMP_RGB ? 3 : 1) /* color */ + + (template->fill_type == GIMP_TRANSPARENT_FILL) /* alpha */ + + 1 /* selection */); + + return channels * template->width * template->height; +} + +GimpImage * +gimp_template_create_image (Gimp *gimp, + GimpTemplate *template) +{ + GimpImage *gimage; + GimpLayer *layer; + GimpImageType type; + gint width, height; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); + g_return_val_if_fail (GIMP_IS_TEMPLATE (template), NULL); + + switch (template->fill_type) + { + case GIMP_FOREGROUND_FILL: + case GIMP_BACKGROUND_FILL: + case GIMP_WHITE_FILL: + type = (template->image_type == GIMP_RGB) ? GIMP_RGB_IMAGE : GIMP_GRAY_IMAGE; + break; + case GIMP_TRANSPARENT_FILL: + type = (template->image_type == GIMP_RGB) ? GIMP_RGBA_IMAGE : GIMP_GRAYA_IMAGE; + break; + default: + type = GIMP_RGB_IMAGE; + break; + } + + gimage = gimp_create_image (gimp, + template->width, template->height, + template->image_type, + TRUE); + + gimp_image_undo_disable (gimage); + + gimp_image_set_resolution (gimage, + template->xresolution, template->yresolution); + gimp_image_set_unit (gimage, template->unit); + + width = gimp_image_get_width (gimage); + height = gimp_image_get_height (gimage); + + layer = gimp_layer_new (gimage, width, height, + type, _("Background"), + GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); + + gimp_image_add_layer (gimage, layer, 0); + + gimp_drawable_fill_by_type (GIMP_DRAWABLE (layer), + gimp_get_current_context (gimp), + template->fill_type); + + gimp_image_undo_enable (gimage); + gimp_image_clean_all (gimage); + + gimp_create_display (gimp, gimage, 0x0101); + + g_object_unref (gimage); + + return gimage; +} diff --git a/app/core/gimptemplate.h b/app/core/gimptemplate.h new file mode 100644 index 0000000000..49584b92a5 --- /dev/null +++ b/app/core/gimptemplate.h @@ -0,0 +1,76 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis + * + * gimptemplate.h + * Copyright (C) 2003 Michael Natterer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_TEMPLATE_H__ +#define __GIMP_TEMPLATE_H__ + + +#include "gimpviewable.h" + + +#define GIMP_TYPE_TEMPLATE (gimp_template_get_type ()) +#define GIMP_TEMPLATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_TEMPLATE, GimpTemplate)) +#define GIMP_TEMPLATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_TEMPLATE, GimpTemplateClass)) +#define GIMP_IS_TEMPLATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_TEMPLATE)) +#define GIMP_IS_TEMPLATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_TEMPLATE)) +#define GIMP_TEMPLATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_TEMPLATE, GimpTemplateClass)) + + +typedef struct _GimpTemplateClass GimpTemplateClass; + +struct _GimpTemplate +{ + GimpViewable parent_instance; + + gint width; + gint height; + GimpUnit unit; + + gdouble xresolution; + gdouble yresolution; + GimpUnit resolution_unit; + + GimpImageBaseType image_type; + GimpFillType fill_type; +}; + +struct _GimpTemplateClass +{ + GimpViewableClass parent_instance; +}; + + +GType gimp_template_get_type (void) G_GNUC_CONST; + +GimpTemplate * gimp_template_new (const gchar *name); + +void gimp_template_set_from_config (GimpTemplate *template, + GimpCoreConfig *config); +void gimp_template_set_from_image (GimpTemplate *template, + GimpImage *gimage); + +gsize gimp_template_calc_memsize (GimpTemplate *values); + +GimpImage * gimp_template_create_image (Gimp *gimp, + GimpTemplate *template); + + +#endif /* __GIMP_TEMPLATE__ */ diff --git a/app/dialogs/image-new-dialog.c b/app/dialogs/image-new-dialog.c index ee41c510d2..34492f64c5 100644 --- a/app/dialogs/image-new-dialog.c +++ b/app/dialogs/image-new-dialog.c @@ -18,6 +18,8 @@ #include "config.h" +#include + #include #include "libgimpmath/gimpmath.h" @@ -26,13 +28,16 @@ #include "gui-types.h" +#include "config/gimpconfig-utils.h" #include "config/gimpguiconfig.h" #include "core/gimp.h" #include "core/gimpimage.h" #include "core/gimpimage-new.h" +#include "core/gimptemplate.h" -#include "widgets/gimpenummenu.h" +#include "widgets/gimpcontainermenuimpl.h" +#include "widgets/gimppropwidgets.h" #include "widgets/gimpviewabledialog.h" #include "file-new-dialog.h" @@ -45,43 +50,41 @@ typedef struct { - GtkWidget *dialog; + GtkWidget *dialog; + GtkWidget *confirm_dialog; - GtkWidget *confirm_dialog; + GtkWidget *option_menu; + GtkWidget *container_menu; - GtkWidget *size_se; - GtkWidget *memsize_label; - GtkWidget *resolution_se; - GtkWidget *couple_resolutions; + GtkWidget *size_se; + GtkWidget *memsize_label; + GtkWidget *resolution_se; + GtkWidget *couple_resolutions; - GtkWidget *type_w; - GtkWidget *fill_type_w; + GimpTemplate *template; + gdouble size; - GimpImageNewValues *values; - gdouble size; - - Gimp *gimp; + Gimp *gimp; } NewImageInfo; /* local function prototypes */ -static void file_new_confirm_dialog (NewImageInfo *info); +static void file_new_confirm_dialog (NewImageInfo *info); -static void file_new_ok_callback (GtkWidget *widget, - gpointer data); -static void file_new_reset_callback (GtkWidget *widget, - gpointer data); -static void file_new_cancel_callback (GtkWidget *widget, - gpointer data); -static void file_new_resolution_callback (GtkWidget *widget, - gpointer data); -static void file_new_image_type_callback (GtkWidget *widget, - gpointer data); -static void file_new_fill_type_callback (GtkWidget *widget, - gpointer data); -static void file_new_image_size_callback (GtkWidget *widget, - gpointer data); +static void file_new_ok_callback (GtkWidget *widget, + NewImageInfo *info); +static void file_new_cancel_callback (GtkWidget *widget, + NewImageInfo *info); +static void file_new_reset_callback (GtkWidget *widget, + NewImageInfo *info); +static void file_new_template_notify (GimpTemplate *template, + GParamSpec *param_spec, + NewImageInfo *info); +static void file_new_template_select (GimpContainerMenu *menu, + GimpViewable *object, + gpointer insert_data, + NewImageInfo *info); /* public functions */ @@ -104,12 +107,16 @@ file_new_dialog_create (Gimp *gimp, GtkWidget *spinbutton2; g_return_if_fail (GIMP_IS_GIMP (gimp)); - g_return_if_fail (! gimage || GIMP_IS_IMAGE (gimage)); + g_return_if_fail (gimage == NULL || GIMP_IS_IMAGE (gimage)); info = g_new0 (NewImageInfo, 1); - info->gimp = gimp; - info->values = gimp_image_new_values_new (gimp, gimage); + info->gimp = gimp; + info->template = gimp_image_new_template_new (gimp, gimage); + + g_signal_connect (info->template, "notify", + G_CALLBACK (file_new_template_notify), + info); info->dialog = gimp_viewable_dialog_new (NULL, @@ -139,6 +146,32 @@ file_new_dialog_create (Gimp *gimp, main_vbox, TRUE, TRUE, 0); gtk_widget_show (main_vbox); + hbox = gtk_hbox_new (FALSE, 4); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new_with_mnemonic (_("From _Template:")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + info->option_menu = gtk_option_menu_new (); + gtk_box_pack_start (GTK_BOX (hbox), info->option_menu, TRUE, TRUE, 0); + gtk_widget_show (info->option_menu); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), info->option_menu); + + info->container_menu = gimp_container_menu_new (gimp->templates, NULL, 16); + gtk_option_menu_set_menu (GTK_OPTION_MENU (info->option_menu), + info->container_menu); + gtk_widget_show (info->container_menu); + + gimp_container_menu_select_item (GIMP_CONTAINER_MENU (info->container_menu), + NULL); + + g_signal_connect (info->container_menu, "select_item", + G_CALLBACK (file_new_template_select), + info); + /* Image size frame */ frame = gtk_frame_new (_("Image Size")); gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); @@ -194,7 +227,7 @@ file_new_dialog_create (Gimp *gimp, gtk_table_attach_defaults (GTK_TABLE (table), abox, 1, 2, 3, 5); gtk_widget_show (abox); - info->size_se = gimp_size_entry_new (0, info->values->unit, "%a", + info->size_se = gimp_size_entry_new (0, info->template->unit, "%a", FALSE, FALSE, TRUE, SB_WIDTH, GIMP_SIZE_ENTRY_UPDATE_SIZE); gtk_table_set_col_spacing (GTK_TABLE (info->size_se), 1, 4); @@ -268,32 +301,11 @@ file_new_dialog_create (Gimp *gimp, GTK_SPIN_BUTTON (spinbutton2)); /* initialize the sizeentry */ - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 0, - info->values->xresolution, FALSE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 1, - info->values->yresolution, FALSE); - - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (info->size_se), 0, - GIMP_MIN_IMAGE_SIZE, - GIMP_MAX_IMAGE_SIZE); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (info->size_se), 1, - GIMP_MIN_IMAGE_SIZE, - GIMP_MAX_IMAGE_SIZE); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->size_se), 0, - info->values->width); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->size_se), 1, - info->values->height); - - g_signal_connect (info->size_se, "refval_changed", - G_CALLBACK (file_new_image_size_callback), - info); - g_signal_connect (info->size_se, "value_changed", - G_CALLBACK (file_new_image_size_callback), - info); - - /* initialize the size label */ - file_new_image_size_callback (info->size_se, info); + gimp_prop_size_entry_connect (G_OBJECT (info->template), + "width", "height", "unit", + info->size_se, NULL, + info->template->xresolution, + info->template->yresolution); /* the resolution labels */ label = gtk_label_new (_("Resolution X:")); @@ -318,11 +330,10 @@ file_new_dialog_create (Gimp *gimp, 1, 2); gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), SB_WIDTH); - info->resolution_se = - gimp_size_entry_new (1, gimp->config->default_resolution_unit, - _("pixels/%a"), - FALSE, FALSE, FALSE, SB_WIDTH, - GIMP_SIZE_ENTRY_UPDATE_RESOLUTION); + info->resolution_se = gimp_size_entry_new (1, info->template->resolution_unit, + _("pixels/%a"), + FALSE, FALSE, FALSE, SB_WIDTH, + GIMP_SIZE_ENTRY_UPDATE_RESOLUTION); gtk_table_set_col_spacing (GTK_TABLE (info->resolution_se), 1, 2); gtk_table_set_col_spacing (GTK_TABLE (info->resolution_se), 2, 2); gtk_table_set_row_spacing (GTK_TABLE (info->resolution_se), 0, 2); @@ -333,66 +344,40 @@ file_new_dialog_create (Gimp *gimp, 1, 2, 0, 1); gtk_widget_show (spinbutton); - gtk_container_add (GTK_CONTAINER (abox), info->resolution_se); + gtk_container_add (GTK_CONTAINER (abox), info->resolution_se); gtk_widget_show (info->resolution_se); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (info->resolution_se), - 0, GIMP_MIN_RESOLUTION, - GIMP_MAX_RESOLUTION); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (info->resolution_se), - 1, GIMP_MIN_RESOLUTION, - GIMP_MAX_RESOLUTION); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->resolution_se), 0, - info->values->xresolution); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->resolution_se), 1, - info->values->yresolution); - - g_signal_connect (info->resolution_se, "value_changed", - G_CALLBACK (file_new_resolution_callback), - info); - /* the resolution chainbutton */ info->couple_resolutions = gimp_chain_button_new (GIMP_CHAIN_RIGHT); - gimp_chain_button_set_active - (GIMP_CHAIN_BUTTON (info->couple_resolutions), - ABS (info->values->xresolution - info->values->yresolution) - < GIMP_MIN_RESOLUTION); gtk_table_attach_defaults (GTK_TABLE (info->resolution_se), info->couple_resolutions, 2, 3, 0, 2); gtk_widget_show (info->couple_resolutions); + gimp_prop_size_entry_connect (G_OBJECT (info->template), + "xresolution", "yresolution", + "resolution-unit", + info->resolution_se, + info->couple_resolutions, + 1.0, 1.0); + /* hbox containing the Image type and fill type frames */ hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); /* frame for Image Type */ - frame = gimp_enum_radio_frame_new_with_range (GIMP_TYPE_IMAGE_BASE_TYPE, - GIMP_RGB, GIMP_GRAY, - gtk_label_new (_("Image Type")), - 2, - G_CALLBACK (file_new_image_type_callback), - info, - &info->type_w); - gimp_radio_group_set_active (GTK_RADIO_BUTTON (info->type_w), - GINT_TO_POINTER (info->values->type)); - + frame = gimp_prop_enum_radio_frame_new (G_OBJECT (info->template), + "image-type", + _("Image Type"), + GIMP_RGB, GIMP_GRAY); gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); /* frame for Fill Type */ - frame = gimp_enum_radio_frame_new_with_range (GIMP_TYPE_FILL_TYPE, - GIMP_FOREGROUND_FILL, - GIMP_TRANSPARENT_FILL, - gtk_label_new (_("Fill Type")), - 2, - G_CALLBACK (file_new_fill_type_callback), - info, - &info->fill_type_w); - gimp_radio_group_set_active (GTK_RADIO_BUTTON (info->fill_type_w), - GINT_TO_POINTER (info->values->fill_type)); - + frame = gimp_prop_enum_radio_frame_new (G_OBJECT (info->template), + "fill-type", + _("Fill Type"), + -1, -1); gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); @@ -405,33 +390,9 @@ file_new_dialog_create (Gimp *gimp, /* private functions */ static void -file_new_ok_callback (GtkWidget *widget, - gpointer data) +file_new_ok_callback (GtkWidget *widget, + NewImageInfo *info) { - NewImageInfo *info; - GimpImageNewValues *values; - - info = (NewImageInfo*) data; - values = info->values; - - /* get the image size in pixels */ - values->width = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->size_se), 0)); - values->height = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->size_se), 1)); - - /* get the resolution in dpi */ - values->xresolution = - gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->resolution_se), 0); - values->yresolution = - gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->resolution_se), 1); - - /* get the units */ - values->unit = - gimp_size_entry_get_unit (GIMP_SIZE_ENTRY (info->size_se)); - values->res_unit = - gimp_size_entry_get_unit (GIMP_SIZE_ENTRY (info->resolution_se)); - if (info->size > GIMP_GUI_CONFIG (info->gimp->config)->max_new_image_size) { file_new_confirm_dialog (info); @@ -439,72 +400,41 @@ file_new_ok_callback (GtkWidget *widget, else { gtk_widget_destroy (info->dialog); - gimp_image_new_create_image (info->gimp, values); - gimp_image_new_values_free (values); + gimp_image_new_create_image (info->gimp, info->template); + g_object_unref (info->template); g_free (info); } } static void -file_new_reset_callback (GtkWidget *widget, - gpointer data) +file_new_cancel_callback (GtkWidget *widget, + NewImageInfo *info) { - NewImageInfo *info; - GimpCoreConfig *config; - - info = (NewImageInfo *) data; - - config = info->gimp->config; - - g_signal_handlers_block_by_func (info->resolution_se, - file_new_resolution_callback, - info); - - gimp_chain_button_set_active - (GIMP_CHAIN_BUTTON (info->couple_resolutions), - ABS (config->default_xresolution - - config->default_yresolution) < GIMP_MIN_RESOLUTION); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->resolution_se), 0, - config->default_xresolution); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->resolution_se), 1, - config->default_yresolution); - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (info->resolution_se), - config->default_resolution_unit); - - g_signal_handlers_unblock_by_func (info->resolution_se, - file_new_resolution_callback, - info); - - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 0, - config->default_xresolution, TRUE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 1, - config->default_yresolution, TRUE); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->size_se), 0, - config->default_image_width); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->size_se), 1, - config->default_image_height); - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (info->size_se), - config->default_unit); - - gimp_radio_group_set_active (GTK_RADIO_BUTTON (info->type_w), - GINT_TO_POINTER (config->default_image_type)); - - gimp_radio_group_set_active (GTK_RADIO_BUTTON (info->fill_type_w), - GINT_TO_POINTER (GIMP_BACKGROUND_FILL)); + gtk_widget_destroy (info->dialog); + g_object_unref (info->template); + g_free (info); } static void -file_new_cancel_callback (GtkWidget *widget, - gpointer data) +file_new_reset_callback (GtkWidget *widget, + NewImageInfo *info) { - NewImageInfo *info; + gint width; + gint height; - info = (NewImageInfo*) data; + width = info->gimp->config->default_image_width; + height = info->gimp->config->default_image_height; - gtk_widget_destroy (info->dialog); - gimp_image_new_values_free (info->values); - g_free (info); + gimp_template_set_from_config (info->template, info->gimp->config); + + g_object_set (info->template, + "width", width, + "height", height, + "fill-type", GIMP_BACKGROUND_FILL, + NULL); + + gimp_container_menu_select_item (GIMP_CONTAINER_MENU (info->container_menu), + NULL); } /* local callback of file_new_confirm_dialog() */ @@ -513,17 +443,15 @@ file_new_confirm_dialog_callback (GtkWidget *widget, gboolean create, gpointer data) { - NewImageInfo *info; - - info = (NewImageInfo*) data; + NewImageInfo *info = (NewImageInfo*) data; info->confirm_dialog = NULL; if (create) { gtk_widget_destroy (info->dialog); - gimp_image_new_create_image (info->gimp, info->values); - gimp_image_new_values_free (info->values); + gimp_image_new_create_image (info->gimp, info->template); + g_object_unref (info->template); g_free (info); } else @@ -542,8 +470,6 @@ file_new_confirm_dialog (NewImageInfo *info) size = gimp_image_new_get_memsize_string (info->size); max_size = gimp_image_new_get_memsize_string (GIMP_GUI_CONFIG (info->gimp->config)->max_new_image_size); - /* xgettext:no-c-format */ - text = g_strdup_printf (_("You are trying to create an image with\n" "an initial size of %s.\n\n" "Choose OK to create this image anyway.\n" @@ -579,103 +505,50 @@ file_new_confirm_dialog (NewImageInfo *info) } static void -file_new_resolution_callback (GtkWidget *widget, - gpointer data) +file_new_template_notify (GimpTemplate *template, + GParamSpec *param_spec, + NewImageInfo *info) { - NewImageInfo *info; + gchar *text; - static gdouble xres = 0.0; - static gdouble yres = 0.0; - gdouble new_xres; - gdouble new_yres; - - info = (NewImageInfo *) data; - - new_xres = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 0); - new_yres = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 1); - - if (gimp_chain_button_get_active - (GIMP_CHAIN_BUTTON (info->couple_resolutions))) + if (! strcmp (param_spec->name, "xresolution")) { - g_signal_handlers_block_by_func (info->resolution_se, - file_new_resolution_callback, - info); - - if (new_xres != xres) - { - yres = new_yres = xres = new_xres; - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (widget), 1, yres); - } - - if (new_yres != yres) - { - xres = new_xres = yres = new_yres; - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (widget), 0, xres); - } - - g_signal_handlers_unblock_by_func (info->resolution_se, - file_new_resolution_callback, - info); + gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 0, + template->xresolution, FALSE); } - else + else if (! strcmp (param_spec->name, "yresolution")) { - if (new_xres != xres) - xres = new_xres; - if (new_yres != yres) - yres = new_yres; + gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 1, + template->yresolution, FALSE); } - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 0, - xres, FALSE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 1, - yres, FALSE); - - file_new_image_size_callback (widget, data); -} - -static void -file_new_image_type_callback (GtkWidget *widget, - gpointer data) -{ - NewImageInfo *info; - - info = (NewImageInfo*) data; - - gimp_radio_button_update (widget, &info->values->type); - - file_new_image_size_callback (widget, data); -} - -static void -file_new_fill_type_callback (GtkWidget *widget, - gpointer data) -{ - NewImageInfo *info; - - info = (NewImageInfo*) data; - - gimp_radio_button_update (widget, &info->values->fill_type); - - file_new_image_size_callback (widget, data); -} - -static void -file_new_image_size_callback (GtkWidget *widget, - gpointer data) -{ - NewImageInfo *info; - gchar *text; - - info = (NewImageInfo*) data; - - info->values->width = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->size_se), 0)); - info->values->height = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->size_se), 1)); - - info->size = gimp_image_new_calculate_memsize (info->values); + info->size = gimp_template_calc_memsize (info->template); text = gimp_image_new_get_memsize_string (info->size); gtk_label_set_text (GTK_LABEL (info->memsize_label), text); g_free (text); } + +static void +file_new_template_select (GimpContainerMenu *menu, + GimpViewable *object, + gpointer insert_data, + NewImageInfo *info) +{ + if (object) + { + gint width; + gint height; + + width = GIMP_TEMPLATE (object)->width; + height = GIMP_TEMPLATE (object)->height; + + gimp_config_copy_properties (G_OBJECT (object), + G_OBJECT (info->template)); + + g_object_set (info->template, + "width", width, + "height", height, + NULL); + } +} diff --git a/app/gui/file-commands.c b/app/gui/file-commands.c index df3a46177b..fae97ed6b9 100644 --- a/app/gui/file-commands.c +++ b/app/gui/file-commands.c @@ -18,6 +18,8 @@ #include "config.h" +#include + #include #include "libgimpwidgets/gimpwidgets.h" @@ -31,7 +33,7 @@ #include "core/gimpcontext.h" #include "core/gimpimage.h" #include "core/gimpimage-undo.h" -#include "core/gimpobject.h" +#include "core/gimptemplate.h" #include "file/file-open.h" #include "file/file-save.h" @@ -77,6 +79,9 @@ /* local function prototypes */ +static void file_new_template_callback (GtkWidget *widget, + gchar *name, + gpointer data); static void file_revert_confirm_callback (GtkWidget *widget, gboolean revert, gpointer data); @@ -264,6 +269,25 @@ file_save_a_copy_cmd_callback (GtkWidget *widget, file_save_a_copy_dialog_show (gdisp->gimage, global_menu_factory); } +void +file_save_template_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GimpDisplay *gdisp; + GtkWidget *qbox; + return_if_no_display (gdisp, data); + + qbox = gimp_query_string_box (_("Create New Template"), + gimp_standard_help_func, + "dialogs/new_template.html", + _("Enter a name for this template"), + NULL, + G_OBJECT (gdisp->gimage), "disconnect", + file_new_template_callback, gdisp->gimage); + gtk_widget_show (qbox); +} + void file_revert_cmd_callback (GtkWidget *widget, gpointer data, @@ -354,8 +378,30 @@ file_file_open_dialog (Gimp *gimp, file_open_dialog_show (gimp, NULL, uri, global_menu_factory); } + /* private functions */ +static void +file_new_template_callback (GtkWidget *widget, + gchar *name, + gpointer data) +{ + GimpTemplate *template; + GimpImage *gimage; + + gimage = (GimpImage *) data; + + if (! (name && strlen (name))) + name = _("(Unnamed Template)"); + + template = gimp_template_new (name); + gimp_template_set_from_image (template, gimage); + + gimp_container_add (gimage->gimp->templates, + GIMP_OBJECT (template)); + g_object_unref (template); +} + static void file_revert_confirm_callback (GtkWidget *widget, gboolean revert, diff --git a/app/gui/file-commands.h b/app/gui/file-commands.h index b2ad508d82..6f04b95437 100644 --- a/app/gui/file-commands.h +++ b/app/gui/file-commands.h @@ -52,6 +52,9 @@ void file_save_as_cmd_callback (GtkWidget *widget, void file_save_a_copy_cmd_callback (GtkWidget *widget, gpointer data, guint action); +void file_save_template_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); void file_revert_cmd_callback (GtkWidget *widget, gpointer data, diff --git a/app/gui/file-new-dialog.c b/app/gui/file-new-dialog.c index ee41c510d2..34492f64c5 100644 --- a/app/gui/file-new-dialog.c +++ b/app/gui/file-new-dialog.c @@ -18,6 +18,8 @@ #include "config.h" +#include + #include #include "libgimpmath/gimpmath.h" @@ -26,13 +28,16 @@ #include "gui-types.h" +#include "config/gimpconfig-utils.h" #include "config/gimpguiconfig.h" #include "core/gimp.h" #include "core/gimpimage.h" #include "core/gimpimage-new.h" +#include "core/gimptemplate.h" -#include "widgets/gimpenummenu.h" +#include "widgets/gimpcontainermenuimpl.h" +#include "widgets/gimppropwidgets.h" #include "widgets/gimpviewabledialog.h" #include "file-new-dialog.h" @@ -45,43 +50,41 @@ typedef struct { - GtkWidget *dialog; + GtkWidget *dialog; + GtkWidget *confirm_dialog; - GtkWidget *confirm_dialog; + GtkWidget *option_menu; + GtkWidget *container_menu; - GtkWidget *size_se; - GtkWidget *memsize_label; - GtkWidget *resolution_se; - GtkWidget *couple_resolutions; + GtkWidget *size_se; + GtkWidget *memsize_label; + GtkWidget *resolution_se; + GtkWidget *couple_resolutions; - GtkWidget *type_w; - GtkWidget *fill_type_w; + GimpTemplate *template; + gdouble size; - GimpImageNewValues *values; - gdouble size; - - Gimp *gimp; + Gimp *gimp; } NewImageInfo; /* local function prototypes */ -static void file_new_confirm_dialog (NewImageInfo *info); +static void file_new_confirm_dialog (NewImageInfo *info); -static void file_new_ok_callback (GtkWidget *widget, - gpointer data); -static void file_new_reset_callback (GtkWidget *widget, - gpointer data); -static void file_new_cancel_callback (GtkWidget *widget, - gpointer data); -static void file_new_resolution_callback (GtkWidget *widget, - gpointer data); -static void file_new_image_type_callback (GtkWidget *widget, - gpointer data); -static void file_new_fill_type_callback (GtkWidget *widget, - gpointer data); -static void file_new_image_size_callback (GtkWidget *widget, - gpointer data); +static void file_new_ok_callback (GtkWidget *widget, + NewImageInfo *info); +static void file_new_cancel_callback (GtkWidget *widget, + NewImageInfo *info); +static void file_new_reset_callback (GtkWidget *widget, + NewImageInfo *info); +static void file_new_template_notify (GimpTemplate *template, + GParamSpec *param_spec, + NewImageInfo *info); +static void file_new_template_select (GimpContainerMenu *menu, + GimpViewable *object, + gpointer insert_data, + NewImageInfo *info); /* public functions */ @@ -104,12 +107,16 @@ file_new_dialog_create (Gimp *gimp, GtkWidget *spinbutton2; g_return_if_fail (GIMP_IS_GIMP (gimp)); - g_return_if_fail (! gimage || GIMP_IS_IMAGE (gimage)); + g_return_if_fail (gimage == NULL || GIMP_IS_IMAGE (gimage)); info = g_new0 (NewImageInfo, 1); - info->gimp = gimp; - info->values = gimp_image_new_values_new (gimp, gimage); + info->gimp = gimp; + info->template = gimp_image_new_template_new (gimp, gimage); + + g_signal_connect (info->template, "notify", + G_CALLBACK (file_new_template_notify), + info); info->dialog = gimp_viewable_dialog_new (NULL, @@ -139,6 +146,32 @@ file_new_dialog_create (Gimp *gimp, main_vbox, TRUE, TRUE, 0); gtk_widget_show (main_vbox); + hbox = gtk_hbox_new (FALSE, 4); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new_with_mnemonic (_("From _Template:")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + info->option_menu = gtk_option_menu_new (); + gtk_box_pack_start (GTK_BOX (hbox), info->option_menu, TRUE, TRUE, 0); + gtk_widget_show (info->option_menu); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), info->option_menu); + + info->container_menu = gimp_container_menu_new (gimp->templates, NULL, 16); + gtk_option_menu_set_menu (GTK_OPTION_MENU (info->option_menu), + info->container_menu); + gtk_widget_show (info->container_menu); + + gimp_container_menu_select_item (GIMP_CONTAINER_MENU (info->container_menu), + NULL); + + g_signal_connect (info->container_menu, "select_item", + G_CALLBACK (file_new_template_select), + info); + /* Image size frame */ frame = gtk_frame_new (_("Image Size")); gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); @@ -194,7 +227,7 @@ file_new_dialog_create (Gimp *gimp, gtk_table_attach_defaults (GTK_TABLE (table), abox, 1, 2, 3, 5); gtk_widget_show (abox); - info->size_se = gimp_size_entry_new (0, info->values->unit, "%a", + info->size_se = gimp_size_entry_new (0, info->template->unit, "%a", FALSE, FALSE, TRUE, SB_WIDTH, GIMP_SIZE_ENTRY_UPDATE_SIZE); gtk_table_set_col_spacing (GTK_TABLE (info->size_se), 1, 4); @@ -268,32 +301,11 @@ file_new_dialog_create (Gimp *gimp, GTK_SPIN_BUTTON (spinbutton2)); /* initialize the sizeentry */ - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 0, - info->values->xresolution, FALSE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 1, - info->values->yresolution, FALSE); - - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (info->size_se), 0, - GIMP_MIN_IMAGE_SIZE, - GIMP_MAX_IMAGE_SIZE); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (info->size_se), 1, - GIMP_MIN_IMAGE_SIZE, - GIMP_MAX_IMAGE_SIZE); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->size_se), 0, - info->values->width); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->size_se), 1, - info->values->height); - - g_signal_connect (info->size_se, "refval_changed", - G_CALLBACK (file_new_image_size_callback), - info); - g_signal_connect (info->size_se, "value_changed", - G_CALLBACK (file_new_image_size_callback), - info); - - /* initialize the size label */ - file_new_image_size_callback (info->size_se, info); + gimp_prop_size_entry_connect (G_OBJECT (info->template), + "width", "height", "unit", + info->size_se, NULL, + info->template->xresolution, + info->template->yresolution); /* the resolution labels */ label = gtk_label_new (_("Resolution X:")); @@ -318,11 +330,10 @@ file_new_dialog_create (Gimp *gimp, 1, 2); gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), SB_WIDTH); - info->resolution_se = - gimp_size_entry_new (1, gimp->config->default_resolution_unit, - _("pixels/%a"), - FALSE, FALSE, FALSE, SB_WIDTH, - GIMP_SIZE_ENTRY_UPDATE_RESOLUTION); + info->resolution_se = gimp_size_entry_new (1, info->template->resolution_unit, + _("pixels/%a"), + FALSE, FALSE, FALSE, SB_WIDTH, + GIMP_SIZE_ENTRY_UPDATE_RESOLUTION); gtk_table_set_col_spacing (GTK_TABLE (info->resolution_se), 1, 2); gtk_table_set_col_spacing (GTK_TABLE (info->resolution_se), 2, 2); gtk_table_set_row_spacing (GTK_TABLE (info->resolution_se), 0, 2); @@ -333,66 +344,40 @@ file_new_dialog_create (Gimp *gimp, 1, 2, 0, 1); gtk_widget_show (spinbutton); - gtk_container_add (GTK_CONTAINER (abox), info->resolution_se); + gtk_container_add (GTK_CONTAINER (abox), info->resolution_se); gtk_widget_show (info->resolution_se); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (info->resolution_se), - 0, GIMP_MIN_RESOLUTION, - GIMP_MAX_RESOLUTION); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (info->resolution_se), - 1, GIMP_MIN_RESOLUTION, - GIMP_MAX_RESOLUTION); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->resolution_se), 0, - info->values->xresolution); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->resolution_se), 1, - info->values->yresolution); - - g_signal_connect (info->resolution_se, "value_changed", - G_CALLBACK (file_new_resolution_callback), - info); - /* the resolution chainbutton */ info->couple_resolutions = gimp_chain_button_new (GIMP_CHAIN_RIGHT); - gimp_chain_button_set_active - (GIMP_CHAIN_BUTTON (info->couple_resolutions), - ABS (info->values->xresolution - info->values->yresolution) - < GIMP_MIN_RESOLUTION); gtk_table_attach_defaults (GTK_TABLE (info->resolution_se), info->couple_resolutions, 2, 3, 0, 2); gtk_widget_show (info->couple_resolutions); + gimp_prop_size_entry_connect (G_OBJECT (info->template), + "xresolution", "yresolution", + "resolution-unit", + info->resolution_se, + info->couple_resolutions, + 1.0, 1.0); + /* hbox containing the Image type and fill type frames */ hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); /* frame for Image Type */ - frame = gimp_enum_radio_frame_new_with_range (GIMP_TYPE_IMAGE_BASE_TYPE, - GIMP_RGB, GIMP_GRAY, - gtk_label_new (_("Image Type")), - 2, - G_CALLBACK (file_new_image_type_callback), - info, - &info->type_w); - gimp_radio_group_set_active (GTK_RADIO_BUTTON (info->type_w), - GINT_TO_POINTER (info->values->type)); - + frame = gimp_prop_enum_radio_frame_new (G_OBJECT (info->template), + "image-type", + _("Image Type"), + GIMP_RGB, GIMP_GRAY); gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); /* frame for Fill Type */ - frame = gimp_enum_radio_frame_new_with_range (GIMP_TYPE_FILL_TYPE, - GIMP_FOREGROUND_FILL, - GIMP_TRANSPARENT_FILL, - gtk_label_new (_("Fill Type")), - 2, - G_CALLBACK (file_new_fill_type_callback), - info, - &info->fill_type_w); - gimp_radio_group_set_active (GTK_RADIO_BUTTON (info->fill_type_w), - GINT_TO_POINTER (info->values->fill_type)); - + frame = gimp_prop_enum_radio_frame_new (G_OBJECT (info->template), + "fill-type", + _("Fill Type"), + -1, -1); gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); @@ -405,33 +390,9 @@ file_new_dialog_create (Gimp *gimp, /* private functions */ static void -file_new_ok_callback (GtkWidget *widget, - gpointer data) +file_new_ok_callback (GtkWidget *widget, + NewImageInfo *info) { - NewImageInfo *info; - GimpImageNewValues *values; - - info = (NewImageInfo*) data; - values = info->values; - - /* get the image size in pixels */ - values->width = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->size_se), 0)); - values->height = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->size_se), 1)); - - /* get the resolution in dpi */ - values->xresolution = - gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->resolution_se), 0); - values->yresolution = - gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->resolution_se), 1); - - /* get the units */ - values->unit = - gimp_size_entry_get_unit (GIMP_SIZE_ENTRY (info->size_se)); - values->res_unit = - gimp_size_entry_get_unit (GIMP_SIZE_ENTRY (info->resolution_se)); - if (info->size > GIMP_GUI_CONFIG (info->gimp->config)->max_new_image_size) { file_new_confirm_dialog (info); @@ -439,72 +400,41 @@ file_new_ok_callback (GtkWidget *widget, else { gtk_widget_destroy (info->dialog); - gimp_image_new_create_image (info->gimp, values); - gimp_image_new_values_free (values); + gimp_image_new_create_image (info->gimp, info->template); + g_object_unref (info->template); g_free (info); } } static void -file_new_reset_callback (GtkWidget *widget, - gpointer data) +file_new_cancel_callback (GtkWidget *widget, + NewImageInfo *info) { - NewImageInfo *info; - GimpCoreConfig *config; - - info = (NewImageInfo *) data; - - config = info->gimp->config; - - g_signal_handlers_block_by_func (info->resolution_se, - file_new_resolution_callback, - info); - - gimp_chain_button_set_active - (GIMP_CHAIN_BUTTON (info->couple_resolutions), - ABS (config->default_xresolution - - config->default_yresolution) < GIMP_MIN_RESOLUTION); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->resolution_se), 0, - config->default_xresolution); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->resolution_se), 1, - config->default_yresolution); - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (info->resolution_se), - config->default_resolution_unit); - - g_signal_handlers_unblock_by_func (info->resolution_se, - file_new_resolution_callback, - info); - - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 0, - config->default_xresolution, TRUE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 1, - config->default_yresolution, TRUE); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->size_se), 0, - config->default_image_width); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (info->size_se), 1, - config->default_image_height); - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (info->size_se), - config->default_unit); - - gimp_radio_group_set_active (GTK_RADIO_BUTTON (info->type_w), - GINT_TO_POINTER (config->default_image_type)); - - gimp_radio_group_set_active (GTK_RADIO_BUTTON (info->fill_type_w), - GINT_TO_POINTER (GIMP_BACKGROUND_FILL)); + gtk_widget_destroy (info->dialog); + g_object_unref (info->template); + g_free (info); } static void -file_new_cancel_callback (GtkWidget *widget, - gpointer data) +file_new_reset_callback (GtkWidget *widget, + NewImageInfo *info) { - NewImageInfo *info; + gint width; + gint height; - info = (NewImageInfo*) data; + width = info->gimp->config->default_image_width; + height = info->gimp->config->default_image_height; - gtk_widget_destroy (info->dialog); - gimp_image_new_values_free (info->values); - g_free (info); + gimp_template_set_from_config (info->template, info->gimp->config); + + g_object_set (info->template, + "width", width, + "height", height, + "fill-type", GIMP_BACKGROUND_FILL, + NULL); + + gimp_container_menu_select_item (GIMP_CONTAINER_MENU (info->container_menu), + NULL); } /* local callback of file_new_confirm_dialog() */ @@ -513,17 +443,15 @@ file_new_confirm_dialog_callback (GtkWidget *widget, gboolean create, gpointer data) { - NewImageInfo *info; - - info = (NewImageInfo*) data; + NewImageInfo *info = (NewImageInfo*) data; info->confirm_dialog = NULL; if (create) { gtk_widget_destroy (info->dialog); - gimp_image_new_create_image (info->gimp, info->values); - gimp_image_new_values_free (info->values); + gimp_image_new_create_image (info->gimp, info->template); + g_object_unref (info->template); g_free (info); } else @@ -542,8 +470,6 @@ file_new_confirm_dialog (NewImageInfo *info) size = gimp_image_new_get_memsize_string (info->size); max_size = gimp_image_new_get_memsize_string (GIMP_GUI_CONFIG (info->gimp->config)->max_new_image_size); - /* xgettext:no-c-format */ - text = g_strdup_printf (_("You are trying to create an image with\n" "an initial size of %s.\n\n" "Choose OK to create this image anyway.\n" @@ -579,103 +505,50 @@ file_new_confirm_dialog (NewImageInfo *info) } static void -file_new_resolution_callback (GtkWidget *widget, - gpointer data) +file_new_template_notify (GimpTemplate *template, + GParamSpec *param_spec, + NewImageInfo *info) { - NewImageInfo *info; + gchar *text; - static gdouble xres = 0.0; - static gdouble yres = 0.0; - gdouble new_xres; - gdouble new_yres; - - info = (NewImageInfo *) data; - - new_xres = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 0); - new_yres = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 1); - - if (gimp_chain_button_get_active - (GIMP_CHAIN_BUTTON (info->couple_resolutions))) + if (! strcmp (param_spec->name, "xresolution")) { - g_signal_handlers_block_by_func (info->resolution_se, - file_new_resolution_callback, - info); - - if (new_xres != xres) - { - yres = new_yres = xres = new_xres; - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (widget), 1, yres); - } - - if (new_yres != yres) - { - xres = new_xres = yres = new_yres; - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (widget), 0, xres); - } - - g_signal_handlers_unblock_by_func (info->resolution_se, - file_new_resolution_callback, - info); + gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 0, + template->xresolution, FALSE); } - else + else if (! strcmp (param_spec->name, "yresolution")) { - if (new_xres != xres) - xres = new_xres; - if (new_yres != yres) - yres = new_yres; + gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 1, + template->yresolution, FALSE); } - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 0, - xres, FALSE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (info->size_se), 1, - yres, FALSE); - - file_new_image_size_callback (widget, data); -} - -static void -file_new_image_type_callback (GtkWidget *widget, - gpointer data) -{ - NewImageInfo *info; - - info = (NewImageInfo*) data; - - gimp_radio_button_update (widget, &info->values->type); - - file_new_image_size_callback (widget, data); -} - -static void -file_new_fill_type_callback (GtkWidget *widget, - gpointer data) -{ - NewImageInfo *info; - - info = (NewImageInfo*) data; - - gimp_radio_button_update (widget, &info->values->fill_type); - - file_new_image_size_callback (widget, data); -} - -static void -file_new_image_size_callback (GtkWidget *widget, - gpointer data) -{ - NewImageInfo *info; - gchar *text; - - info = (NewImageInfo*) data; - - info->values->width = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->size_se), 0)); - info->values->height = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (info->size_se), 1)); - - info->size = gimp_image_new_calculate_memsize (info->values); + info->size = gimp_template_calc_memsize (info->template); text = gimp_image_new_get_memsize_string (info->size); gtk_label_set_text (GTK_LABEL (info->memsize_label), text); g_free (text); } + +static void +file_new_template_select (GimpContainerMenu *menu, + GimpViewable *object, + gpointer insert_data, + NewImageInfo *info) +{ + if (object) + { + gint width; + gint height; + + width = GIMP_TEMPLATE (object)->width; + height = GIMP_TEMPLATE (object)->height; + + gimp_config_copy_properties (G_OBJECT (object), + G_OBJECT (info->template)); + + g_object_set (info->template, + "width", width, + "height", height, + NULL); + } +} diff --git a/app/gui/image-menu.c b/app/gui/image-menu.c index 48d3849309..67f1155b18 100644 --- a/app/gui/image-menu.c +++ b/app/gui/image-menu.c @@ -112,6 +112,10 @@ GimpItemFactoryEntry image_menu_entries[] = file_save_a_copy_cmd_callback, 0 }, NULL, "file/dialogs/file_save.html", NULL }, + { { N_("/File/Save as Template..."), NULL, + file_save_template_cmd_callback, 0 }, + NULL, + "file/dialogs/file_save.html", NULL }, { { N_("/File/Revert..."), NULL, file_revert_cmd_callback, 0, "", GTK_STOCK_REVERT_TO_SAVED }, diff --git a/app/menus/image-menu.c b/app/menus/image-menu.c index 48d3849309..67f1155b18 100644 --- a/app/menus/image-menu.c +++ b/app/menus/image-menu.c @@ -112,6 +112,10 @@ GimpItemFactoryEntry image_menu_entries[] = file_save_a_copy_cmd_callback, 0 }, NULL, "file/dialogs/file_save.html", NULL }, + { { N_("/File/Save as Template..."), NULL, + file_save_template_cmd_callback, 0 }, + NULL, + "file/dialogs/file_save.html", NULL }, { { N_("/File/Revert..."), NULL, file_revert_cmd_callback, 0, "", GTK_STOCK_REVERT_TO_SAVED }, diff --git a/app/widgets/gimpcontainermenuimpl.c b/app/widgets/gimpcontainermenuimpl.c index 8a628f303e..2108e1faf1 100644 --- a/app/widgets/gimpcontainermenuimpl.c +++ b/app/widgets/gimpcontainermenuimpl.c @@ -181,9 +181,6 @@ gimp_container_menu_impl_insert_item (GimpContainerMenu *menu, gtk_menu_reorder_child (GTK_MENU (menu), GIMP_CONTAINER_MENU_IMPL (menu)->empty_item, -1); - if (g_list_length (GTK_MENU_SHELL (menu)->children) == 2) - gtk_widget_hide (GIMP_CONTAINER_MENU_IMPL (menu)->empty_item); - return (gpointer) menu_item; } @@ -248,6 +245,7 @@ gimp_container_menu_impl_select_item (GimpContainerMenu *menu, gpointer insert_data) { GtkWidget *menu_item; + gint index; if (insert_data) menu_item = GTK_WIDGET (insert_data); @@ -256,11 +254,19 @@ gimp_container_menu_impl_select_item (GimpContainerMenu *menu, if (menu_item) { - gint index; + gtk_widget_hide (GIMP_CONTAINER_MENU_IMPL (menu)->empty_item); index = gimp_container_get_child_index (menu->container, GIMP_OBJECT (viewable)); + gimp_container_menu_impl_set_history (menu, index); + } + else + { + gtk_widget_show (GIMP_CONTAINER_MENU_IMPL (menu)->empty_item); + + index = gimp_container_num_children (menu->container); + gimp_container_menu_impl_set_history (menu, index); } } diff --git a/app/widgets/gimppropwidgets.c b/app/widgets/gimppropwidgets.c index 393ad841aa..521e08dba4 100644 --- a/app/widgets/gimppropwidgets.c +++ b/app/widgets/gimppropwidgets.c @@ -1644,30 +1644,79 @@ gimp_prop_coordinates_new (GObject *config, gdouble xresolution, gdouble yresolution, gboolean has_chainbutton) +{ + GtkWidget *sizeentry; + GtkWidget *chainbutton = NULL; + + sizeentry = gimp_size_entry_new (2, GIMP_UNIT_INCH, unit_format, + FALSE, FALSE, TRUE, 10, + update_policy); + + if (has_chainbutton) + { + chainbutton = gimp_chain_button_new (GIMP_CHAIN_BOTTOM); + + gtk_table_attach_defaults (GTK_TABLE (sizeentry), chainbutton, + 1, 3, 3, 4); + gtk_widget_show (chainbutton); + } + + if (! gimp_prop_size_entry_connect (config, + x_property_name, + y_property_name, + unit_property_name, + sizeentry, + chainbutton, + xresolution, + yresolution)) + { + gtk_widget_destroy (sizeentry); + return NULL; + } + + return sizeentry; +} + +gboolean +gimp_prop_size_entry_connect (GObject *config, + const gchar *x_property_name, + const gchar *y_property_name, + const gchar *unit_property_name, + GtkWidget *sizeentry, + GtkWidget *chainbutton, + gdouble xresolution, + gdouble yresolution) { GParamSpec *x_param_spec; GParamSpec *y_param_spec; GParamSpec *unit_param_spec; - GtkWidget *sizeentry; gdouble x_value; gdouble y_value; + gdouble *old_x_value; + gdouble *old_y_value; GimpUnit unit_value; gboolean chain_checked = FALSE; + g_return_val_if_fail (GIMP_IS_SIZE_ENTRY (sizeentry), FALSE); + g_return_val_if_fail (GIMP_SIZE_ENTRY (sizeentry)->number_of_fields == 2, + FALSE); + g_return_val_if_fail (chainbutton == NULL || + GIMP_IS_CHAIN_BUTTON (chainbutton), FALSE); + x_param_spec = find_param_spec (config, x_property_name, G_STRLOC); if (! x_param_spec) - return NULL; + return FALSE; y_param_spec = find_param_spec (config, y_property_name, G_STRLOC); if (! y_param_spec) - return NULL; + return FALSE; if (unit_property_name) { unit_param_spec = check_param_spec (config, unit_property_name, GIMP_TYPE_PARAM_UNIT, G_STRLOC); if (! unit_param_spec) - return NULL; + return FALSE; g_object_get (config, unit_property_name, &unit_value, @@ -1707,14 +1756,10 @@ gimp_prop_coordinates_new (GObject *config, " both int or both double", G_STRLOC, x_property_name, y_property_name, g_type_name (G_TYPE_FROM_INSTANCE (config))); - return NULL; + return FALSE; } - sizeentry = gimp_size_entry_new (2, unit_value, unit_format, - FALSE, FALSE, TRUE, 10, - update_policy); - - switch (update_policy) + switch (GIMP_SIZE_ENTRY (sizeentry)->update_policy) { case GIMP_SIZE_ENTRY_UPDATE_SIZE: gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 0, @@ -1760,19 +1805,24 @@ gimp_prop_coordinates_new (GObject *config, g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-unit", unit_param_spec); - if (has_chainbutton) + old_x_value = g_new0 (gdouble, 1); + *old_x_value = x_value; + g_object_set_data_full (G_OBJECT (sizeentry), "old-x-value", + old_x_value, + (GDestroyNotify) g_free); + + old_y_value = g_new0 (gdouble, 1); + *old_y_value = y_value; + g_object_set_data_full (G_OBJECT (sizeentry), "old-y-value", + old_y_value, + (GDestroyNotify) g_free); + + if (chainbutton) { - GtkWidget *button; - - button = gimp_chain_button_new (GIMP_CHAIN_BOTTOM); - if (chain_checked) - gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (button), TRUE); + gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chainbutton), TRUE); - gtk_table_attach_defaults (GTK_TABLE (sizeentry), button, 1, 3, 3, 4); - gtk_widget_show (button); - - g_object_set_data (G_OBJECT (sizeentry), "chainbutton", button); + g_object_set_data (G_OBJECT (sizeentry), "chainbutton", chainbutton); } g_signal_connect (sizeentry, "value_changed", @@ -1803,7 +1853,7 @@ gimp_prop_coordinates_new (GObject *config, sizeentry); } - return sizeentry; + return TRUE; } static void @@ -1834,26 +1884,10 @@ gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry, unit_value = gimp_size_entry_get_unit (sizeentry); old_x_value = g_object_get_data (G_OBJECT (sizeentry), "old-x-value"); - - if (! old_x_value) - { - old_x_value = g_new0 (gdouble, 1); - *old_x_value = 0.0; - g_object_set_data_full (G_OBJECT (sizeentry), "old-x-value", - old_x_value, - (GDestroyNotify) g_free); - } - old_y_value = g_object_get_data (G_OBJECT (sizeentry), "old-y-value"); - if (! old_y_value) - { - old_y_value = g_new0 (gdouble, 1); - *old_y_value = 0.0; - g_object_set_data_full (G_OBJECT (sizeentry), "old-y-value", - old_y_value, - (GDestroyNotify) g_free); - } + if (! old_x_value || ! old_y_value) + return; if (x_value != y_value) { @@ -1865,20 +1899,9 @@ gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry, gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chainbutton))) { if (x_value != *old_x_value) - { - *old_x_value = x_value; - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 1, - x_value); - return; - } - - if (y_value != *old_y_value) - { - *old_y_value = y_value; - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 0, - y_value); - return; - } + y_value = x_value; + else if (y_value != *old_y_value) + x_value = y_value; } } @@ -1892,8 +1915,8 @@ gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry, G_IS_PARAM_SPEC_INT (y_param_spec)) { g_object_set (config, - x_param_spec->name, (gint) x_value, - y_param_spec->name, (gint) y_value, + x_param_spec->name, ROUND (x_value), + y_param_spec->name, ROUND (y_value), unit_param_spec ? unit_param_spec->name : NULL, unit_value, @@ -1904,8 +1927,8 @@ gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry, G_IS_PARAM_SPEC_DOUBLE (y_param_spec)) { g_object_set (config, - x_param_spec->name, x_value, - y_param_spec->name, y_value, + x_param_spec->name, x_value, + y_param_spec->name, y_value, unit_param_spec ? unit_param_spec->name : NULL, unit_value, diff --git a/app/widgets/gimppropwidgets.h b/app/widgets/gimppropwidgets.h index 96f529e60d..daae8af8b9 100644 --- a/app/widgets/gimppropwidgets.h +++ b/app/widgets/gimppropwidgets.h @@ -140,6 +140,15 @@ GtkWidget * gimp_prop_coordinates_new (GObject *config, gdouble yresolution, gboolean has_chainbutton); +gboolean gimp_prop_size_entry_connect (GObject *config, + const gchar *x_property_name, + const gchar *y_property_name, + const gchar *unit_property_name, + GtkWidget *sizeentry, + GtkWidget *chainbutton, + gdouble xresolution, + gdouble yresolution); + /* GimpParamColor */ diff --git a/libgimpwidgets/gimppropwidgets.c b/libgimpwidgets/gimppropwidgets.c index 393ad841aa..521e08dba4 100644 --- a/libgimpwidgets/gimppropwidgets.c +++ b/libgimpwidgets/gimppropwidgets.c @@ -1644,30 +1644,79 @@ gimp_prop_coordinates_new (GObject *config, gdouble xresolution, gdouble yresolution, gboolean has_chainbutton) +{ + GtkWidget *sizeentry; + GtkWidget *chainbutton = NULL; + + sizeentry = gimp_size_entry_new (2, GIMP_UNIT_INCH, unit_format, + FALSE, FALSE, TRUE, 10, + update_policy); + + if (has_chainbutton) + { + chainbutton = gimp_chain_button_new (GIMP_CHAIN_BOTTOM); + + gtk_table_attach_defaults (GTK_TABLE (sizeentry), chainbutton, + 1, 3, 3, 4); + gtk_widget_show (chainbutton); + } + + if (! gimp_prop_size_entry_connect (config, + x_property_name, + y_property_name, + unit_property_name, + sizeentry, + chainbutton, + xresolution, + yresolution)) + { + gtk_widget_destroy (sizeentry); + return NULL; + } + + return sizeentry; +} + +gboolean +gimp_prop_size_entry_connect (GObject *config, + const gchar *x_property_name, + const gchar *y_property_name, + const gchar *unit_property_name, + GtkWidget *sizeentry, + GtkWidget *chainbutton, + gdouble xresolution, + gdouble yresolution) { GParamSpec *x_param_spec; GParamSpec *y_param_spec; GParamSpec *unit_param_spec; - GtkWidget *sizeentry; gdouble x_value; gdouble y_value; + gdouble *old_x_value; + gdouble *old_y_value; GimpUnit unit_value; gboolean chain_checked = FALSE; + g_return_val_if_fail (GIMP_IS_SIZE_ENTRY (sizeentry), FALSE); + g_return_val_if_fail (GIMP_SIZE_ENTRY (sizeentry)->number_of_fields == 2, + FALSE); + g_return_val_if_fail (chainbutton == NULL || + GIMP_IS_CHAIN_BUTTON (chainbutton), FALSE); + x_param_spec = find_param_spec (config, x_property_name, G_STRLOC); if (! x_param_spec) - return NULL; + return FALSE; y_param_spec = find_param_spec (config, y_property_name, G_STRLOC); if (! y_param_spec) - return NULL; + return FALSE; if (unit_property_name) { unit_param_spec = check_param_spec (config, unit_property_name, GIMP_TYPE_PARAM_UNIT, G_STRLOC); if (! unit_param_spec) - return NULL; + return FALSE; g_object_get (config, unit_property_name, &unit_value, @@ -1707,14 +1756,10 @@ gimp_prop_coordinates_new (GObject *config, " both int or both double", G_STRLOC, x_property_name, y_property_name, g_type_name (G_TYPE_FROM_INSTANCE (config))); - return NULL; + return FALSE; } - sizeentry = gimp_size_entry_new (2, unit_value, unit_format, - FALSE, FALSE, TRUE, 10, - update_policy); - - switch (update_policy) + switch (GIMP_SIZE_ENTRY (sizeentry)->update_policy) { case GIMP_SIZE_ENTRY_UPDATE_SIZE: gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 0, @@ -1760,19 +1805,24 @@ gimp_prop_coordinates_new (GObject *config, g_object_set_data (G_OBJECT (sizeentry), "gimp-config-param-spec-unit", unit_param_spec); - if (has_chainbutton) + old_x_value = g_new0 (gdouble, 1); + *old_x_value = x_value; + g_object_set_data_full (G_OBJECT (sizeentry), "old-x-value", + old_x_value, + (GDestroyNotify) g_free); + + old_y_value = g_new0 (gdouble, 1); + *old_y_value = y_value; + g_object_set_data_full (G_OBJECT (sizeentry), "old-y-value", + old_y_value, + (GDestroyNotify) g_free); + + if (chainbutton) { - GtkWidget *button; - - button = gimp_chain_button_new (GIMP_CHAIN_BOTTOM); - if (chain_checked) - gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (button), TRUE); + gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chainbutton), TRUE); - gtk_table_attach_defaults (GTK_TABLE (sizeentry), button, 1, 3, 3, 4); - gtk_widget_show (button); - - g_object_set_data (G_OBJECT (sizeentry), "chainbutton", button); + g_object_set_data (G_OBJECT (sizeentry), "chainbutton", chainbutton); } g_signal_connect (sizeentry, "value_changed", @@ -1803,7 +1853,7 @@ gimp_prop_coordinates_new (GObject *config, sizeentry); } - return sizeentry; + return TRUE; } static void @@ -1834,26 +1884,10 @@ gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry, unit_value = gimp_size_entry_get_unit (sizeentry); old_x_value = g_object_get_data (G_OBJECT (sizeentry), "old-x-value"); - - if (! old_x_value) - { - old_x_value = g_new0 (gdouble, 1); - *old_x_value = 0.0; - g_object_set_data_full (G_OBJECT (sizeentry), "old-x-value", - old_x_value, - (GDestroyNotify) g_free); - } - old_y_value = g_object_get_data (G_OBJECT (sizeentry), "old-y-value"); - if (! old_y_value) - { - old_y_value = g_new0 (gdouble, 1); - *old_y_value = 0.0; - g_object_set_data_full (G_OBJECT (sizeentry), "old-y-value", - old_y_value, - (GDestroyNotify) g_free); - } + if (! old_x_value || ! old_y_value) + return; if (x_value != y_value) { @@ -1865,20 +1899,9 @@ gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry, gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chainbutton))) { if (x_value != *old_x_value) - { - *old_x_value = x_value; - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 1, - x_value); - return; - } - - if (y_value != *old_y_value) - { - *old_y_value = y_value; - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 0, - y_value); - return; - } + y_value = x_value; + else if (y_value != *old_y_value) + x_value = y_value; } } @@ -1892,8 +1915,8 @@ gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry, G_IS_PARAM_SPEC_INT (y_param_spec)) { g_object_set (config, - x_param_spec->name, (gint) x_value, - y_param_spec->name, (gint) y_value, + x_param_spec->name, ROUND (x_value), + y_param_spec->name, ROUND (y_value), unit_param_spec ? unit_param_spec->name : NULL, unit_value, @@ -1904,8 +1927,8 @@ gimp_prop_coordinates_callback (GimpSizeEntry *sizeentry, G_IS_PARAM_SPEC_DOUBLE (y_param_spec)) { g_object_set (config, - x_param_spec->name, x_value, - y_param_spec->name, y_value, + x_param_spec->name, x_value, + y_param_spec->name, y_value, unit_param_spec ? unit_param_spec->name : NULL, unit_value, diff --git a/libgimpwidgets/gimppropwidgets.h b/libgimpwidgets/gimppropwidgets.h index 96f529e60d..daae8af8b9 100644 --- a/libgimpwidgets/gimppropwidgets.h +++ b/libgimpwidgets/gimppropwidgets.h @@ -140,6 +140,15 @@ GtkWidget * gimp_prop_coordinates_new (GObject *config, gdouble yresolution, gboolean has_chainbutton); +gboolean gimp_prop_size_entry_connect (GObject *config, + const gchar *x_property_name, + const gchar *y_property_name, + const gchar *unit_property_name, + GtkWidget *sizeentry, + GtkWidget *chainbutton, + gdouble xresolution, + gdouble yresolution); + /* GimpParamColor */