Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  gimpcontainertreeview-dnd.c   Sprache: C

 

/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * gimpcontainertreeview-dnd.c
 * Copyright (C) 2003-2009 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 "widgets-types.h"

#include "core/gimpcontainer.h"
#include "core/gimpitem.h"
#include "core/gimpviewable.h"

#include "gimpcontainertreestore.h"
#include "gimpcontainertreeview.h"
#include "gimpcontainertreeview-dnd.h"
#include "gimpcontainertreeview-private.h"
#include "gimpcontainerview.h"
#include "gimpdnd.h"
#include "gimpviewrenderer.h"
#include "gimpselectiondata.h"


static gint
gimp_container_tree_view_viewable_sort (GimpViewable          *v1,
                                        GimpViewable          *v2,
                                        GimpContainerTreeView *tree_view)
{
  GimpContainerView *view        = GIMP_CONTAINER_VIEW (tree_view);
  GimpViewable      *parent1;
  GimpViewable      *parent2;
  GimpContainer     *container1  = NULL;
  GimpContainer     *container2  = NULL;
  GimpContainer     *container   = gimp_container_view_get_container (view);
  gint               index1      = -1;
  gint               index2      = -1;
  gint               depth1;
  gint               depth2;

  parent1 = gimp_viewable_get_parent (v1);
  parent2 = gimp_viewable_get_parent (v2);

  if (parent1)
    container1 = gimp_viewable_get_children (parent1);
  else if (gimp_container_have (container, GIMP_OBJECT (v1)))
    container1 = container;
  else
    container1 = gimp_item_get_container (GIMP_ITEM (v1));

  if (parent2)
    container2 = gimp_viewable_get_children (parent2);
  else if (gimp_container_have (container, GIMP_OBJECT (v2)))
    container2 = container;
  else
    container2 = gimp_item_get_container (GIMP_ITEM (v2));

  g_return_val_if_fail (container1 && container2, 0);

  if (container1 == container2)
    {
      index1 = gimp_container_get_child_index (container1, GIMP_OBJECT (v1));
      index2 = gimp_container_get_child_index (container2, GIMP_OBJECT (v2));

      return index1 < index2 ? -1 : (index1 > index2 ? 1 : 0);
    }

  depth1 = gimp_viewable_get_depth (v1);
  depth2 = gimp_viewable_get_depth (v2);

  if (depth1 == depth2)
    {
      return gimp_container_tree_view_viewable_sort (parent1, parent2, tree_view);
    }
  else if (depth1 > depth2)
    {
      depth1 = gimp_viewable_get_depth (parent1);
      while (depth1 > depth2)
        {
          parent1 = gimp_viewable_get_parent (parent1);
          depth1 = gimp_viewable_get_depth (parent1);
        }
      return gimp_container_tree_view_viewable_sort (parent1, v2, tree_view);
    }
  else /* if (depth1 < depth2) */
    {
      depth2 = gimp_viewable_get_depth (parent2);
      while (depth1 < depth2)
        {
          parent2 = gimp_viewable_get_parent (parent2);
          depth2 = gimp_viewable_get_depth (parent2);
        }
      return gimp_container_tree_view_viewable_sort (v1, parent2, tree_view);
    }
}

/**
 * gimp_container_tree_view_drop_status:
 * @tree_view:
 * @context:
 * @x:
 * @y:
 * @time:
 * @return_path: the #GtkTreePath of the drop position if the drop is
 *               possible.
 * @return_atom:
 * @return_src_type: the type of drag'n drop.
 * @return_src: allocated #GList of #GimpViewable being dragged.
 * @return_dest: the #GimpViewable you are dropping on.
 * @return_pos: the drop position (before, after or into @return_dest).
 *
 * Check whether the current drag can be dropped into @tree_view at
 * position (@x, @y). If so, the various return value information will
 * be optionally filled.
 * Note: if @return_src is not %NULL, hence is filled, it must be freed
 * with g_list_free().
 *
 * Returns: %TRUE is the drop is possible, %FALSE otherwise.
 */

