gimpchanneltreeview.c 13.5 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2 3
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
4
 * gimpchanneltreeview.c
5
 * Copyright (C) 2001-2004 Michael Natterer <mitch@gimp.org>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * 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 <gtk/gtk.h>

26
#include "libgimpbase/gimpbase.h"
27
#include "libgimpcolor/gimpcolor.h"
28 29
#include "libgimpwidgets/gimpwidgets.h"

30 31
#include "widgets-types.h"

32 33 34
#include "core/gimpchannel.h"
#include "core/gimpcontainer.h"
#include "core/gimpimage.h"
35
#include "core/gimpimage-undo.h"
36 37
#include "core/gimplayer.h"
#include "core/gimplayermask.h"
38

39
#include "gimpchanneltreeview.h"
40
#include "gimpcomponenteditor.h"
41
#include "gimpcontainerview.h"
42
#include "gimpdnd.h"
43
#include "gimpdocked.h"
44
#include "gimphelp-ids.h"
45
#include "gimpwidgets-utils.h"
46

47
#include "gimp-intl.h"
48 49


50
static void  gimp_channel_tree_view_view_iface_init   (GimpContainerViewInterface *iface);
51

52 53 54
static GObject * gimp_channel_tree_view_constructor   (GType              type,
                                                       guint              n_params,
                                                       GObjectConstructParam *params);
55 56 57 58
static void   gimp_channel_tree_view_drop_viewable    (GimpContainerTreeView *view,
                                                       GimpViewable      *src_viewable,
                                                       GimpViewable      *dest_viewable,
                                                       GtkTreeViewDropPosition  drop_pos);
59
static void   gimp_channel_tree_view_drop_component   (GimpContainerTreeView *tree_view,
60
                                                       GimpImage         *image,
61 62 63
                                                       GimpChannelType    component,
                                                       GimpViewable      *dest_viewable,
                                                       GtkTreeViewDropPosition drop_pos);
64
static void   gimp_channel_tree_view_set_image        (GimpItemTreeView  *item_view,
65
                                                       GimpImage         *image);
66
static GimpItem * gimp_channel_tree_view_item_new     (GimpImage         *image);
67

68
static void   gimp_channel_tree_view_set_context      (GimpContainerView *view,
69
                                                       GimpContext       *context);
70
static void   gimp_channel_tree_view_set_view_size    (GimpContainerView *view);
71

72

73 74 75
G_DEFINE_TYPE_WITH_CODE (GimpChannelTreeView, gimp_channel_tree_view,
                         GIMP_TYPE_DRAWABLE_TREE_VIEW,
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONTAINER_VIEW,
76
                                                gimp_channel_tree_view_view_iface_init))
77 78 79

#define parent_class gimp_channel_tree_view_parent_class

80
static GimpContainerViewInterface *parent_view_iface = NULL;
81 82 83


static void
84
gimp_channel_tree_view_class_init (GimpChannelTreeViewClass *klass)
85
{
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
  GObjectClass               *object_class = G_OBJECT_CLASS (klass);
  GimpContainerTreeViewClass *view_class   = GIMP_CONTAINER_TREE_VIEW_CLASS (klass);
  GimpItemTreeViewClass      *iv_class     = GIMP_ITEM_TREE_VIEW_CLASS (klass);

  object_class->constructor  = gimp_channel_tree_view_constructor;

  view_class->drop_viewable  = gimp_channel_tree_view_drop_viewable;
  view_class->drop_component = gimp_channel_tree_view_drop_component;

  iv_class->set_image        = gimp_channel_tree_view_set_image;

  iv_class->item_type        = GIMP_TYPE_CHANNEL;
  iv_class->signal_name      = "active-channel-changed";

  iv_class->get_container    = gimp_image_get_channels;
  iv_class->get_active_item  = (GimpGetItemFunc) gimp_image_get_active_channel;
  iv_class->set_active_item  = (GimpSetItemFunc) gimp_image_set_active_channel;
  iv_class->reorder_item     = (GimpReorderItemFunc) gimp_image_position_channel;
  iv_class->add_item         = (GimpAddItemFunc) gimp_image_add_channel;
  iv_class->remove_item      = (GimpRemoveItemFunc) gimp_image_remove_channel;
  iv_class->new_item         = gimp_channel_tree_view_item_new;

  iv_class->action_group        = "channels";
  iv_class->activate_action     = "channels-edit-attributes";
  iv_class->edit_action         = "channels-edit-attributes";
  iv_class->new_action          = "channels-new";
  iv_class->new_default_action  = "channels-new-last-values";
  iv_class->raise_action        = "channels-raise";
  iv_class->raise_top_action    = "channels-raise-to-top";
  iv_class->lower_action        = "channels-lower";
  iv_class->lower_bottom_action = "channels-lower-to-bottom";
  iv_class->duplicate_action    = "channels-duplicate";
  iv_class->delete_action       = "channels-delete";
  iv_class->reorder_desc        = _("Reorder Channel");
120 121
}

