mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-03 17:33:25 +00:00

Rather than trying to fix up our own heuristics using a `GtkMenuPositionFunc`, use the API that GTK provides to have popup nicely placed near the pointer, which also has the benefit of nicely integrating with GDK backends such as Wayland.
630 lines
22 KiB
C
630 lines
22 KiB
C
/* GIMP - The GNU Image Manipulation Program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* gimpcomponenteditor.c
|
|
* Copyright (C) 2003-2005 Michael Natterer <mitch@gimp.org>
|
|
*
|
|
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gegl.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
#include "widgets-types.h"
|
|
|
|
#include "core/gimpchannel.h"
|
|
#include "core/gimpimage.h"
|
|
|
|
#include "gimpcellrendererviewable.h"
|
|
#include "gimpcomponenteditor.h"
|
|
#include "gimpdnd.h"
|
|
#include "gimpdocked.h"
|
|
#include "gimpmenufactory.h"
|
|
#include "gimpviewrendererimage.h"
|
|
#include "gimpwidgets-utils.h"
|
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
|
enum
|
|
{
|
|
COLUMN_CHANNEL,
|
|
COLUMN_VISIBLE,
|
|
COLUMN_RENDERER,
|
|
COLUMN_NAME,
|
|
N_COLUMNS
|
|
};
|
|
|
|
|
|
static void gimp_component_editor_docked_iface_init (GimpDockedInterface *iface);
|
|
|
|
static void gimp_component_editor_set_context (GimpDocked *docked,
|
|
GimpContext *context);
|
|
|
|
static void gimp_component_editor_set_image (GimpImageEditor *editor,
|
|
GimpImage *image);
|
|
|
|
static void gimp_component_editor_create_components (GimpComponentEditor *editor);
|
|
static void gimp_component_editor_clear_components (GimpComponentEditor *editor);
|
|
static void gimp_component_editor_clicked (GtkCellRendererToggle *cellrenderertoggle,
|
|
gchar *path,
|
|
GdkModifierType state,
|
|
GimpComponentEditor *editor);
|
|
static gboolean gimp_component_editor_select (GtkTreeSelection *selection,
|
|
GtkTreeModel *model,
|
|
GtkTreePath *path,
|
|
gboolean path_currently_selected,
|
|
gpointer data);
|
|
static gboolean gimp_component_editor_button_press (GtkWidget *widget,
|
|
GdkEventButton *bevent,
|
|
GimpComponentEditor *editor);
|
|
static void gimp_component_editor_renderer_update (GimpViewRenderer *renderer,
|
|
GimpComponentEditor *editor);
|
|
static void gimp_component_editor_mode_changed (GimpImage *image,
|
|
GimpComponentEditor *editor);
|
|
static void gimp_component_editor_alpha_changed (GimpImage *image,
|
|
GimpComponentEditor *editor);
|
|
static void gimp_component_editor_visibility_changed(GimpImage *image,
|
|
GimpChannelType channel,
|
|
GimpComponentEditor *editor);
|
|
static void gimp_component_editor_active_changed (GimpImage *image,
|
|
GimpChannelType channel,
|
|
GimpComponentEditor *editor);
|
|
static GimpImage * gimp_component_editor_drag_component (GtkWidget *widget,
|
|
GimpContext **context,
|
|
GimpChannelType *channel,
|
|
gpointer data);
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GimpComponentEditor, gimp_component_editor,
|
|
GIMP_TYPE_IMAGE_EDITOR,
|
|
G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED,
|
|
gimp_component_editor_docked_iface_init))
|
|
|
|
#define parent_class gimp_component_editor_parent_class
|
|
|
|
static GimpDockedInterface *parent_docked_iface = NULL;
|
|
|
|
|
|
static void
|
|
gimp_component_editor_class_init (GimpComponentEditorClass *klass)
|
|
{
|
|
GimpImageEditorClass *image_editor_class = GIMP_IMAGE_EDITOR_CLASS (klass);
|
|
|
|
image_editor_class->set_image = gimp_component_editor_set_image;
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_init (GimpComponentEditor *editor)
|
|
{
|
|
GtkWidget *frame;
|
|
GtkListStore *list;
|
|
|
|
frame = gtk_frame_new (NULL);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
|
gtk_box_pack_start (GTK_BOX (editor), frame, FALSE, FALSE, 0);
|
|
gtk_widget_show (frame);
|
|
|
|
list = gtk_list_store_new (N_COLUMNS,
|
|
G_TYPE_INT,
|
|
G_TYPE_BOOLEAN,
|
|
GIMP_TYPE_VIEW_RENDERER,
|
|
G_TYPE_STRING);
|
|
editor->model = GTK_TREE_MODEL (list);
|
|
|
|
editor->view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (editor->model));
|
|
g_object_unref (list);
|
|
|
|
gtk_tree_view_set_headers_visible (editor->view, FALSE);
|
|
|
|
editor->eye_column = gtk_tree_view_column_new ();
|
|
gtk_tree_view_append_column (editor->view, editor->eye_column);
|
|
|
|
editor->eye_cell = gimp_cell_renderer_toggle_new (GIMP_ICON_VISIBLE);
|
|
gtk_tree_view_column_pack_start (editor->eye_column, editor->eye_cell,
|
|
FALSE);
|
|
gtk_tree_view_column_set_attributes (editor->eye_column, editor->eye_cell,
|
|
"active", COLUMN_VISIBLE,
|
|
NULL);
|
|
|
|
g_signal_connect (editor->eye_cell, "clicked",
|
|
G_CALLBACK (gimp_component_editor_clicked),
|
|
editor);
|
|
|
|
editor->renderer_cell = gimp_cell_renderer_viewable_new ();
|
|
gtk_tree_view_insert_column_with_attributes (editor->view,
|
|
-1, NULL,
|
|
editor->renderer_cell,
|
|
"renderer", COLUMN_RENDERER,
|
|
NULL);
|
|
|
|
gtk_tree_view_insert_column_with_attributes (editor->view,
|
|
-1, NULL,
|
|
gtk_cell_renderer_text_new (),
|
|
"text", COLUMN_NAME,
|
|
NULL);
|
|
|
|
gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (editor->view));
|
|
gtk_widget_show (GTK_WIDGET (editor->view));
|
|
|
|
g_signal_connect (editor->view, "button-press-event",
|
|
G_CALLBACK (gimp_component_editor_button_press),
|
|
editor);
|
|
|
|
editor->selection = gtk_tree_view_get_selection (editor->view);
|
|
gtk_tree_selection_set_mode (editor->selection, GTK_SELECTION_MULTIPLE);
|
|
|
|
gtk_tree_selection_set_select_function (editor->selection,
|
|
gimp_component_editor_select,
|
|
editor, NULL);
|
|
|
|
gimp_dnd_component_source_add (GTK_WIDGET (editor->view),
|
|
gimp_component_editor_drag_component,
|
|
editor);
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_docked_iface_init (GimpDockedInterface *iface)
|
|
{
|
|
parent_docked_iface = g_type_interface_peek_parent (iface);
|
|
|
|
if (! parent_docked_iface)
|
|
parent_docked_iface = g_type_default_interface_peek (GIMP_TYPE_DOCKED);
|
|
|
|
iface->set_context = gimp_component_editor_set_context;
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_set_context (GimpDocked *docked,
|
|
GimpContext *context)
|
|
{
|
|
GimpComponentEditor *editor = GIMP_COMPONENT_EDITOR (docked);
|
|
GtkTreeIter iter;
|
|
gboolean iter_valid;
|
|
|
|
parent_docked_iface->set_context (docked, context);
|
|
|
|
for (iter_valid = gtk_tree_model_get_iter_first (editor->model, &iter);
|
|
iter_valid;
|
|
iter_valid = gtk_tree_model_iter_next (editor->model, &iter))
|
|
{
|
|
GimpViewRenderer *renderer;
|
|
|
|
gtk_tree_model_get (editor->model, &iter,
|
|
COLUMN_RENDERER, &renderer,
|
|
-1);
|
|
|
|
gimp_view_renderer_set_context (renderer, context);
|
|
g_object_unref (renderer);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_set_image (GimpImageEditor *editor,
|
|
GimpImage *image)
|
|
{
|
|
GimpComponentEditor *component_editor = GIMP_COMPONENT_EDITOR (editor);
|
|
|
|
if (editor->image)
|
|
{
|
|
gimp_component_editor_clear_components (component_editor);
|
|
|
|
g_signal_handlers_disconnect_by_func (editor->image,
|
|
gimp_component_editor_mode_changed,
|
|
component_editor);
|
|
g_signal_handlers_disconnect_by_func (editor->image,
|
|
gimp_component_editor_alpha_changed,
|
|
component_editor);
|
|
g_signal_handlers_disconnect_by_func (editor->image,
|
|
gimp_component_editor_visibility_changed,
|
|
component_editor);
|
|
g_signal_handlers_disconnect_by_func (editor->image,
|
|
gimp_component_editor_active_changed,
|
|
component_editor);
|
|
}
|
|
|
|
GIMP_IMAGE_EDITOR_CLASS (parent_class)->set_image (editor, image);
|
|
|
|
if (editor->image)
|
|
{
|
|
gimp_component_editor_create_components (component_editor);
|
|
|
|
g_signal_connect (editor->image, "mode-changed",
|
|
G_CALLBACK (gimp_component_editor_mode_changed),
|
|
component_editor);
|
|
g_signal_connect (editor->image, "alpha-changed",
|
|
G_CALLBACK (gimp_component_editor_alpha_changed),
|
|
component_editor);
|
|
g_signal_connect (editor->image, "component-visibility-changed",
|
|
G_CALLBACK (gimp_component_editor_visibility_changed),
|
|
component_editor);
|
|
g_signal_connect (editor->image, "component-active-changed",
|
|
G_CALLBACK (gimp_component_editor_active_changed),
|
|
component_editor);
|
|
}
|
|
}
|
|
|
|
GtkWidget *
|
|
gimp_component_editor_new (gint view_size,
|
|
GimpMenuFactory *menu_factory)
|
|
{
|
|
GimpComponentEditor *editor;
|
|
|
|
g_return_val_if_fail (view_size > 0 &&
|
|
view_size <= GIMP_VIEWABLE_MAX_PREVIEW_SIZE, NULL);
|
|
g_return_val_if_fail (GIMP_IS_MENU_FACTORY (menu_factory), NULL);
|
|
|
|
editor = g_object_new (GIMP_TYPE_COMPONENT_EDITOR,
|
|
"menu-factory", menu_factory,
|
|
"menu-identifier", "<Channels>",
|
|
"ui-path", "/channels-popup",
|
|
NULL);
|
|
|
|
gimp_component_editor_set_view_size (editor, view_size);
|
|
|
|
return GTK_WIDGET (editor);
|
|
}
|
|
|
|
void
|
|
gimp_component_editor_set_view_size (GimpComponentEditor *editor,
|
|
gint view_size)
|
|
{
|
|
GtkWidget *tree_widget;
|
|
GtkStyleContext *tree_style;
|
|
GtkBorder border;
|
|
GtkTreeIter iter;
|
|
gboolean iter_valid;
|
|
gint icon_size;
|
|
|
|
g_return_if_fail (GIMP_IS_COMPONENT_EDITOR (editor));
|
|
g_return_if_fail (view_size > 0 &&
|
|
view_size <= GIMP_VIEWABLE_MAX_PREVIEW_SIZE);
|
|
|
|
tree_widget = GTK_WIDGET (editor->view);
|
|
tree_style = gtk_widget_get_style_context (tree_widget);
|
|
|
|
gtk_style_context_save (tree_style);
|
|
gtk_style_context_add_class (tree_style, GTK_STYLE_CLASS_BUTTON);
|
|
gtk_style_context_get_border (tree_style, 0, &border);
|
|
gtk_style_context_restore (tree_style);
|
|
|
|
g_object_get (editor->eye_cell, "icon-size", &icon_size, NULL);
|
|
icon_size = MIN (icon_size, MAX (view_size - (border.left + border.right),
|
|
view_size - (border.top + border.bottom)));
|
|
g_object_set (editor->eye_cell, "icon-size", icon_size, NULL);
|
|
|
|
for (iter_valid = gtk_tree_model_get_iter_first (editor->model, &iter);
|
|
iter_valid;
|
|
iter_valid = gtk_tree_model_iter_next (editor->model, &iter))
|
|
{
|
|
GimpViewRenderer *renderer;
|
|
|
|
gtk_tree_model_get (editor->model, &iter,
|
|
COLUMN_RENDERER, &renderer,
|
|
-1);
|
|
|
|
gimp_view_renderer_set_size (renderer, view_size, 1);
|
|
g_object_unref (renderer);
|
|
}
|
|
|
|
editor->view_size = view_size;
|
|
|
|
gtk_tree_view_columns_autosize (editor->view);
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_create_components (GimpComponentEditor *editor)
|
|
{
|
|
GimpImage *image = GIMP_IMAGE_EDITOR (editor)->image;
|
|
gint n_components = 0;
|
|
GimpChannelType components[MAX_CHANNELS];
|
|
GEnumClass *enum_class;
|
|
gint i;
|
|
|
|
switch (gimp_image_get_base_type (image))
|
|
{
|
|
case GIMP_RGB:
|
|
n_components = 3;
|
|
components[0] = GIMP_CHANNEL_RED;
|
|
components[1] = GIMP_CHANNEL_GREEN;
|
|
components[2] = GIMP_CHANNEL_BLUE;
|
|
break;
|
|
|
|
case GIMP_GRAY:
|
|
n_components = 1;
|
|
components[0] = GIMP_CHANNEL_GRAY;
|
|
break;
|
|
|
|
case GIMP_INDEXED:
|
|
n_components = 1;
|
|
components[0] = GIMP_CHANNEL_INDEXED;
|
|
break;
|
|
}
|
|
|
|
if (gimp_image_has_alpha (image))
|
|
components[n_components++] = GIMP_CHANNEL_ALPHA;
|
|
|
|
enum_class = g_type_class_ref (GIMP_TYPE_CHANNEL_TYPE);
|
|
|
|
for (i = 0; i < n_components; i++)
|
|
{
|
|
GimpViewRenderer *renderer;
|
|
GtkTreeIter iter;
|
|
GEnumValue *enum_value;
|
|
const gchar *desc;
|
|
gboolean visible;
|
|
|
|
visible = gimp_image_get_component_visible (image, components[i]);
|
|
|
|
renderer = gimp_view_renderer_new (GIMP_IMAGE_EDITOR (editor)->context,
|
|
G_TYPE_FROM_INSTANCE (image),
|
|
editor->view_size, 1, FALSE);
|
|
gimp_view_renderer_set_viewable (renderer, GIMP_VIEWABLE (image));
|
|
gimp_view_renderer_remove_idle (renderer);
|
|
|
|
GIMP_VIEW_RENDERER_IMAGE (renderer)->channel = components[i];
|
|
|
|
g_signal_connect (renderer, "update",
|
|
G_CALLBACK (gimp_component_editor_renderer_update),
|
|
editor);
|
|
|
|
enum_value = g_enum_get_value (enum_class, components[i]);
|
|
desc = gimp_enum_value_get_desc (enum_class, enum_value);
|
|
|
|
gtk_list_store_append (GTK_LIST_STORE (editor->model), &iter);
|
|
|
|
gtk_list_store_set (GTK_LIST_STORE (editor->model), &iter,
|
|
COLUMN_CHANNEL, components[i],
|
|
COLUMN_VISIBLE, visible,
|
|
COLUMN_RENDERER, renderer,
|
|
COLUMN_NAME, desc,
|
|
-1);
|
|
|
|
g_object_unref (renderer);
|
|
|
|
if (gimp_image_get_component_active (image, components[i]))
|
|
gtk_tree_selection_select_iter (editor->selection, &iter);
|
|
}
|
|
|
|
g_type_class_unref (enum_class);
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_clear_components (GimpComponentEditor *editor)
|
|
{
|
|
gtk_list_store_clear (GTK_LIST_STORE (editor->model));
|
|
|
|
/* Clear the renderer so that it don't reference the viewable.
|
|
* See bug #149906.
|
|
*/
|
|
g_object_set (editor->renderer_cell, "renderer", NULL, NULL);
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_clicked (GtkCellRendererToggle *cellrenderertoggle,
|
|
gchar *path_str,
|
|
GdkModifierType state,
|
|
GimpComponentEditor *editor)
|
|
{
|
|
GtkTreePath *path;
|
|
GtkTreeIter iter;
|
|
|
|
path = gtk_tree_path_new_from_string (path_str);
|
|
|
|
if (gtk_tree_model_get_iter (editor->model, &iter, path))
|
|
{
|
|
GimpImage *image = GIMP_IMAGE_EDITOR (editor)->image;
|
|
GimpChannelType channel;
|
|
gboolean active;
|
|
|
|
gtk_tree_model_get (editor->model, &iter,
|
|
COLUMN_CHANNEL, &channel,
|
|
-1);
|
|
g_object_get (cellrenderertoggle,
|
|
"active", &active,
|
|
NULL);
|
|
|
|
gimp_image_set_component_visible (image, channel, !active);
|
|
gimp_image_flush (image);
|
|
}
|
|
|
|
gtk_tree_path_free (path);
|
|
}
|
|
|
|
static gboolean
|
|
gimp_component_editor_select (GtkTreeSelection *selection,
|
|
GtkTreeModel *model,
|
|
GtkTreePath *path,
|
|
gboolean path_currently_selected,
|
|
gpointer data)
|
|
{
|
|
GimpComponentEditor *editor = GIMP_COMPONENT_EDITOR (data);
|
|
GtkTreeIter iter;
|
|
GimpChannelType channel;
|
|
gboolean active;
|
|
|
|
gtk_tree_model_get_iter (editor->model, &iter, path);
|
|
gtk_tree_model_get (editor->model, &iter,
|
|
COLUMN_CHANNEL, &channel,
|
|
-1);
|
|
|
|
active = gimp_image_get_component_active (GIMP_IMAGE_EDITOR (editor)->image,
|
|
channel);
|
|
|
|
return active != path_currently_selected;
|
|
}
|
|
|
|
static gboolean
|
|
gimp_component_editor_button_press (GtkWidget *widget,
|
|
GdkEventButton *bevent,
|
|
GimpComponentEditor *editor)
|
|
{
|
|
GtkTreeViewColumn *column;
|
|
GtkTreePath *path;
|
|
|
|
editor->clicked_component = -1;
|
|
|
|
if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
|
|
bevent->x,
|
|
bevent->y,
|
|
&path, &column, NULL, NULL))
|
|
{
|
|
GtkTreeIter iter;
|
|
GimpChannelType channel;
|
|
gboolean active;
|
|
|
|
active = gtk_tree_selection_path_is_selected (editor->selection, path);
|
|
|
|
gtk_tree_model_get_iter (editor->model, &iter, path);
|
|
|
|
gtk_tree_path_free (path);
|
|
|
|
gtk_tree_model_get (editor->model, &iter,
|
|
COLUMN_CHANNEL, &channel,
|
|
-1);
|
|
|
|
editor->clicked_component = channel;
|
|
|
|
if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
|
|
{
|
|
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (editor), (GdkEvent *) bevent);
|
|
}
|
|
else if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 1 &&
|
|
column != editor->eye_column)
|
|
{
|
|
GimpImage *image = GIMP_IMAGE_EDITOR (editor)->image;
|
|
|
|
gimp_image_set_component_active (image, channel, ! active);
|
|
gimp_image_flush (image);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
gimp_component_editor_get_iter (GimpComponentEditor *editor,
|
|
GimpChannelType channel,
|
|
GtkTreeIter *iter)
|
|
{
|
|
gint index;
|
|
|
|
index = gimp_image_get_component_index (GIMP_IMAGE_EDITOR (editor)->image,
|
|
channel);
|
|
|
|
if (index != -1)
|
|
return gtk_tree_model_iter_nth_child (editor->model, iter, NULL, index);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_renderer_update (GimpViewRenderer *renderer,
|
|
GimpComponentEditor *editor)
|
|
{
|
|
GimpChannelType channel = GIMP_VIEW_RENDERER_IMAGE (renderer)->channel;
|
|
GtkTreeIter iter;
|
|
|
|
if (gimp_component_editor_get_iter (editor, channel, &iter))
|
|
{
|
|
GtkTreePath *path;
|
|
|
|
path = gtk_tree_model_get_path (editor->model, &iter);
|
|
gtk_tree_model_row_changed (editor->model, path, &iter);
|
|
gtk_tree_path_free (path);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_mode_changed (GimpImage *image,
|
|
GimpComponentEditor *editor)
|
|
{
|
|
gimp_component_editor_clear_components (editor);
|
|
gimp_component_editor_create_components (editor);
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_alpha_changed (GimpImage *image,
|
|
GimpComponentEditor *editor)
|
|
{
|
|
gimp_component_editor_clear_components (editor);
|
|
gimp_component_editor_create_components (editor);
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_visibility_changed (GimpImage *image,
|
|
GimpChannelType channel,
|
|
GimpComponentEditor *editor)
|
|
{
|
|
GtkTreeIter iter;
|
|
|
|
if (gimp_component_editor_get_iter (editor, channel, &iter))
|
|
{
|
|
gboolean visible = gimp_image_get_component_visible (image, channel);
|
|
|
|
gtk_list_store_set (GTK_LIST_STORE (editor->model), &iter,
|
|
COLUMN_VISIBLE, visible,
|
|
-1);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_component_editor_active_changed (GimpImage *image,
|
|
GimpChannelType channel,
|
|
GimpComponentEditor *editor)
|
|
{
|
|
GtkTreeIter iter;
|
|
|
|
if (gimp_component_editor_get_iter (editor, channel, &iter))
|
|
{
|
|
gboolean active = gimp_image_get_component_active (image, channel);
|
|
|
|
if (gtk_tree_selection_iter_is_selected (editor->selection, &iter) !=
|
|
active)
|
|
{
|
|
if (active)
|
|
gtk_tree_selection_select_iter (editor->selection, &iter);
|
|
else
|
|
gtk_tree_selection_unselect_iter (editor->selection, &iter);
|
|
}
|
|
}
|
|
}
|
|
|
|
static GimpImage *
|
|
gimp_component_editor_drag_component (GtkWidget *widget,
|
|
GimpContext **context,
|
|
GimpChannelType *channel,
|
|
gpointer data)
|
|
{
|
|
GimpComponentEditor *editor = GIMP_COMPONENT_EDITOR (data);
|
|
|
|
if (GIMP_IMAGE_EDITOR (editor)->image &&
|
|
editor->clicked_component != -1)
|
|
{
|
|
if (channel)
|
|
*channel = editor->clicked_component;
|
|
|
|
if (context)
|
|
*context = GIMP_IMAGE_EDITOR (editor)->context;
|
|
|
|
return GIMP_IMAGE_EDITOR (editor)->image;
|
|
}
|
|
|
|
return NULL;
|
|
}
|