static gboolean
gimp_container_tree_view_drop_status (GimpContainerTreeView    *tree_view,
                                      GdkDragContext           *context,
                                      gint                      x,
                                      gint                      y,
                                      guint                     time,
                                      GtkTreePath             **return_path,
                                      GdkAtom                  *return_atom,
                                      GimpDndType              *return_src_type,
                                      GList                   **return_src,
                                      GimpViewable            **return_dest,
                                      GtkTreeViewDropPosition  *return_pos)
{
  GList                   *src_viewables = NULL;
  GimpViewable            *dest_viewable = NULL;
  GtkTreePath             *drop_path     = NULL;
  GtkTargetList           *target_list;
  GdkAtom                  target_atom;
  GimpDndType              src_type;
  GtkTreeViewDropPosition  drop_pos      = GTK_TREE_VIEW_DROP_BEFORE;
  GdkDragAction            drag_action   = 0;

  if (! gimp_container_view_get_container (GIMP_CONTAINER_VIEW (tree_view)) ||
      ! gimp_container_view_get_reorderable (GIMP_CONTAINER_VIEW (tree_view)))
    goto drop_impossible;

  target_list = gtk_drag_dest_get_target_list (GTK_WIDGET (tree_view->view));
  target_atom = gtk_drag_dest_find_target (GTK_WIDGET (tree_view->view),
                                           context, target_list);
  if (! gtk_target_list_find (target_list, target_atom, &src_type))
    goto drop_impossible;

  switch (src_type)
    {
    case GIMP_DND_TYPE_URI_LIST:
    case GIMP_DND_TYPE_TEXT_PLAIN:
    case GIMP_DND_TYPE_NETSCAPE_URL:
    case GIMP_DND_TYPE_COLOR:
    case GIMP_DND_TYPE_SVG:
    case GIMP_DND_TYPE_SVG_XML:
    case GIMP_DND_TYPE_COMPONENT:
    case GIMP_DND_TYPE_PIXBUF:
      break;

    case GIMP_DND_TYPE_XDS:
    case GIMP_DND_TYPE_IMAGE:
    case GIMP_DND_TYPE_LAYER:
    case GIMP_DND_TYPE_CHANNEL:
    case GIMP_DND_TYPE_LAYER_MASK:
    case GIMP_DND_TYPE_PATH:
    case GIMP_DND_TYPE_BRUSH:
    case GIMP_DND_TYPE_PATTERN:
    case GIMP_DND_TYPE_GRADIENT:
    case GIMP_DND_TYPE_PALETTE:
    case GIMP_DND_TYPE_FONT:
    case GIMP_DND_TYPE_BUFFER:
    case GIMP_DND_TYPE_IMAGEFILE:
    case GIMP_DND_TYPE_TEMPLATE:
    case GIMP_DND_TYPE_TOOL_ITEM:
    case GIMP_DND_TYPE_NOTEBOOK_TAB:
      /* Various GimpViewable drag data. */
      {
        GtkWidget    *src_widget = gtk_drag_get_source_widget (context);
        GimpViewable *src_viewable  = NULL;

        if (! src_widget)
          goto drop_impossible;

        src_viewable = gimp_dnd_get_drag_viewable (src_widget);

        if (! GIMP_IS_VIEWABLE (src_viewable))
          goto drop_impossible;

        src_viewables = g_list_prepend (src_viewables, src_viewable);
      }
      break;

    case GIMP_DND_TYPE_CHANNEL_LIST:
    case GIMP_DND_TYPE_LAYER_LIST:
    case GIMP_DND_TYPE_PATH_LIST:
      /* Various GimpViewable list (GList) drag data. */
      {
        GtkWidget *src_widget = gtk_drag_get_source_widget (context);
        GList     *iter;

        if (! src_widget)
          goto drop_impossible;

        src_viewables = gimp_dnd_get_drag_list (src_widget);

        if (! src_viewables)
          goto drop_impossible;

        for (iter = src_viewables; iter; iter = iter->next)
          if (! GIMP_IS_VIEWABLE (iter->data))
            {
              g_warning ("%s: contents of the viewable list has the wrong type '%s'.",
                         G_STRFUNC, G_OBJECT_TYPE_NAME (iter->data));
              goto drop_impossible;
            }
      }
      break;

    default:
      goto drop_impossible;
      break;
    }

  gtk_tree_view_convert_widget_to_bin_window_coords (tree_view->view, x, y, &x, &y);
  if (gtk_tree_view_get_path_at_pos (tree_view->view, x, y,
                                     &drop_path, NULL, NULL, NULL))
    {
      GimpViewRenderer *renderer;
      GtkTreeIter       iter;
      GdkRectangle      cell_area;

      gtk_tree_model_get_iter (tree_view->model, &iter, drop_path);

      renderer = gimp_container_tree_store_get_renderer (GIMP_CONTAINER_TREE_STORE (tree_view->model),
                                                         &iter);

      dest_viewable = renderer->viewable;

      g_object_unref (renderer);

      gtk_tree_view_get_cell_area (tree_view->view, drop_path, NULL, &cell_area);

      if (gimp_viewable_get_children (dest_viewable))
        {
          if (gtk_tree_view_row_expanded (tree_view->view, drop_path))
            {
              if (y >= (cell_area.y + cell_area.height / 2))
                drop_pos = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
              else
                drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
            }
          else
            {
              if (y >= (cell_area.y + 2 * (cell_area.height / 3)))
                drop_pos = GTK_TREE_VIEW_DROP_AFTER;
              else if (y <= (cell_area.y + cell_area.height / 3))
                drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
              else
                drop_pos = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
            }
        }
      else
        {
          if (y >= (cell_area.y + cell_area.height / 2))
            drop_pos = GTK_TREE_VIEW_DROP_AFTER;
          else
            drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
        }
    }
  else
    {
      GtkTreeIter iter;
      gint        n_children;

      if (y < 0)
        goto drop_impossible;

      n_children = gtk_tree_model_iter_n_children (tree_view->model, NULL);

      if (n_children > 0 &&
          gtk_tree_model_iter_nth_child (tree_view->model, &iter,
                                         NULL, n_children - 1))
        {
          GimpViewRenderer *renderer;

          renderer = gimp_container_tree_store_get_renderer (GIMP_CONTAINER_TREE_STORE (tree_view->model),
                                                             &iter);

          drop_path     = gtk_tree_model_get_path (tree_view->model, &iter);
          dest_viewable = renderer->viewable;
          drop_pos      = GTK_TREE_VIEW_DROP_AFTER;

          g_object_unref (renderer);
        }
    }

  if (dest_viewable || tree_view->priv->dnd_drop_to_empty)
    {
      if (GIMP_CONTAINER_TREE_VIEW_GET_CLASS (tree_view)->drop_possible (tree_view,
                                                                         src_type,
                                                                         src_viewables,
                                                                         dest_viewable,
                                                                         drop_path,
                                                                         drop_pos,
                                                                         &drop_pos,
                                                                         &drag_action))
        {
          gdk_drag_status (context, drag_action, time);

          if (return_path)
            *return_path = drop_path;
          else
            gtk_tree_path_free (drop_path);

          if (return_atom)
            *return_atom = target_atom;

          if (return_src)
            {
              src_viewables = g_list_sort_with_data (src_viewables,
                                                     (GCompareDataFunc) gimp_container_tree_view_viewable_sort,
                                                     tree_view);
              *return_src = src_viewables;
            }
          else
            {
              g_list_free (src_viewables);
            }

          if (return_dest)
            *return_dest = dest_viewable;

          if (return_pos)
            *return_pos = drop_pos;

          return TRUE;
        }
    }

 drop_impossible:

  g_list_free (src_viewables);
  gtk_tree_path_free (drop_path);
  gdk_drag_status (context, 0, time);

  return FALSE;
}