122 123 124 125 126
static void
gimp_channel_tree_view_view_iface_init (GimpContainerViewInterface *view_iface)
{
  parent_view_iface = g_type_interface_peek_parent (view_iface);

127
  view_iface->set_context   = gimp_channel_tree_view_set_context;
128
  view_iface->set_view_size = gimp_channel_tree_view_set_view_size;
129 130
}

131 132 133 134 135
static void
gimp_channel_tree_view_init (GimpChannelTreeView *view)
{
}

136 137 138 139 140
static GObject *
gimp_channel_tree_view_constructor (GType                  type,
                                    guint                  n_params,
                                    GObjectConstructParam *params)
{
141 142 143 144
  GObject               *object;
  GimpEditor            *editor;
  GimpChannelTreeView   *view;
  GimpContainerTreeView *tree_view;
145 146 147

  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);

148 149 150 151
  editor    = GIMP_EDITOR (object);
  view      = GIMP_CHANNEL_TREE_VIEW (object);
  tree_view = GIMP_CONTAINER_TREE_VIEW (object);

152 153 154 155
  gimp_dnd_viewable_dest_add  (GTK_WIDGET (tree_view->view), GIMP_TYPE_LAYER,
                               NULL, tree_view);
  gimp_dnd_viewable_dest_add  (GTK_WIDGET (tree_view->view), GIMP_TYPE_LAYER_MASK,
                               NULL, tree_view);
156 157
  gimp_dnd_component_dest_add (GTK_WIDGET (tree_view->view),
                               NULL, tree_view);
158

159
  view->toselection_button =
160 161 162 163
    gimp_editor_add_action_button (GIMP_EDITOR (view), "channels",
                                   "channels-selection-replace",
                                   "channels-selection-add",
                                   GDK_SHIFT_MASK,
164 165 166 167
                                   "channels-selection-subtract",
                                   GDK_CONTROL_MASK,
                                   "channels-selection-intersect",
                                   GDK_SHIFT_MASK | GDK_CONTROL_MASK,
168
                                   NULL);
169
  gimp_container_view_enable_dnd (GIMP_CONTAINER_VIEW (view),
170 171
                                  GTK_BUTTON (view->toselection_button),
                                  GIMP_TYPE_CHANNEL);
172
  gtk_box_reorder_child (GTK_BOX (GIMP_EDITOR (view)->button_box),
173
                         view->toselection_button, 5);
174

175
  return object;
176 177
}

178

179 180
/*  GimpContainerTreeView methods  */

181 182 183 184 185 186
static void
gimp_channel_tree_view_drop_viewable (GimpContainerTreeView   *tree_view,
                                      GimpViewable            *src_viewable,
                                      GimpViewable            *dest_viewable,
                                      GtkTreeViewDropPosition  drop_pos)
{
187
  GimpItemTreeView      *item_view = GIMP_ITEM_TREE_VIEW (tree_view);
188 189 190 191
  GimpItemTreeViewClass *item_view_class;

  item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (item_view);

192
  if (GIMP_IS_DRAWABLE (src_viewable) &&
193
      (item_view->image != gimp_item_get_image (GIMP_ITEM (src_viewable)) ||
194
       G_TYPE_FROM_INSTANCE (src_viewable) != item_view_class->item_type))
195 196
    {
      GimpItem *new_item;
197
      gint      index = -1;
198

199 200
      if (dest_viewable)
        {
201
          index = gimp_image_get_channel_index (item_view->image,
202
                                                GIMP_CHANNEL (dest_viewable));
203

204 205 206
          if (drop_pos == GTK_TREE_VIEW_DROP_AFTER)
            index++;
        }
207 208

      new_item = gimp_item_convert (GIMP_ITEM (src_viewable),
209
                                    item_view->image,
210
                                    item_view_class->item_type);
211

212 213
      gimp_item_set_linked (new_item, FALSE, FALSE);

214 215
      item_view_class->add_item (item_view->image, new_item, index);
      gimp_image_flush (item_view->image);
216
      return;
217
    }
218 219 220 221 222

  GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewable (tree_view,
                                                                src_viewable,
                                                                dest_viewable,
                                                                drop_pos);
223 224
}

