From 725a4e414fd19c80388fcedec7e50f88497fd993 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Fri, 3 Nov 2006 17:12:27 +0000 Subject: [PATCH] added value GIMP_UNDO_GROUP_LAYER_ADD. 2006-11-03 Michael Natterer * app/core/core-enums.[ch] (enum GimpUndoType): added value GIMP_UNDO_GROUP_LAYER_ADD. * app/file/file-open.[ch]: changed file_open_layer() to file_open_layers(), added parameter "gboolean merge_visible", return a GList of layers. * app/dialogs/file-open-dialog.c * app/display/gimpdisplayshell-dnd.c * app/widgets/gimplayertreeview.c: pass merge_visible = FALSE and add all returned layers to the image. Fixes bug #358082. (contains lots of duplicated code, will factor that out later). * tools/pdbgen/pdb/fileops.pdb (load_layer): pass merge_visible = TRUE (load_layers): new wrapper which returns all the image's layers. * app/pdb/fileops_cmds.c * app/pdb/internal_procs.c * libgimp/gimpfileops_pdb.[ch]: regenerated. * libgimp/gimp.def: changed accordingly. --- ChangeLog | 24 +++++ app/core/core-enums.c | 2 + app/core/core-enums.h | 1 + app/dialogs/file-open-dialog.c | 113 +++++++++++++++--------- app/display/gimpdisplayshell-dnd.c | 64 ++++++++++---- app/file/file-open.c | 83 ++++++++++-------- app/file/file-open.h | 3 +- app/pdb/fileops_cmds.c | 136 +++++++++++++++++++++++++++-- app/pdb/internal_procs.c | 2 +- app/widgets/gimplayertreeview.c | 64 ++++++++++---- libgimp/gimp.def | 1 + libgimp/gimpfileops_pdb.c | 57 +++++++++++- libgimp/gimpfileops_pdb.h | 4 + tools/pdbgen/pdb/fileops.pdb | 107 ++++++++++++++++++++--- 14 files changed, 530 insertions(+), 131 deletions(-) diff --git a/ChangeLog b/ChangeLog index ea9889e608..193ac483df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2006-11-03 Michael Natterer + + * app/core/core-enums.[ch] (enum GimpUndoType): added value + GIMP_UNDO_GROUP_LAYER_ADD. + + * app/file/file-open.[ch]: changed file_open_layer() to + file_open_layers(), added parameter "gboolean merge_visible", + return a GList of layers. + + * app/dialogs/file-open-dialog.c + * app/display/gimpdisplayshell-dnd.c + * app/widgets/gimplayertreeview.c: pass merge_visible = FALSE and + add all returned layers to the image. Fixes bug #358082. + (contains lots of duplicated code, will factor that out later). + + * tools/pdbgen/pdb/fileops.pdb (load_layer): pass merge_visible = TRUE + (load_layers): new wrapper which returns all the image's layers. + + * app/pdb/fileops_cmds.c + * app/pdb/internal_procs.c + * libgimp/gimpfileops_pdb.[ch]: regenerated. + + * libgimp/gimp.def: changed accordingly. + 2006-11-03 Sven Neumann * plug-ins/common/lcms.c: use gimp_any_to_utf8(). diff --git a/app/core/core-enums.c b/app/core/core-enums.c index f614b39e7f..3cd741abcb 100644 --- a/app/core/core-enums.c +++ b/app/core/core-enums.c @@ -780,6 +780,7 @@ gimp_undo_type_get_type (void) { GIMP_UNDO_GROUP_ITEM_DISPLACE, "GIMP_UNDO_GROUP_ITEM_DISPLACE", "group-item-displace" }, { GIMP_UNDO_GROUP_ITEM_SCALE, "GIMP_UNDO_GROUP_ITEM_SCALE", "group-item-scale" }, { GIMP_UNDO_GROUP_ITEM_RESIZE, "GIMP_UNDO_GROUP_ITEM_RESIZE", "group-item-resize" }, + { GIMP_UNDO_GROUP_LAYER_ADD, "GIMP_UNDO_GROUP_LAYER_ADD", "group-layer-add" }, { GIMP_UNDO_GROUP_LAYER_ADD_MASK, "GIMP_UNDO_GROUP_LAYER_ADD_MASK", "group-layer-add-mask" }, { GIMP_UNDO_GROUP_LAYER_APPLY_MASK, "GIMP_UNDO_GROUP_LAYER_APPLY_MASK", "group-layer-apply-mask" }, { GIMP_UNDO_GROUP_FS_TO_LAYER, "GIMP_UNDO_GROUP_FS_TO_LAYER", "group-fs-to-layer" }, @@ -867,6 +868,7 @@ gimp_undo_type_get_type (void) { GIMP_UNDO_GROUP_ITEM_DISPLACE, N_("Move item"), NULL }, { GIMP_UNDO_GROUP_ITEM_SCALE, N_("Scale item"), NULL }, { GIMP_UNDO_GROUP_ITEM_RESIZE, N_("Resize item"), NULL }, + { GIMP_UNDO_GROUP_LAYER_ADD, N_("Add layer"), NULL }, { GIMP_UNDO_GROUP_LAYER_ADD_MASK, N_("Add layer mask"), NULL }, { GIMP_UNDO_GROUP_LAYER_APPLY_MASK, N_("Apply layer mask"), NULL }, { GIMP_UNDO_GROUP_FS_TO_LAYER, N_("Floating selection to layer"), NULL }, diff --git a/app/core/core-enums.h b/app/core/core-enums.h index 279f6c745f..3704369da3 100644 --- a/app/core/core-enums.h +++ b/app/core/core-enums.h @@ -380,6 +380,7 @@ typedef enum /*< pdb-skip >*/ GIMP_UNDO_GROUP_ITEM_DISPLACE, /*< desc="Move item" >*/ GIMP_UNDO_GROUP_ITEM_SCALE, /*< desc="Scale item" >*/ GIMP_UNDO_GROUP_ITEM_RESIZE, /*< desc="Resize item" >*/ + GIMP_UNDO_GROUP_LAYER_ADD, /*< desc="Add layer" >*/ GIMP_UNDO_GROUP_LAYER_ADD_MASK, /*< desc="Add layer mask" >*/ GIMP_UNDO_GROUP_LAYER_APPLY_MASK, /*< desc="Apply layer mask" >*/ GIMP_UNDO_GROUP_FS_TO_LAYER, /*< desc="Floating selection to layer" >*/ diff --git a/app/dialogs/file-open-dialog.c b/app/dialogs/file-open-dialog.c index 30c2b90d56..e68fd2cbd6 100644 --- a/app/dialogs/file-open-dialog.c +++ b/app/dialogs/file-open-dialog.c @@ -29,7 +29,8 @@ #include "core/gimp.h" #include "core/gimpimage.h" -#include "core/gimpitem.h" +#include "core/gimpimage-undo.h" +#include "core/gimplayer.h" #include "core/gimpprogress.h" #include "file/file-open.h" @@ -45,19 +46,19 @@ /* local function prototypes */ -static void file_open_dialog_response (GtkWidget *open_dialog, - gint response_id, - Gimp *gimp); -static gboolean file_open_dialog_open_image (GtkWidget *open_dialog, - Gimp *gimp, - const gchar *uri, - const gchar *entered_filename, - GimpPlugInProcedure *load_proc); -static gboolean file_open_dialog_open_layer (GtkWidget *open_dialog, - GimpImage *image, - const gchar *uri, - const gchar *entered_filename, - GimpPlugInProcedure *load_proc); +static void file_open_dialog_response (GtkWidget *open_dialog, + gint response_id, + Gimp *gimp); +static gboolean file_open_dialog_open_image (GtkWidget *open_dialog, + Gimp *gimp, + const gchar *uri, + const gchar *entered_filename, + GimpPlugInProcedure *load_proc); +static gboolean file_open_dialog_open_layers (GtkWidget *open_dialog, + GimpImage *image, + const gchar *uri, + const gchar *entered_filename, + GimpPlugInProcedure *load_proc); /* public functions */ @@ -131,11 +132,11 @@ file_open_dialog_response (GtkWidget *open_dialog, if (dialog->image) { - if (file_open_dialog_open_layer (open_dialog, - dialog->image, - list->data, - list->data, - dialog->file_proc)) + if (file_open_dialog_open_layers (open_dialog, + dialog->image, + list->data, + list->data, + dialog->file_proc)) { success = TRUE; } @@ -211,39 +212,69 @@ file_open_dialog_open_image (GtkWidget *open_dialog, } static gboolean -file_open_dialog_open_layer (GtkWidget *open_dialog, - GimpImage *image, - const gchar *uri, - const gchar *entered_filename, - GimpPlugInProcedure *load_proc) +file_open_dialog_open_layers (GtkWidget *open_dialog, + GimpImage *image, + const gchar *uri, + const gchar *entered_filename, + GimpPlugInProcedure *load_proc) { - GimpLayer *new_layer; + GList *new_layers; GimpPDBStatusType status; GError *error = NULL; - new_layer = file_open_layer (image->gimp, - gimp_get_user_context (image->gimp), - GIMP_PROGRESS (open_dialog), - image, uri, GIMP_RUN_INTERACTIVE, load_proc, - &status, &error); + new_layers = file_open_layers (image->gimp, + gimp_get_user_context (image->gimp), + GIMP_PROGRESS (open_dialog), + image, FALSE, + uri, GIMP_RUN_INTERACTIVE, load_proc, + &status, &error); - if (new_layer) + if (new_layers) { - GimpItem *new_item = GIMP_ITEM (new_layer); - gint width, height; - gint off_x, off_y; + GList *list; + gint image_width = gimp_image_get_width (image); + gint image_height = gimp_image_get_height (image); + gint layers_x = G_MAXINT; + gint layers_y = G_MAXINT; + gint layers_width = 0; + gint layers_height = 0; + gint offset_x; + gint offset_y; - width = gimp_image_get_width (image); - height = gimp_image_get_height (image); + for (list = new_layers; list; list = g_list_next (list)) + { + GimpItem *item = GIMP_ITEM (list->data); + gint off_x, off_y; - gimp_item_offsets (new_item, &off_x, &off_y); + gimp_item_offsets (item, &off_x, &off_y); - off_x = (width - gimp_item_width (new_item)) / 2 - off_x; - off_y = (height - gimp_item_height (new_item)) / 2 - off_y; + layers_x = MIN (layers_x, off_x); + layers_y = MIN (layers_y, off_y); - gimp_item_translate (new_item, off_x, off_y, FALSE); + layers_width = MAX (layers_width, + off_x + gimp_item_width (item) - layers_x); + layers_height = MAX (layers_height, + off_y + gimp_item_height (item) - layers_y); + } - gimp_image_add_layer (image, new_layer, -1); + offset_x = (image_width - layers_width) / 2 - layers_x; + offset_y = (image_height - layers_height) / 2 - layers_y; + + gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_LAYER_ADD, + _("Open layers")); + + for (list = new_layers; list; list = g_list_next (list)) + { + GimpItem *item = GIMP_ITEM (list->data); + + gimp_item_translate (item, offset_x, offset_y, FALSE); + + gimp_image_add_layer (image, GIMP_LAYER (item), -1); + } + + gimp_image_undo_group_end (image); + + g_list_free (new_layers); return TRUE; } diff --git a/app/display/gimpdisplayshell-dnd.c b/app/display/gimpdisplayshell-dnd.c index e28a5d7789..24507cdb82 100644 --- a/app/display/gimpdisplayshell-dnd.c +++ b/app/display/gimpdisplayshell-dnd.c @@ -416,34 +416,66 @@ gimp_display_shell_drop_uri_list (GtkWidget *widget, for (list = uri_list; list; list = g_list_next (list)) { const gchar *uri = list->data; - GimpLayer *new_layer; + GList *new_layers; GimpPDBStatusType status; GError *error = NULL; - new_layer = file_open_layer (image->gimp, context, - GIMP_PROGRESS (shell->display), - image, uri, GIMP_RUN_INTERACTIVE, NULL, - &status, &error); + new_layers = file_open_layers (image->gimp, context, + GIMP_PROGRESS (shell->display), + image, FALSE, + uri, GIMP_RUN_INTERACTIVE, NULL, + &status, &error); - if (new_layer) + if (new_layers) { - GimpItem *new_item = GIMP_ITEM (new_layer); - gint x, y; - gint width, height; - gint off_x, off_y; + GList *list; + gint x, y; + gint width, height; + gint layers_x = G_MAXINT; + gint layers_y = G_MAXINT; + gint layers_width = 0; + gint layers_height = 0; + gint offset_x; + gint offset_y; gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height); - gimp_item_offsets (new_item, &off_x, &off_y); + for (list = new_layers; list; list = g_list_next (list)) + { + GimpItem *item = GIMP_ITEM (list->data); + gint off_x, off_y; - off_x = x + (width - gimp_item_width (new_item)) / 2 - off_x; - off_y = y + (height - gimp_item_height (new_item)) / 2 - off_y; + gimp_item_offsets (item, &off_x, &off_y); - gimp_item_translate (new_item, off_x, off_y, FALSE); + layers_x = MIN (layers_x, off_x); + layers_y = MIN (layers_y, off_y); - gimp_image_add_layer (image, new_layer, -1); - } + layers_width = MAX (layers_width, + off_x + gimp_item_width (item) - layers_x); + layers_height = MAX (layers_height, + off_y + gimp_item_height (item) - layers_y); + } + + offset_x = x + (width - layers_width) / 2 - layers_x; + offset_y = y + (height - layers_height) / 2 - layers_y; + + gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_LAYER_ADD, + _("Drop layers")); + + for (list = new_layers; list; list = g_list_next (list)) + { + GimpItem *new_item = GIMP_ITEM (list->data); + + gimp_item_translate (new_item, offset_x, offset_y, FALSE); + + gimp_image_add_layer (image, GIMP_LAYER (new_item), -1); + } + + gimp_image_undo_group_end (image); + + g_list_free (new_layers); + } else if (status != GIMP_PDB_CANCEL) { gchar *filename = file_utils_uri_display_name (uri); diff --git a/app/file/file-open.c b/app/file/file-open.c index b5b9718d2f..ce185ec5a7 100644 --- a/app/file/file-open.c +++ b/app/file/file-open.c @@ -342,19 +342,20 @@ file_open_with_proc_and_display (Gimp *gimp, return image; } -GimpLayer * -file_open_layer (Gimp *gimp, - GimpContext *context, - GimpProgress *progress, - GimpImage *dest_image, - const gchar *uri, - GimpRunMode run_mode, - GimpPlugInProcedure *file_proc, - GimpPDBStatusType *status, - GError **error) +GList * +file_open_layers (Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + GimpImage *dest_image, + gboolean merge_visible, + const gchar *uri, + GimpRunMode run_mode, + GimpPlugInProcedure *file_proc, + GimpPDBStatusType *status, + GError **error) { - GimpLayer *new_layer = NULL; GimpImage *new_image; + GList *layers = NULL; const gchar *mime_type = NULL; g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); @@ -373,9 +374,8 @@ file_open_layer (Gimp *gimp, if (new_image) { - GList *list; - GimpLayer *layer = NULL; - gint n_visible = 0; + GList *list; + gint n_visible = 0; gimp_image_undo_disable (new_image); @@ -383,50 +383,65 @@ file_open_layer (Gimp *gimp, list; list = g_list_next (list)) { + if (! merge_visible) + layers = g_list_prepend (layers, list->data); + if (gimp_item_get_visible (list->data)) { n_visible++; - if (! layer) - layer = list->data; + if (! layers) + layers = g_list_prepend (layers, list->data); } } - if (n_visible > 1) - layer = gimp_image_merge_visible_layers (new_image, context, - GIMP_CLIP_TO_IMAGE, FALSE); - - if (layer) + if (merge_visible && n_visible > 1) { - GimpItem *item = gimp_item_convert (GIMP_ITEM (layer), dest_image, - G_TYPE_FROM_INSTANCE (layer), - TRUE); + GimpLayer *layer; - if (item) + g_list_free (layers); + + layer = gimp_image_merge_visible_layers (new_image, context, + GIMP_CLIP_TO_IMAGE, FALSE); + + layers = g_list_prepend (NULL, layer); + } + + if (layers) + { + for (list = layers; list; list = g_list_next (list)) { - new_layer = GIMP_LAYER (item); + GimpLayer *layer = list->data; + GimpItem *item; - gimp_object_take_name (GIMP_OBJECT (new_layer), - file_utils_uri_display_basename (uri)); + item = gimp_item_convert (GIMP_ITEM (layer), dest_image, + G_TYPE_FROM_INSTANCE (layer), + TRUE); - gimp_document_list_add_uri (GIMP_DOCUMENT_LIST (gimp->documents), - uri, mime_type); + if (merge_visible) + gimp_object_take_name (GIMP_OBJECT (item), + file_utils_uri_display_basename (uri)); - if (gimp->config->save_document_history) - gimp_recent_list_add_uri (uri, mime_type); + list->data = item; } + + gimp_document_list_add_uri (GIMP_DOCUMENT_LIST (gimp->documents), + uri, mime_type); + + if (gimp->config->save_document_history) + gimp_recent_list_add_uri (uri, mime_type); } else { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, - _("Image doesn't contain any visible layers")); + _("Image doesn't contain any layers")); *status = GIMP_PDB_EXECUTION_ERROR; } g_object_unref (new_image); } - return new_layer; + return g_list_reverse (layers); } diff --git a/app/file/file-open.h b/app/file/file-open.h index 4e67ad9729..1e81257344 100644 --- a/app/file/file-open.h +++ b/app/file/file-open.h @@ -57,10 +57,11 @@ GimpImage * file_open_with_proc_and_display (Gimp *gimp, GimpPDBStatusType *status, GError **error); -GimpLayer * file_open_layer (Gimp *gimp, +GList * file_open_layers (Gimp *gimp, GimpContext *context, GimpProgress *progress, GimpImage *dest_image, + gboolean merge_visible, const gchar *uri, GimpRunMode run_mode, GimpPlugInProcedure *file_proc, diff --git a/app/pdb/fileops_cmds.c b/app/pdb/fileops_cmds.c index 2f8286e3a9..e8152dbaa0 100644 --- a/app/pdb/fileops_cmds.c +++ b/app/pdb/fileops_cmds.c @@ -37,6 +37,7 @@ #include "core/gimpimage.h" #include "core/gimplayer.h" #include "file/file-open.h" +#include "file/file-save.h" #include "file/file-utils.h" #include "plug-in/gimppluginmanager-file.h" #include "plug-in/gimppluginmanager.h" @@ -119,12 +120,19 @@ file_load_layer_invoker (GimpProcedure *procedure, if (uri) { - GimpPDBStatusType status; + GList *layers; + GimpPDBStatusType status; - layer = file_open_layer (gimp, context, progress, - image, uri, run_mode, NULL, &status, NULL); + layers = file_open_layers (gimp, context, progress, + image, FALSE, + uri, run_mode, NULL, &status, NULL); - if (! layer) + if (layers) + { + layer = layers->data; + g_list_free (layers); + } + else success = FALSE; } else @@ -139,6 +147,73 @@ file_load_layer_invoker (GimpProcedure *procedure, return return_vals; } +static GValueArray * +file_load_layers_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GValueArray *args) +{ + gboolean success = TRUE; + GValueArray *return_vals; + gint32 run_mode; + GimpImage *image; + const gchar *filename; + gint32 num_layers = 0; + gint32 *layer_ids = NULL; + + run_mode = g_value_get_enum (&args->values[0]); + image = gimp_value_get_image (&args->values[1], gimp); + filename = g_value_get_string (&args->values[2]); + + if (success) + { + gchar *uri = file_utils_filename_to_uri (gimp->plug_in_manager->load_procs, + filename, NULL); + + if (uri) + { + GList *layers; + GimpPDBStatusType status; + + layers = file_open_layers (gimp, context, progress, + image, FALSE, + uri, run_mode, NULL, &status, NULL); + + if (layers) + { + GList *list; + gint i; + + num_layers = g_list_length (layers); + + layer_ids = g_new (gint32, num_layers); + + for (i = 0, list = layers; + i < num_layers; + i++, list = g_list_next (list)) + layer_ids[i] = gimp_item_get_ID (GIMP_ITEM (list->data)); + + g_list_free (layers); + } + else + success = FALSE; + } + else + success = FALSE; + } + + return_vals = gimp_procedure_get_return_values (procedure, success); + + if (success) + { + g_value_set_int (&return_vals->values[1], num_layers); + gimp_value_take_int32array (&return_vals->values[2], layer_ids, num_layers); + } + + return return_vals; +} + static GValueArray * file_save_invoker (GimpProcedure *procedure, Gimp *gimp, @@ -489,8 +564,8 @@ register_fileops_procs (GimpPDB *pdb) gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-file-load-layer"); gimp_procedure_set_static_strings (procedure, "gimp-file-load-layer", - "Loads an image file as a layer into an already opened image.", - "This procedure behaves like the file-load procedure but opens the specified image as a layer into an already opened image.", + "Loads an image file as a layer for an existing image.", + "This procedure behaves like the file-load procedure but opens the specified image as a layer for an existing image. The returned layer needs to be added to the existing image with 'gimp-image-add-layer'.", "Sven Neumann ", "Sven Neumann", "2005", @@ -526,6 +601,55 @@ register_fileops_procs (GimpPDB *pdb) gimp_pdb_register_procedure (pdb, procedure); g_object_unref (procedure); + /* + * gimp-file-load-layers + */ + procedure = gimp_procedure_new (file_load_layers_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-file-load-layers"); + gimp_procedure_set_static_strings (procedure, + "gimp-file-load-layers", + "Loads an image file as layers for an existing image.", + "This procedure behaves like the file-load procedure but opens the specified image as layers for an existing image. The returned layers needs to be added to the existing image with 'gimp-image-add-layer'.", + "Michael Natterer ", + "Michael Natterer", + "2006", + NULL); + gimp_procedure_add_argument (procedure, + gimp_param_spec_enum ("run-mode", + "run mode", + "The run mode", + GIMP_TYPE_RUN_MODE, + GIMP_RUN_INTERACTIVE, + GIMP_PARAM_READWRITE)); + gimp_param_spec_enum_exclude_value (GIMP_PARAM_SPEC_ENUM (procedure->args[0]), + GIMP_RUN_WITH_LAST_VALS); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image_id ("image", + "image", + "Destination image", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("filename", + "filename", + "The name of the file to load", + TRUE, FALSE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_return_value (procedure, + gimp_param_spec_int32 ("num-layers", + "num layers", + "The number of loaded layers", + 0, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_return_value (procedure, + gimp_param_spec_int32_array ("layer-ids", + "layer ids", + "The list of loaded layers", + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + /* * gimp-file-save */ diff --git a/app/pdb/internal_procs.c b/app/pdb/internal_procs.c index 4ff24d2c46..02cded2301 100644 --- a/app/pdb/internal_procs.c +++ b/app/pdb/internal_procs.c @@ -29,7 +29,7 @@ #include "internal_procs.h" -/* 537 procedures registered total */ +/* 538 procedures registered total */ void internal_procs_init (GimpPDB *pdb) diff --git a/app/widgets/gimplayertreeview.c b/app/widgets/gimplayertreeview.c index 79c79b9f26..d577f89bef 100644 --- a/app/widgets/gimplayertreeview.c +++ b/app/widgets/gimplayertreeview.c @@ -729,33 +729,63 @@ gimp_layer_tree_view_drop_uri_list (GimpContainerTreeView *view, for (list = uri_list; list; list = g_list_next (list)) { const gchar *uri = list->data; - GimpLayer *new_layer; + GList *new_layers; GimpPDBStatusType status; GError *error = NULL; - new_layer = file_open_layer (image->gimp, - gimp_container_view_get_context (cont_view), - NULL, - image, uri, GIMP_RUN_INTERACTIVE, NULL, - &status, &error); + new_layers = file_open_layers (image->gimp, + gimp_container_view_get_context (cont_view), + NULL, + image, FALSE, + uri, GIMP_RUN_INTERACTIVE, NULL, + &status, &error); - if (new_layer) + if (new_layers) { - GimpItem *new_item = GIMP_ITEM (new_layer); - gint width, height; - gint off_x, off_y; + GList *list; + gint image_width = gimp_image_get_width (image); + gint image_height = gimp_image_get_height (image); + gint layers_x = G_MAXINT; + gint layers_y = G_MAXINT; + gint layers_width = 0; + gint layers_height = 0; + gint offset_x; + gint offset_y; - width = gimp_image_get_width (image); - height = gimp_image_get_height (image); + for (list = new_layers; list; list = g_list_next (list)) + { + GimpItem *item = GIMP_ITEM (list->data); + gint off_x, off_y; - gimp_item_offsets (new_item, &off_x, &off_y); + gimp_item_offsets (item, &off_x, &off_y); - off_x = (width - gimp_item_width (new_item)) / 2 - off_x; - off_y = (height - gimp_item_height (new_item)) / 2 - off_y; + layers_x = MIN (layers_x, off_x); + layers_y = MIN (layers_y, off_y); - gimp_item_translate (new_item, off_x, off_y, FALSE); + layers_width = MAX (layers_width, + off_x + gimp_item_width (item) - layers_x); + layers_height = MAX (layers_height, + off_y + gimp_item_height (item) - layers_y); + } - gimp_image_add_layer (image, new_layer, index++); + offset_x = (image_width - layers_width) / 2 - layers_x; + offset_y = (image_height - layers_height) / 2 - layers_y; + + gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_LAYER_ADD, + _("Drop layers")); + + for (list = new_layers; list; list = g_list_next (list)) + { + GimpItem *new_item = GIMP_ITEM (list->data); + + gimp_item_translate (new_item, offset_x, offset_y, FALSE); + + gimp_image_add_layer (image, GIMP_LAYER (new_item), index++); + } + + gimp_image_undo_group_end (image); + + g_list_free (new_layers); } else if (status != GIMP_PDB_CANCEL) { diff --git a/libgimp/gimp.def b/libgimp/gimp.def index 997ab5035c..8c05b85363 100644 --- a/libgimp/gimp.def +++ b/libgimp/gimp.def @@ -203,6 +203,7 @@ EXPORTS gimp_extension_process gimp_file_load gimp_file_load_layer + gimp_file_load_layers gimp_file_save gimp_fill_type_get_type gimp_flip diff --git a/libgimp/gimpfileops_pdb.c b/libgimp/gimpfileops_pdb.c index cf2e72ee00..695d4a3b0e 100644 --- a/libgimp/gimpfileops_pdb.c +++ b/libgimp/gimpfileops_pdb.c @@ -23,6 +23,8 @@ #include "config.h" +#include + #include "gimp.h" /** @@ -73,10 +75,11 @@ gimp_file_load (GimpRunMode run_mode, * @image_ID: Destination image. * @filename: The name of the file to load. * - * Loads an image file as a layer into an already opened image. + * Loads an image file as a layer for an existing image. * * This procedure behaves like the file-load procedure but opens the - * specified image as a layer into an already opened image. + * specified image as a layer for an existing image. The returned layer + * needs to be added to the existing image with gimp_image_add_layer(). * * Returns: The layer created when loading the image file. * @@ -106,6 +109,56 @@ gimp_file_load_layer (GimpRunMode run_mode, return layer_ID; } +/** + * gimp_file_load_layers: + * @run_mode: The run mode. + * @image_ID: Destination image. + * @filename: The name of the file to load. + * @num_layers: The number of loaded layers. + * + * Loads an image file as layers for an existing image. + * + * This procedure behaves like the file-load procedure but opens the + * specified image as layers for an existing image. The returned layers + * needs to be added to the existing image with gimp_image_add_layer(). + * + * Returns: The list of loaded layers. + * + * Since: GIMP 2.4 + */ +gint * +gimp_file_load_layers (GimpRunMode run_mode, + gint32 image_ID, + const gchar *filename, + gint *num_layers) +{ + GimpParam *return_vals; + gint nreturn_vals; + gint *layer_ids = NULL; + + return_vals = gimp_run_procedure ("gimp-file-load-layers", + &nreturn_vals, + GIMP_PDB_INT32, run_mode, + GIMP_PDB_IMAGE, image_ID, + GIMP_PDB_STRING, filename, + GIMP_PDB_END); + + *num_layers = 0; + + if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS) + { + *num_layers = return_vals[1].data.d_int32; + layer_ids = g_new (gint32, *num_layers); + memcpy (layer_ids, + return_vals[2].data.d_int32array, + *num_layers * sizeof (gint32)); + } + + gimp_destroy_params (return_vals, nreturn_vals); + + return layer_ids; +} + /** * gimp_file_save: * @run_mode: The run mode. diff --git a/libgimp/gimpfileops_pdb.h b/libgimp/gimpfileops_pdb.h index cd8a944156..6df41c884c 100644 --- a/libgimp/gimpfileops_pdb.h +++ b/libgimp/gimpfileops_pdb.h @@ -35,6 +35,10 @@ gint32 gimp_file_load (GimpRunMode run_mode, gint32 gimp_file_load_layer (GimpRunMode run_mode, gint32 image_ID, const gchar *filename); +gint* gimp_file_load_layers (GimpRunMode run_mode, + gint32 image_ID, + const gchar *filename, + gint *num_layers); gboolean gimp_file_save (GimpRunMode run_mode, gint32 image_ID, gint32 drawable_ID, diff --git a/tools/pdbgen/pdb/fileops.pdb b/tools/pdbgen/pdb/fileops.pdb index b97737c9de..af5116ff76 100644 --- a/tools/pdbgen/pdb/fileops.pdb +++ b/tools/pdbgen/pdb/fileops.pdb @@ -98,11 +98,12 @@ CODE } sub file_load_layer { - $blurb = 'Loads an image file as a layer into an already opened image.'; + $blurb = 'Loads an image file as a layer for an existing image.'; $help = <<'HELP'; This procedure behaves like the file-load procedure but opens the specified -image as a layer into an already opened image. +image as a layer for an existing image. The returned layer needs to be +added to the existing image with gimp_image_add_layer(). HELP &neo_pdb_misc('2005', '2.4'); @@ -123,20 +124,95 @@ HELP ); %invoke = ( - headers => [ qw("file/file-open.h") ], - code => <<'CODE' + code => <<'CODE' { gchar *uri = file_utils_filename_to_uri (gimp->plug_in_manager->load_procs, filename, NULL); if (uri) { - GimpPDBStatusType status; + GList *layers; + GimpPDBStatusType status; - layer = file_open_layer (gimp, context, progress, - image, uri, run_mode, NULL, &status, NULL); + layers = file_open_layers (gimp, context, progress, + image, FALSE, + uri, run_mode, NULL, &status, NULL); - if (! layer) + if (layers) + { + layer = layers->data; + g_list_free (layers); + } + else + success = FALSE; + } + else + success = FALSE; +} +CODE + ); +} + +sub file_load_layers { + $blurb = 'Loads an image file as layers for an existing image.'; + + $help = <<'HELP'; +This procedure behaves like the file-load procedure but opens the specified +image as layers for an existing image. The returned layers needs to be +added to the existing image with gimp_image_add_layer(). +HELP + + &mitch_pdb_misc('2006', '2.4'); + + @inargs = ( + { name => 'run_mode', + type => 'enum GimpRunMode (no GIMP_RUN_WITH_LAST_VALS)', + desc => 'The run mode' }, + { name => 'image', type => 'image', + desc => 'Destination image' }, + { name => 'filename', type => 'string', no_validate => 1, + desc => 'The name of the file to load' } + ); + + @outargs = ( + { name => 'layer_ids', type => 'int32array', + desc => 'The list of loaded layers', + array => { name => 'num_layers', + desc => 'The number of loaded layers' } } + ); + + %invoke = ( + code => <<'CODE' +{ + gchar *uri = file_utils_filename_to_uri (gimp->plug_in_manager->load_procs, + filename, NULL); + + if (uri) + { + GList *layers; + GimpPDBStatusType status; + + layers = file_open_layers (gimp, context, progress, + image, FALSE, + uri, run_mode, NULL, &status, NULL); + + if (layers) + { + GList *list; + gint i; + + num_layers = g_list_length (layers); + + layer_ids = g_new (gint32, num_layers); + + for (i = 0, list = layers; + i < num_layers; + i++, list = g_list_next (list)) + layer_ids[i] = gimp_item_get_ID (GIMP_ITEM (list->data)); + + g_list_free (layers); + } + else success = FALSE; } else @@ -327,7 +403,6 @@ HELP ); %invoke = ( - headers => [ qw("core/gimp-utils.h") ], code => <<'CODE' { name = gimp_get_temp_filename (gimp, extension); @@ -518,17 +593,23 @@ CODE @headers = qw("libgimpbase/gimpbase.h" "libgimpconfig/gimpconfig.h" "core/gimp.h" + "core/gimp-utils.h" "plug-in/gimppluginmanager.h" "plug-in/gimppluginmanager-file.h" + "file/file-open.h" + "file/file-save.h" "file/file-utils.h"); -@procs = qw(file_load file_load_layer file_save +@procs = qw(file_load file_load_layer file_load_layers + file_save file_load_thumbnail file_save_thumbnail - temp_name register_magic_load_handler register_load_handler - register_save_handler register_file_handler_mime + temp_name + register_magic_load_handler register_load_handler + register_save_handler + register_file_handler_mime register_thumbnail_loader); -%exports = (app => [@procs], lib => [@procs[0..2,5..10]]); +%exports = (app => [@procs], lib => [@procs[0..3,6..11]]); $desc = 'File Operations';