#define SCROLL_DISTANCE 30
#define SCROLL_STEP     10
#define SCROLL_INTERVAL  5
/* #define SCROLL_DEBUG 1 */

static gboolean
gimp_container_tree_view_scroll_timeout (gpointer data)
{
  GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (data);
  GtkAdjustment         *adj;
  gdouble                new_value;

  adj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (tree_view->view));

#ifdef SCROLL_DEBUG
  g_print ("scroll_timeout: scrolling by %d\n", SCROLL_STEP);
#endif

  if (tree_view->priv->scroll_dir == GDK_SCROLL_UP)
    new_value = gtk_adjustment_get_value (adj) - SCROLL_STEP;
  else
    new_value = gtk_adjustment_get_value (adj) + SCROLL_STEP;

  new_value = CLAMP (new_value,
                     gtk_adjustment_get_lower (adj),
                     gtk_adjustment_get_upper (adj) -
                     gtk_adjustment_get_page_size (adj));

  gtk_adjustment_set_value (adj, new_value);

  if (tree_view->priv->scroll_timeout_id)
    {
      g_source_remove (tree_view->priv->scroll_timeout_id);

      tree_view->priv->scroll_timeout_id =
        g_timeout_add (tree_view->priv->scroll_timeout_interval,
                       gimp_container_tree_view_scroll_timeout,
                       tree_view);
    }

  return FALSE;
}