225 226 227 228 229 230 231
static void
gimp_channel_tree_view_drop_component (GimpContainerTreeView   *tree_view,
                                       GimpImage               *src_image,
                                       GimpChannelType          component,
                                       GimpViewable            *dest_viewable,
                                       GtkTreeViewDropPosition  drop_pos)
{
232 233 234
  GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (tree_view);
  GimpItem         *new_item;
  gint              index     = -1;
235 236 237
  const gchar      *desc;
  gchar            *name;

238 239
  if (dest_viewable)
    {
240
      index = gimp_image_get_channel_index (item_view->image,
241
                                            GIMP_CHANNEL (dest_viewable));
242

243 244 245
      if (drop_pos == GTK_TREE_VIEW_DROP_AFTER)
        index++;
    }
246 247 248 249 250

  gimp_enum_get_value (GIMP_TYPE_CHANNEL_TYPE, component,
                       NULL, NULL, &desc, NULL);
  name = g_strdup_printf (_("%s Channel Copy"), desc);

251 252
  new_item = GIMP_ITEM (gimp_channel_new_from_component (src_image, component,
                                                         name, NULL));
253 254 255 256

  /*  copied components are invisible by default so subsequent copies
   *  of components don't affect each other
   */
257
  gimp_item_set_visible (new_item, FALSE, FALSE);
258 259 260

  g_free (name);

261 262
  if (src_image != item_view->image)
    GIMP_ITEM_GET_CLASS (new_item)->convert (new_item, item_view->image);
263

264 265
  gimp_image_add_channel (item_view->image, GIMP_CHANNEL (new_item), index);
  gimp_image_flush (item_view->image);
266 267 268
}


269
/*  GimpItemTreeView methods  */
270 271

static void
272
gimp_channel_tree_view_set_image (GimpItemTreeView *item_view,
273
                                  GimpImage        *image)
274
{
275
  GimpChannelTreeView *channel_view = GIMP_CHANNEL_TREE_VIEW (item_view);
276

277
  if (! channel_view->component_editor)
278
    {
279
      GimpContainerView *view = GIMP_CONTAINER_VIEW (item_view);
280
      gint               view_size;
281

282
      view_size = gimp_container_view_get_view_size (view, NULL);
283

284
      channel_view->component_editor =
285
        gimp_component_editor_new (view_size,
286
                                   GIMP_EDITOR (item_view)->menu_factory);
287
      gimp_docked_set_context (GIMP_DOCKED (channel_view->component_editor),
288
                               gimp_container_view_get_context (view));
289 290 291 292 293
      gtk_box_pack_start (GTK_BOX (item_view), channel_view->component_editor,
                          FALSE, FALSE, 0);
      gtk_box_reorder_child (GTK_BOX (item_view),
                             channel_view->component_editor, 0);
    }
294

295
  if (! image)
296
    gtk_widget_hide (channel_view->component_editor);
297

298
  gimp_image_editor_set_image (GIMP_IMAGE_EDITOR (channel_view->component_editor),
299
                               image);
300

301
  GIMP_ITEM_TREE_VIEW_CLASS (parent_class)->set_image (item_view, image);
302

303
  if (item_view->image)
304
    gtk_widget_show (channel_view->component_editor);
305 306
}

307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
static GimpItem *
gimp_channel_tree_view_item_new (GimpImage *image)
{
  GimpChannel *new_channel;
  GimpRGB      color;

  gimp_rgba_set (&color, 0.0, 0.0, 0.0, 0.5);

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE,
                               _("New Channel"));

  new_channel = gimp_channel_new (image,
                                  gimp_image_get_width (image),
                                  gimp_image_get_height (image),
                                  _("Empty Channel"), &color);

  gimp_image_add_channel (image, new_channel, -1);

  gimp_image_undo_group_end (image);

  return GIMP_ITEM (new_channel);
}

330 331 332

/*  GimpContainerView methods  */

333
static void
334 335
gimp_channel_tree_view_set_context (GimpContainerView *view,
                                    GimpContext       *context)
336
{
337
  GimpChannelTreeView *channel_view = GIMP_CHANNEL_TREE_VIEW (view);
338

339
  parent_view_iface->set_context (view, context);
340

341
  if (channel_view->component_editor)
342 343
    gimp_docked_set_context (GIMP_DOCKED (channel_view->component_editor),
                             context);
344
}
345 346

static void
347
gimp_channel_tree_view_set_view_size (GimpContainerView *view)
348
{
349 350
  GimpChannelTreeView *channel_view = GIMP_CHANNEL_TREE_VIEW (view);
  gint                 view_size;
351

352 353 354
  parent_view_iface->set_view_size (view);

  view_size = gimp_container_view_get_view_size (view, NULL);
355 356

  if (channel_view->component_editor)
357 358
    gimp_component_editor_set_view_size (GIMP_COMPONENT_EDITOR (channel_view->component_editor),
                                         view_size);
359
}