void
gimp_container_tree_view_drag_failed (GtkWidget             *widget,
                                      GdkDragContext        *context,
                                      GtkDragResult          result,
                                      GimpContainerTreeView *tree_view)
{
  if (tree_view->priv->scroll_timeout_id)
    {
      g_source_remove (tree_view->priv->scroll_timeout_id);
      tree_view->priv->scroll_timeout_id = 0;
    }

  gtk_tree_view_set_drag_dest_row (tree_view->view, NULL, 0);
}

void
gimp_container_tree_view_drag_leave (GtkWidget             *widget,
                                     GdkDragContext        *context,
                                     guint                  time,
                                     GimpContainerTreeView *tree_view)
{
  if (tree_view->priv->scroll_timeout_id)
    {
      g_source_remove (tree_view->priv->scroll_timeout_id);
      tree_view->priv->scroll_timeout_id = 0;
    }

  gtk_tree_view_set_drag_dest_row (tree_view->view, NULL, 0);
}

gboolean
gimp_container_tree_view_drag_motion (GtkWidget             *widget,
                                      GdkDragContext        *context,
                                      gint                   x,
                                      gint                   y,
                                      guint                  time,
                                      GimpContainerTreeView *tree_view)
{
  GtkAllocation            allocation;
  GtkTreePath             *drop_path;
  GtkTreeViewDropPosition  drop_pos;

  gtk_widget_get_allocation (widget, &allocation);

  if (y < SCROLL_DISTANCE || y > (allocation.height - SCROLL_DISTANCE))
    {
      gint distance;

      if (y < SCROLL_DISTANCE)
        {
          tree_view->priv->scroll_dir = GDK_SCROLL_UP;
          distance = MIN (-y, -1);
        }
      else
        {
          tree_view->priv->scroll_dir = GDK_SCROLL_DOWN;
          distance = MAX (allocation.height - y, 1);
        }

      tree_view->priv->scroll_timeout_interval = SCROLL_INTERVAL * ABS (distance);

#ifdef SCROLL_DEBUG
      g_print ("drag_motion: scroll_distance = %d  scroll_interval = %d\n",
               distance, tree_view->priv->scroll_timeout_interval);
#endif

      if (! tree_view->priv->scroll_timeout_id)
        tree_view->priv->scroll_timeout_id =
          g_timeout_add (tree_view->priv->scroll_timeout_interval,
                         gimp_container_tree_view_scroll_timeout,
                         tree_view);
    }
  else if (tree_view->priv->scroll_timeout_id)
    {
      g_source_remove (tree_view->priv->scroll_timeout_id);
      tree_view->priv->scroll_timeout_id = 0;
    }

  if (gimp_container_tree_view_drop_status (tree_view,
                                            context, x, y, time,
                                            &drop_path, NULL, NULL, NULL, NULL,
                                            &drop_pos))
    {
      gtk_tree_view_set_drag_dest_row (tree_view->view, drop_path, drop_pos);
      gtk_tree_path_free (drop_path);
    }
  else
    {
      gtk_tree_view_set_drag_dest_row (tree_view->view, NULL, 0);
    }

  /*  always return TRUE so drag_leave() is called  */
  return TRUE;
}

gboolean
gimp_container_tree_view_drag_drop (GtkWidget             *widget,
                                    GdkDragContext        *context,
                                    gint                   x,
                                    gint                   y,
                                    guint                  time,
                                    GimpContainerTreeView *tree_view)
{
  GimpDndType              src_type;
  GList                   *src_viewables;
  GimpViewable            *dest_viewable;
  GdkAtom                  target;
  GtkTreeViewDropPosition  drop_pos;

  if (tree_view->priv->scroll_timeout_id)
    {
      g_source_remove (tree_view->priv->scroll_timeout_id);
      tree_view->priv->scroll_timeout_id = 0;
    }

  if (gimp_container_tree_view_drop_status (tree_view,
                                            context, x, y, time,
                                            NULL, &target, &src_type,
                                            &src_viewables,
                                            &dest_viewable, &drop_pos))
    {
      GimpContainerTreeViewClass *tree_view_class;

      tree_view_class = GIMP_CONTAINER_TREE_VIEW_GET_CLASS (tree_view);

      if (src_viewables)
        {
          gboolean success = TRUE;

          /* XXX: Make GimpContainerTreeViewClass::drop_viewable()
           * return success?
           */

          tree_view_class->drop_viewables (tree_view, src_viewables,
                                           dest_viewable, drop_pos);

          gtk_drag_finish (context, success, FALSE, time);
          g_list_free (src_viewables);
        }
      else
        {
          /* Necessary for instance for dragging color components onto
           * item dialogs.
           */

          gtk_drag_get_data (widget, context, target, time);
        }

      return TRUE;
    }

  return FALSE;
}

void
gimp_container_tree_view_drag_data_received (GtkWidget             *widget,
                                             GdkDragContext        *context,
                                             gint                   x,
                                             gint                   y,
                                             GtkSelectionData      *selection_data,
                                             guint                  info,
                                             guint                  time,
                                             GimpContainerTreeView *tree_view)
{
  GimpViewable            *dest_viewable;
  GtkTreeViewDropPosition  drop_pos;
  gboolean                 success = FALSE;

  if (gimp_container_tree_view_drop_status (tree_view,
                                            context, x, y, time,
                                            NULL, NULL, NULL, NULL,
                                            &dest_viewable, &drop_pos))
    {
      GimpContainerTreeViewClass *tree_view_class;

      tree_view_class = GIMP_CONTAINER_TREE_VIEW_GET_CLASS (tree_view);

      switch (info)
        {
        case GIMP_DND_TYPE_URI_LIST:
        case GIMP_DND_TYPE_TEXT_PLAIN:
        case GIMP_DND_TYPE_NETSCAPE_URL:
          if (tree_view_class->drop_uri_list)
            {
              GList *uri_list;

              uri_list = gimp_selection_data_get_uri_list (selection_data);

              if (uri_list)
                {
                  tree_view_class->drop_uri_list (tree_view, uri_list,
                                                  dest_viewable, drop_pos);

                  g_list_free_full (uri_list, (GDestroyNotify) g_free);

                  success = TRUE;
                }
            }
          break;

        case GIMP_DND_TYPE_COLOR:
          if (tree_view_class->drop_color)
            {
              GeglColor *color;

              if ((color = gimp_selection_data_get_color (selection_data)))
                {
                  tree_view_class->drop_color (tree_view, color, dest_viewable, drop_pos);

                  success = TRUE;
                  g_object_unref (color);
                }
            }
          break;

        case GIMP_DND_TYPE_SVG:
        case GIMP_DND_TYPE_SVG_XML:
          if (tree_view_class->drop_svg)
            {
              const guchar *stream;
              gsize         stream_length;

              stream = gimp_selection_data_get_stream (selection_data,
                                                       &stream_length);

              if (stream)
                {
                  tree_view_class->drop_svg (tree_view,
                                             (const gchar *) stream,
                                             stream_length,
                                             dest_viewable, drop_pos);

                  success = TRUE;
                }
            }
          break;

        case GIMP_DND_TYPE_COMPONENT:
          if (tree_view_class->drop_component)
            {
              GimpImage       *image = NULL;
              GimpChannelType  component;

              if (tree_view->dnd_gimp)
                image = gimp_selection_data_get_component (selection_data,
                                                           tree_view->dnd_gimp,
                                                           &component);

              if (image)
                {
                  tree_view_class->drop_component (tree_view,
                                                   image, component,
                                                   dest_viewable, drop_pos);

                  success = TRUE;
                }
            }
          break;

        case GIMP_DND_TYPE_PIXBUF:
          if (tree_view_class->drop_pixbuf)
            {
              GdkPixbuf *pixbuf;

              pixbuf = gtk_selection_data_get_pixbuf (selection_data);

              if (pixbuf)
                {
                  tree_view_class->drop_pixbuf (tree_view,
                                                pixbuf,
                                                dest_viewable, drop_pos);
                  g_object_unref (pixbuf);

                  success = TRUE;
                }
            }
          break;

        default:
          break;
        }
    }

  gtk_drag_finish (context, success, FALSE, time);
}

gboolean
gimp_container_tree_view_real_drop_possible (GimpContainerTreeView   *tree_view,
                                             GimpDndType              src_type,
                                             GList                   *src_viewables,
                                             GimpViewable            *dest_viewable,
                                             GtkTreePath             *drop_path,
                                             GtkTreeViewDropPosition  drop_pos,
                                             GtkTreeViewDropPosition *return_drop_pos,
                                             GdkDragAction           *return_drag_action)
{
  GimpContainerView *view           = GIMP_CONTAINER_VIEW (tree_view);
  GimpContainer     *container      = gimp_container_view_get_container (view);
  GimpContainer     *src_container  = NULL;
  GimpContainer     *dest_container = NULL;
  GList             *iter;
  gint               src_index      = -1;
  gint               dest_index     = -1;

  if (dest_viewable)
    {
      GimpViewable *parent;

      /*  dropping on the lower third of a group item drops into that group  */
      if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER &&
          gimp_viewable_get_children (dest_viewable))
        {
          parent = dest_viewable;
        }
      else
        {
          parent = gimp_viewable_get_parent (dest_viewable);
        }

      if (parent)
        dest_container = gimp_viewable_get_children (parent);
      else if (gimp_container_have (container, GIMP_OBJECT (dest_viewable)))
        dest_container = container;

      if (parent == dest_viewable)
        dest_index = 0;
      else
        dest_index = gimp_container_get_child_index (dest_container,
                                                     GIMP_OBJECT (dest_viewable));
    }

  if (return_drag_action)
    {
      if (! src_viewables)
        *return_drag_action = GDK_ACTION_COPY;
      else
        *return_drag_action = GDK_ACTION_MOVE;
    }

  for (iter = src_viewables; iter; iter = iter->next)
    {
      GimpViewable *src_viewable = iter->data;
      GimpViewable *parent;

      parent = gimp_viewable_get_parent (src_viewable);

      if (parent)
        src_container = gimp_viewable_get_children (parent);
      else if (gimp_container_have (container, GIMP_OBJECT (src_viewable)))
        src_container = container;

      if (src_container)
        src_index = gimp_container_get_child_index (src_container,
                                                    GIMP_OBJECT (src_viewable));


      if (g_type_is_a (G_TYPE_FROM_INSTANCE (src_viewable),
                       gimp_container_get_child_type (container)))
        {
          /* The drop won't change a thing. This is not a fatal drop
           * failure, unless there is only one source viewable.
           * See also the XXX below.
           */

          if (src_viewable == dest_viewable && g_list_length (src_viewables) == 1)
            return FALSE;

          if (src_index == -1 || dest_index == -1)
            return FALSE;

          /*  don't allow dropping a parent node onto one of its descendants
          */

          if (gimp_viewable_is_ancestor (src_viewable, dest_viewable))
            return FALSE;
        }

      /* XXX only check these for list of 1 viewable for now.
       * Actually this drop failure would also happen for more than 1
       * viewable if all the sources are from the same src_container
       * with successive indexes.
       */

      if (src_container == dest_container && g_list_length (src_viewables) == 1)
        {
          if (drop_pos == GTK_TREE_VIEW_DROP_BEFORE)
            {
              if (dest_index == (src_index + 1))
                return FALSE;
            }
          else if (drop_pos == GTK_TREE_VIEW_DROP_AFTER)
            {
              if (dest_index == (src_index - 1))
                return FALSE;
            }
        }

      if (return_drag_action)
        {
          if (! g_type_is_a (G_TYPE_FROM_INSTANCE (src_viewable),
                             gimp_container_get_child_type (container)))
            *return_drag_action = GDK_ACTION_COPY;
        }
    }

  if (return_drop_pos)
    *return_drop_pos = drop_pos;

  return TRUE;
}

void
gimp_container_tree_view_real_drop_viewables (GimpContainerTreeView   *tree_view,
                                              GList                   *src_viewables,
                                              GimpViewable            *dest_viewable,
                                              GtkTreeViewDropPosition  drop_pos)
{
  GimpContainerView *view       = GIMP_CONTAINER_VIEW (tree_view);
  GimpContainer     *src_container;
  GimpContainer     *dest_container;
  GList             *iter;
  gint               dest_index = 0;

  g_return_if_fail (g_list_length (src_viewables) > 0);

  src_viewables = g_list_reverse (src_viewables);
  for (iter = src_viewables; iter; iter = iter->next)
    {
      GimpViewable *src_viewable = iter->data;

      if ((drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER   ||
           drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE) &&
          gimp_viewable_get_children (dest_viewable))
        {
          dest_container = gimp_viewable_get_children (dest_viewable);
          dest_viewable  = NULL;
          drop_pos       = GTK_TREE_VIEW_DROP_BEFORE;
        }
      else if (gimp_viewable_get_parent (dest_viewable))
        {
          dest_container = gimp_viewable_get_children (gimp_viewable_get_parent (dest_viewable));
        }
      else
        {
          dest_container = gimp_container_view_get_container (view);
        }

      if (dest_viewable)
        {
          dest_index = gimp_container_get_child_index (dest_container,
                                                       GIMP_OBJECT (dest_viewable));
        }

      if (gimp_viewable_get_parent (src_viewable))
        {
          src_container = gimp_viewable_get_children (
                                                      gimp_viewable_get_parent (src_viewable));
        }
      else
        {
          src_container = gimp_container_view_get_container (view);
        }

      if (src_container == dest_container)
        {
          gint src_index;

          src_index  = gimp_container_get_child_index (src_container,
                                                       GIMP_OBJECT (src_viewable));

          switch (drop_pos)
            {
            case GTK_TREE_VIEW_DROP_AFTER:
            case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
              if (src_index > dest_index)
                dest_index++;
              break;

            case GTK_TREE_VIEW_DROP_BEFORE:
            case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
              if (src_index < dest_index)
                dest_index--;
              break;
            }

          gimp_container_reorder (src_container,
                                  GIMP_OBJECT (src_viewable), dest_index);
        }
      else
        {
          switch (drop_pos)
            {
            case GTK_TREE_VIEW_DROP_AFTER:
            case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
              dest_index++;
              break;

            case GTK_TREE_VIEW_DROP_BEFORE:
            case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
              break;
            }

          g_object_ref (src_viewable);

          gimp_container_remove (src_container,  GIMP_OBJECT (src_viewable));
          gimp_container_insert (dest_container, GIMP_OBJECT (src_viewable),
                                 dest_index);

          g_object_unref (src_viewable);
        }
    }
}

Messung
CHZG
84979993

¤ Dauer der Verarbeitung: 0.11 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104856
#Domains=417321