Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  gimppageselector.c   Sprache: C

 

/* LIBGIMP - The GIMP Library
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 *
 * gimppageselector.c
 * Copyright (C) 2005 Michael Natterer <mitch@gimp.org>
 *
 * This library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see
 * <https://www.gnu.org/licenses/>.
 */


#include "config.h"

#include <stdlib.h>
#include <string.h>

#include <gegl.h>
#include <gtk/gtk.h>

#include "libgimpbase/gimpbase.h"

#include "gimpwidgetstypes.h"

#include "gimpicons.h"
#include "gimppageselector.h"
#include "gimppropwidgets.h"
#include "gimpwidgets.h"

#include "libgimp/libgimp-intl.h"


/**
 * SECTION: gimppageselector
 * @title: GimpPageSelector
 * @short_description: A widget to select pages from multi-page things.
 *
 * Use this for example for specifying what pages to import from
 * a PDF or PS document.
 **/



enum
{
  SELECTION_CHANGED,
  ACTIVATE,
  LAST_SIGNAL
};

enum
{
  PROP_0,
  PROP_N_PAGES,
  PROP_TARGET
};

enum
{
  COLUMN_PAGE_NO,
  COLUMN_THUMBNAIL,
  COLUMN_LABEL,
  COLUMN_LABEL_SET
};


struct _GimpPageSelector
{
  GtkBox                  parent_instance;

  gint                    n_pages;
  GimpPageSelectorTarget  target;

  GtkListStore           *store;
  GtkWidget              *view;

  GtkWidget              *count_label;
  GtkWidget              *range_entry;

  GdkPixbuf              *default_thumbnail;
};


static void   gimp_page_selector_finalize          (GObject          *object);
static void   gimp_page_selector_get_property      (GObject          *object,
                                                    guint             property_id,
                                                    GValue           *value,
                                                    GParamSpec       *pspec);
static void   gimp_page_selector_set_property      (GObject          *object,
                                                    guint             property_id,
                                                    const GValue     *value,
                                                    GParamSpec       *pspec);

static void   gimp_page_selector_selection_changed (GtkIconView      *icon_view,
                                                    GimpPageSelector *selector);
static void   gimp_page_selector_item_activated    (GtkIconView      *icon_view,
                                                    GtkTreePath      *path,
                                                    GimpPageSelector *selector);
static gboolean gimp_page_selector_range_focus_out (GtkEntry         *entry,
                                                    GdkEventFocus    *fevent,
                                                    GimpPageSelector *selector);
static void   gimp_page_selector_range_activate    (GtkEntry         *entry,
                                                    GimpPageSelector *selector);
static gint   gimp_page_selector_int_compare       (gconstpointer     a,
                                                    gconstpointer     b);
static void   gimp_page_selector_print_range       (GString          *string,
                                                    gint              start,
                                                    gint              end);

static GdkPixbuf * gimp_page_selector_add_frame    (GtkWidget        *widget,
                                                    GdkPixbuf        *pixbuf);


G_DEFINE_TYPE (GimpPageSelector, gimp_page_selector, GTK_TYPE_BOX)

#define parent_class gimp_page_selector_parent_class

static guint selector_signals[LAST_SIGNAL] = { 0 };


static void
gimp_page_selector_class_init (GimpPageSelectorClass *klass)
{
  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);

  object_class->finalize     = gimp_page_selector_finalize;
  object_class->get_property = gimp_page_selector_get_property;
  object_class->set_property = gimp_page_selector_set_property;

  /**
   * GimpPageSelector::selection-changed:
   * @widget: the object which received the signal.
   *
   * This signal is emitted whenever the set of selected pages changes.
   *
   * Since: 2.4
   **/

  selector_signals[SELECTION_CHANGED] =
    g_signal_new ("selection-changed",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  0,
                  NULL, NULL, NULL,
                  G_TYPE_NONE, 0);

  /**
   * GimpPageSelector::activate:
   * @widget: the object which received the signal.
   *
   * The "activate" signal on GimpPageSelector is an action signal. It
   * is emitted when a user double-clicks an item in the page selection.
   *
   * Since: 2.4
   */

  selector_signals[ACTIVATE] =
    g_signal_new ("activate",
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
                  0,
                  NULL, NULL, NULL,
                  G_TYPE_NONE, 0);
  widget_class->activate_signal = selector_signals[ACTIVATE];

  /**
   * GimpPageSelector:n-pages:
   *
   * The number of pages of the document to open.
   *
   * Since: 2.4
   **/

  g_object_class_install_property (object_class, PROP_N_PAGES,
                                   g_param_spec_int ("n-pages",
                                                     _("N Pages"),
                                                     _("The number of pages to open"),
                                                     0, G_MAXINT, 0,
                                                     GIMP_PARAM_READWRITE));

  /**
   * GimpPageSelector:target:
   *
   * The target to open the document to.
   *
   * Since: 2.4
   **/

  g_object_class_install_property (object_class, PROP_TARGET,
                                   g_param_spec_enum ("target",
                                                      _("Target"),
                                                      _("the target to open to"),
                                                      GIMP_TYPE_PAGE_SELECTOR_TARGET,
                                                      GIMP_PAGE_SELECTOR_TARGET_LAYERS,
                                                      GIMP_PARAM_READWRITE));
}

static void
gimp_page_selector_init (GimpPageSelector *selector)
{
  GtkWidget       *vbox;
  GtkWidget       *sw;
  GtkWidget       *hbox;
  GtkWidget       *hbbox;
  GtkWidget       *button;
  GtkWidget       *label;
  GtkWidget       *combo;
  GtkCellRenderer *renderer;

  selector->n_pages = 0;
  selector->target  = GIMP_PAGE_SELECTOR_TARGET_LAYERS;

  gtk_orientable_set_orientation (GTK_ORIENTABLE (selector),
                                  GTK_ORIENTATION_VERTICAL);

  gtk_box_set_spacing (GTK_BOX (selector), 12);

  /*  Pages  */

  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
  gtk_box_pack_start (GTK_BOX (selector), vbox, TRUE, TRUE, 0);
  gtk_widget_show (vbox);

  sw = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
  gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
  gtk_widget_show (sw);

  selector->store = gtk_list_store_new (4,
                                        G_TYPE_INT,
                                        GDK_TYPE_PIXBUF,
                                        G_TYPE_STRING,
                                        G_TYPE_BOOLEAN);

  selector->view = gtk_icon_view_new_with_model (GTK_TREE_MODEL (selector->store));
  gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (selector->view),
                                    GTK_SELECTION_MULTIPLE);
  gtk_container_add (GTK_CONTAINER (sw), selector->view);
  gtk_widget_show (selector->view);

  renderer = gtk_cell_renderer_pixbuf_new ();
  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (selector->view), renderer, FALSE);
  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (selector->view), renderer,
                                  "pixbuf", COLUMN_THUMBNAIL,
                                  NULL);

  renderer = gtk_cell_renderer_text_new ();
  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (selector->view), renderer, FALSE);
  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (selector->view), renderer,
                                  "text", COLUMN_LABEL,
                                  NULL);
  g_object_set (renderer,
                "alignment", PANGO_ALIGN_CENTER,
                "wrap-mode", PANGO_WRAP_WORD_CHAR,
                "xalign",    0.5,
                "yalign",    0.0,
                NULL);

  g_signal_connect (selector->view, "selection-changed",
                    G_CALLBACK (gimp_page_selector_selection_changed),
                    selector);
  g_signal_connect (selector->view, "item-activated",
                    G_CALLBACK (gimp_page_selector_item_activated),
                    selector);

  /*  Count label  */

  selector->count_label = gtk_label_new (_("Nothing selected"));
  gtk_label_set_xalign (GTK_LABEL (selector->count_label), 0.0);
  gimp_label_set_attributes (GTK_LABEL (selector->count_label),
                             PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
                             -1);
  gtk_box_pack_start (GTK_BOX (vbox), selector->count_label, FALSE, FALSE, 0);
  gtk_widget_show (selector->count_label);

  /*  Target combo  */

  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  gtk_box_pack_start (GTK_BOX (selector), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  label = gtk_label_new_with_mnemonic (_("Open _pages as"));
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  combo = gimp_prop_enum_combo_box_new (G_OBJECT (selector), "target", -1, -1);
  gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
  gtk_widget_show (combo);

  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);

  /*  Select all button & range entry  */

  label = gtk_label_new_with_mnemonic (_("Select _range:"));
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  selector->range_entry = gtk_entry_new ();
  gtk_widget_set_size_request (selector->range_entry, 40, -1);
  gtk_box_pack_start (GTK_BOX (hbox), selector->range_entry, TRUE, TRUE, 0);
  gtk_widget_show (selector->range_entry);

  g_signal_connect (selector->range_entry, "focus-out-event",
                    G_CALLBACK (gimp_page_selector_range_focus_out),
                    selector);
  g_signal_connect (selector->range_entry, "activate",
                    G_CALLBACK (gimp_page_selector_range_activate),
                    selector);

  gtk_label_set_mnemonic_widget (GTK_LABEL (label), selector->range_entry);

  hbbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
  gtk_box_pack_end (GTK_BOX (hbox), hbbox, FALSE, FALSE, 0);
  gtk_widget_show (hbbox);

  button = gtk_button_new_with_mnemonic (_("Select _All"));
  gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

  g_signal_connect_swapped (button, "clicked",
                            G_CALLBACK (gimp_page_selector_select_all),
                            selector);

  selector->default_thumbnail =
    gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
                              "text-x-generic", 32, 0, NULL);
}

static void
gimp_page_selector_finalize (GObject *object)
{
  GimpPageSelector *selector = GIMP_PAGE_SELECTOR (object);

  g_clear_object (&selector->default_thumbnail);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
gimp_page_selector_get_property (GObject    *object,
                                 guint       property_id,
                                 GValue     *value,
                                 GParamSpec *pspec)
{
  GimpPageSelector *selector = GIMP_PAGE_SELECTOR (object);

  switch (property_id)
    {
    case PROP_N_PAGES:
      g_value_set_int (value, selector->n_pages);
      break;
    case PROP_TARGET:
      g_value_set_enum (value, selector->target);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_page_selector_set_property (GObject      *object,
                                 guint         property_id,
                                 const GValue *value,
                                 GParamSpec   *pspec)
{
  GimpPageSelector *selector = GIMP_PAGE_SELECTOR (object);

  switch (property_id)
    {
    case PROP_N_PAGES:
      gimp_page_selector_set_n_pages (selector, g_value_get_int (value));
      break;
    case PROP_TARGET:
      selector->target = g_value_get_enum (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}


/*  public functions  */

/**
 * gimp_page_selector_new:
 *
 * Creates a new #GimpPageSelector widget.
 *
 * Returns: Pointer to the new #GimpPageSelector widget.
 *
 * Since: 2.4
 **/

GtkWidget *
gimp_page_selector_new (void)
{
  return g_object_new (GIMP_TYPE_PAGE_SELECTOR, NULL);
}

/**
 * gimp_page_selector_set_n_pages:
 * @selector: Pointer to a #GimpPageSelector.
 * @n_pages:  The number of pages.
 *
 * Sets the number of pages in the document to open.
 *
 * Since: 2.4
 **/

void
gimp_page_selector_set_n_pages (GimpPageSelector *selector,
                                gint              n_pages)
{
  g_return_if_fail (GIMP_IS_PAGE_SELECTOR (selector));
  g_return_if_fail (n_pages >= 0);

  if (n_pages != selector->n_pages)
    {
      GtkTreeIter iter;
      gint        i;

      if (n_pages < selector->n_pages)
        {
          for (i = n_pages; i < selector->n_pages; i++)
            {
              gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (selector->store),
                                             &iter, NULL, n_pages);
              gtk_list_store_remove (selector->store, &iter);
            }
        }
      else
        {
          for (i = selector->n_pages; i < n_pages; i++)
            {
              gchar *text;

              text = g_strdup_printf (_("Page %d"), i + 1);

              gtk_list_store_append (selector->store, &iter);
              gtk_list_store_set (selector->store, &iter,
                                  COLUMN_PAGE_NO,   i,
                                  COLUMN_THUMBNAIL, selector->default_thumbnail,
                                  COLUMN_LABEL,     text,
                                  COLUMN_LABEL_SET, FALSE,
                                  -1);

              g_free (text);
            }
        }

      selector->n_pages = n_pages;

      g_object_notify (G_OBJECT (selector), "n-pages");
    }
}

/**
 * gimp_page_selector_get_n_pages:
 * @selector: Pointer to a #GimpPageSelector.
 *
 * Returns: the number of pages in the document to open.
 *
 * Since: 2.4
 **/

gint
gimp_page_selector_get_n_pages (GimpPageSelector *selector)
{
  g_return_val_if_fail (GIMP_IS_PAGE_SELECTOR (selector), 0);

  return selector->n_pages;
}

/**
 * gimp_page_selector_set_target:
 * @selector: Pointer to a #GimpPageSelector.
 * @target:   How to open the selected pages.
 *
 * Since: 2.4
 **/

void
gimp_page_selector_set_target (GimpPageSelector       *selector,
                               GimpPageSelectorTarget  target)
{
  g_return_if_fail (GIMP_IS_PAGE_SELECTOR (selector));
  g_return_if_fail (target <= GIMP_PAGE_SELECTOR_TARGET_IMAGES);

  if (target != selector->target)
    {
      selector->target = target;

      g_object_notify (G_OBJECT (selector), "target");
    }
}

/**
 * gimp_page_selector_get_target:
 * @selector: Pointer to a #GimpPageSelector.
 *
 * Returns: How the selected pages should be opened.
 *
 * Since: 2.4
 **/

GimpPageSelectorTarget
gimp_page_selector_get_target (GimpPageSelector *selector)
{
  g_return_val_if_fail (GIMP_IS_PAGE_SELECTOR (selector),
                        GIMP_PAGE_SELECTOR_TARGET_LAYERS);

  return selector->target;
}

/**
 * gimp_page_selector_set_page_thumbnail:
 * @selector: Pointer to a #GimpPageSelector.
 * @page_no: The number of the page to set the thumbnail for.
 * @thumbnail: The thumbnail pixbuf.
 *
 * Sets the thumbnail for given @page_no. A default "page" icon will
 * be used if no page thumbnail is set.
 *
 * Since: 2.4
 **/

void
gimp_page_selector_set_page_thumbnail (GimpPageSelector *selector,
                                       gint              page_no,
                                       GdkPixbuf        *thumbnail)
{
  GtkTreeIter iter;

  g_return_if_fail (GIMP_IS_PAGE_SELECTOR (selector));
  g_return_if_fail (thumbnail == NULL || GDK_IS_PIXBUF (thumbnail));

  g_return_if_fail (page_no >= 0 && page_no < selector->n_pages);

  gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (selector->store),
                                 &iter, NULL, page_no);

  if (! thumbnail)
    {
      thumbnail = g_object_ref (selector->default_thumbnail);
    }
  else
    {
      thumbnail = gimp_page_selector_add_frame (GTK_WIDGET (selector),
                                                thumbnail);
    }

  gtk_list_store_set (selector->store, &iter,
                      COLUMN_THUMBNAIL, thumbnail,
                      -1);
  g_clear_object (&thumbnail);
}

/**
 * gimp_page_selector_get_page_thumbnail:
 * @selector: Pointer to a #GimpPageSelector.
 * @page_no: The number of the page to get the thumbnail for.
 *
 * Returns: (nullable) (transfer none): The page's thumbnail, or %NULL if none
 *          is set. The returned pixbuf is owned by #GimpPageSelector and must
 *          not be unref'ed when no longer needed.
 *
 * Since: 2.4
 **/

GdkPixbuf *
gimp_page_selector_get_page_thumbnail (GimpPageSelector *selector,
                                       gint              page_no)
{
  GdkPixbuf   *thumbnail;
  GtkTreeIter  iter;

  g_return_val_if_fail (GIMP_IS_PAGE_SELECTOR (selector), NULL);

  g_return_val_if_fail (page_no >= 0 && page_no < selector->n_pages, NULL);

  gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (selector->store),
                                 &iter, NULL, page_no);
  gtk_tree_model_get (GTK_TREE_MODEL (selector->store), &iter,
                      COLUMN_THUMBNAIL, &thumbnail,
                      -1);

  if (thumbnail)
    g_object_unref (thumbnail);

  if (thumbnail == selector->default_thumbnail)
    return NULL;

  return thumbnail;
}

/**
 * gimp_page_selector_set_page_label:
 * @selector: Pointer to a #GimpPageSelector.
 * @page_no:  The number of the page to set the label for.
 * @label:    The label.
 *
 * Sets the label of the specified page.
 *
 * Since: 2.4
 **/

void
gimp_page_selector_set_page_label (GimpPageSelector *selector,
                                   gint              page_no,
                                   const gchar      *label)
{
  GtkTreeIter  iter;
  gchar       *tmp;

  g_return_if_fail (GIMP_IS_PAGE_SELECTOR (selector));

  g_return_if_fail (page_no >= 0 && page_no < selector->n_pages);

  if (! label)
    tmp = g_strdup_printf (_("Page %d"), page_no + 1);
  else
    tmp = (gchar *) label;

  gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (selector->store),
                                 &iter, NULL, page_no);
  gtk_list_store_set (selector->store, &iter,
                      COLUMN_LABEL,     tmp,
                      COLUMN_LABEL_SET, label != NULL,
                      -1);

  if (! label)
    g_free (tmp);
}

/**
 * gimp_page_selector_get_page_label:
 * @selector: Pointer to a #GimpPageSelector.
 * @page_no: The number of the page to get the thumbnail for.
 *
 * Returns: (nullable) (transfer full): The page's label, or %NULL if none is
 *          set. This is a newly allocated string that should be g_free()'d
 *          when no longer needed.
 *
 * Since: 2.4
 **/

gchar *
gimp_page_selector_get_page_label (GimpPageSelector *selector,
                                   gint              page_no)
{
  GtkTreeIter  iter;
  gchar       *label;
  gboolean     label_set;

  g_return_val_if_fail (GIMP_IS_PAGE_SELECTOR (selector), NULL);

  g_return_val_if_fail (page_no >= 0 && page_no < selector->n_pages, NULL);

  gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (selector->store),
                                 &iter, NULL, page_no);
  gtk_tree_model_get (GTK_TREE_MODEL (selector->store), &iter,
                      COLUMN_LABEL,     &label,
                      COLUMN_LABEL_SET, &label_set,
                      -1);

  if (! label_set)
    {
      g_free (label);
      label = NULL;
    }

  return label;
}

/**
 * gimp_page_selector_select_all:
 * @selector: Pointer to a #GimpPageSelector.
 *
 * Selects all pages.
 *
 * Since: 2.4
 **/

void
gimp_page_selector_select_all (GimpPageSelector *selector)
{
  g_return_if_fail (GIMP_IS_PAGE_SELECTOR (selector));

  gtk_icon_view_select_all (GTK_ICON_VIEW (selector->view));
}

/**
 * gimp_page_selector_unselect_all:
 * @selector: Pointer to a #GimpPageSelector.
 *
 * Unselects all pages.
 *
 * Since: 2.4
 **/

void
gimp_page_selector_unselect_all (GimpPageSelector *selector)
{
  g_return_if_fail (GIMP_IS_PAGE_SELECTOR (selector));

  gtk_icon_view_unselect_all (GTK_ICON_VIEW (selector->view));
}

/**
 * gimp_page_selector_select_page:
 * @selector: Pointer to a #GimpPageSelector.
 * @page_no: The number of the page to select.
 *
 * Adds a page to the selection.
 *
 * Since: 2.4
 **/

void
gimp_page_selector_select_page (GimpPageSelector *selector,
                                gint              page_no)
{
  GtkTreeIter  iter;
  GtkTreePath *path;

  g_return_if_fail (GIMP_IS_PAGE_SELECTOR (selector));

  g_return_if_fail (page_no >= 0 && page_no < selector->n_pages);

  gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (selector->store),
                                 &iter, NULL, page_no);
  path = gtk_tree_model_get_path (GTK_TREE_MODEL (selector->store), &iter);

  gtk_icon_view_select_path (GTK_ICON_VIEW (selector->view), path);

  gtk_tree_path_free (path);
}

/**
 * gimp_page_selector_unselect_page:
 * @selector: Pointer to a #GimpPageSelector.
 * @page_no: The number of the page to unselect.
 *
 * Removes a page from the selection.
 *
 * Since: 2.4
 **/

void
gimp_page_selector_unselect_page (GimpPageSelector *selector,
                                  gint              page_no)
{
  GtkTreeIter  iter;
  GtkTreePath *path;

  g_return_if_fail (GIMP_IS_PAGE_SELECTOR (selector));

  g_return_if_fail (page_no >= 0 && page_no < selector->n_pages);

  gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (selector->store),
                                 &iter, NULL, page_no);
  path = gtk_tree_model_get_path (GTK_TREE_MODEL (selector->store), &iter);

  gtk_icon_view_unselect_path (GTK_ICON_VIEW (selector->view), path);

  gtk_tree_path_free (path);
}

/**
 * gimp_page_selector_page_is_selected:
 * @selector: Pointer to a #GimpPageSelector.
 * @page_no: The number of the page to check.
 *
 * Returns: %TRUE if the page is selected, %FALSE otherwise.
 *
 * Since: 2.4
 **/

gboolean
gimp_page_selector_page_is_selected (GimpPageSelector *selector,
                                     gint              page_no)
{
  GtkTreeIter  iter;
  GtkTreePath *path;
  gboolean     selected;

  g_return_val_if_fail (GIMP_IS_PAGE_SELECTOR (selector), FALSE);

  g_return_val_if_fail (page_no >= 0 && page_no < selector->n_pages, FALSE);

  gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (selector->store),
                                 &iter, NULL, page_no);
  path = gtk_tree_model_get_path (GTK_TREE_MODEL (selector->store), &iter);

  selected = gtk_icon_view_path_is_selected (GTK_ICON_VIEW (selector->view),
                                             path);

  gtk_tree_path_free (path);

  return selected;
}

/**
 * gimp_page_selector_get_selected_pages:
 * @selector: Pointer to a #GimpPageSelector.
 * @n_selected_pages: (out): Returns the number of selected pages.
 *
 * Returns: (array length=n_selected_pages): A sorted array of page numbers of
 *          selected pages. Use g_free() if you don't need the array any longer
 *
 * Since: 2.4
 **/

gint *
gimp_page_selector_get_selected_pages (GimpPageSelector *selector,
                                       gint             *n_selected_pages)
{
  GList *selected;
  GList *list;
  gint  *array;
  gint   i;

  g_return_val_if_fail (GIMP_IS_PAGE_SELECTOR (selector), NULL);
  g_return_val_if_fail (n_selected_pages != NULL, NULL);

  selected = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (selector->view));

  *n_selected_pages = g_list_length (selected);
  array = g_new0 (gint, *n_selected_pages);

  for (list = selected, i = 0; list; list = g_list_next (list), i++)
    {
      gint *indices = gtk_tree_path_get_indices (list->data);

      array[i] = indices[0];
    }

  qsort (array, *n_selected_pages, sizeof (gint),
         gimp_page_selector_int_compare);

  g_list_free_full (selected, (GDestroyNotify) gtk_tree_path_free);

  return array;
}

/**
 * gimp_page_selector_select_range:
 * @selector: Pointer to a #GimpPageSelector.
 * @range: A string representing the set of selected pages.
 *
 * Selects the pages described by @range. The range string is a
 * user-editable list of pages and ranges, e.g. "1,3,5-7,9-12,14".
 * Note that the page numbering in the range string starts with 1,
 * not 0.
 *
 * Invalid pages and ranges will be silently ignored, duplicate and
 * overlapping pages and ranges will be merged.
 *
 * Since: 2.4
 **/

void
gimp_page_selector_select_range (GimpPageSelector *selector,
                                 const gchar      *range)
{
  gchar **ranges;

  g_return_if_fail (GIMP_IS_PAGE_SELECTOR (selector));

  if (! range)
    range = "";

  g_signal_handlers_block_by_func (selector->view,
                                   gimp_page_selector_selection_changed,
                                   selector);

  gimp_page_selector_unselect_all (selector);

  ranges = g_strsplit (range, ",", -1);

  if (ranges)
    {
      gint i;

      for (i = 0; ranges[i] != NULL; i++)
        {
          gchar *range = g_strstrip (ranges[i]);
          gchar *dash;

          dash = strchr (range, '-');

          if (dash)
            {
              gchar *from;
              gchar *to;
              gint   page_from = -1;
              gint   page_to   = -1;

              *dash = '\0';

              from = g_strstrip (range);
              to   = g_strstrip (dash + 1);

              if (sscanf (from, "%i", &page_from) != 1 && strlen (from) == 0)
                page_from = 1;

              if (sscanf (to, "%i", &page_to) != 1 && strlen (to) == 0)
                page_to = selector->n_pages;

              if (page_from > 0        &&
                  page_to   > 0        &&
                  page_from <= page_to &&
                  page_from <= selector->n_pages)
                {
                  gint page_no;

                  page_from = MAX (page_from, 1) - 1;
                  page_to   = MIN (page_to, selector->n_pages) - 1;

                  for (page_no = page_from; page_no <= page_to; page_no++)
                    gimp_page_selector_select_page (selector, page_no);
                }
            }
          else
            {
              gint page_no;

              if (sscanf (range, "%i", &page_no) == 1 &&
                  page_no >= 1                        &&
                  page_no <= selector->n_pages)
                {
                  gimp_page_selector_select_page (selector, page_no - 1);
                }
            }
        }

      g_strfreev (ranges);
    }

  g_signal_handlers_unblock_by_func (selector->view,
                                     gimp_page_selector_selection_changed,
                                     selector);

  gimp_page_selector_selection_changed (GTK_ICON_VIEW (selector->view), selector);
}

/**
 * gimp_page_selector_get_selected_range:
 * @selector: Pointer to a #GimpPageSelector.
 *
 * Returns: A newly allocated string representing the set of selected
 *          pages. See gimp_page_selector_select_range() for the
 *          format of the string.
 *
 * Since: 2.4
 **/

gchar *
gimp_page_selector_get_selected_range (GimpPageSelector *selector)
{
  gint    *pages;
  gint     n_pages;
  GString *string;

  g_return_val_if_fail (GIMP_IS_PAGE_SELECTOR (selector), NULL);

  string = g_string_new ("");

  pages = gimp_page_selector_get_selected_pages (selector, &n_pages);

  if (pages)
    {
      gint range_start, range_end;
      gint last_printed;
      gint i;

      range_start  = pages[0];
      range_end    = pages[0];
      last_printed = -1;

      for (i = 1; i < n_pages; i++)
        {
          if (pages[i] > range_end + 1)
            {
              gimp_page_selector_print_range (string,
                                              range_start, range_end);

              last_printed = range_end;
              range_start = pages[i];
            }

          range_end = pages[i];
        }

      if (range_end != last_printed)
        gimp_page_selector_print_range (string, range_start, range_end);

      g_free (pages);
    }

  return g_string_free (string, FALSE);
}


/*  selectorate functions  */

static void
gimp_page_selector_selection_changed (GtkIconView      *icon_view,
                                      GimpPageSelector *selector)
{
  GList *selected;
  gint   n_selected;
  gchar *range;

  selected = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (selector->view));
  n_selected = g_list_length (selected);
  g_list_free_full (selected, (GDestroyNotify) gtk_tree_path_free);

  if (n_selected == 0)
    {
      gtk_label_set_text (GTK_LABEL (selector->count_label),
                          _("Nothing selected"));
    }
  else if (n_selected == 1)
    {
      gtk_label_set_text (GTK_LABEL (selector->count_label),
                          _("One page selected"));
    }
  else
    {
      gchar *text;

      if (n_selected == selector->n_pages)
        text = g_strdup_printf (ngettext ("The page is selected",
                                          "All %d pages selected", n_selected),
                                n_selected);
      else
        text = g_strdup_printf (ngettext ("%d page selected",
                                          "%d pages selected",
                                          n_selected),
                                n_selected);

      gtk_label_set_text (GTK_LABEL (selector->count_label), text);
      g_free (text);
    }

  range = gimp_page_selector_get_selected_range (selector);
  gtk_entry_set_text (GTK_ENTRY (selector->range_entry), range);
  g_free (range);

  gtk_editable_set_position (GTK_EDITABLE (selector->range_entry), -1);

  g_signal_emit (selector, selector_signals[SELECTION_CHANGED], 0);
}

static void
gimp_page_selector_item_activated (GtkIconView      *icon_view,
                                   GtkTreePath      *path,
                                   GimpPageSelector *selector)
{
  g_signal_emit (selector, selector_signals[ACTIVATE], 0);
}

static gboolean
gimp_page_selector_range_focus_out (GtkEntry         *entry,
                                    GdkEventFocus    *fevent,
                                    GimpPageSelector *selector)
{
  gimp_page_selector_range_activate (entry, selector);

  return FALSE;
}

static void
gimp_page_selector_range_activate (GtkEntry         *entry,
                                   GimpPageSelector *selector)
{
  gimp_page_selector_select_range (selector, gtk_entry_get_text (entry));
}

static gint
gimp_page_selector_int_compare (gconstpointer a,
                                gconstpointer b)
{
  return *(gint*)a - *(gint*)b;
}

static void
gimp_page_selector_print_range (GString *string,
                                gint     start,
                                gint     end)
{
  if (string->len != 0)
    g_string_append_c (string, ',');

  if (start == end)
    g_string_append_printf (string, "%d", start + 1);
  else
    g_string_append_printf (string, "%d-%d", start + 1, end + 1);
}

static void
draw_frame_row (GdkPixbuf *frame_image,
                gint       target_width,
                gint       source_width,
                gint       source_v_position,
                gint       dest_v_position,
                GdkPixbuf *result_pixbuf,
                gint       left_offset,
                gint       height)
{
  gint remaining_width = target_width;
  gint h_offset        = 0;

  while (remaining_width > 0)
    {
      gint slab_width = (remaining_width > source_width ?
                         source_width : remaining_width);

      gdk_pixbuf_copy_area (frame_image,
                            left_offset, source_v_position,
                            slab_width, height,
                            result_pixbuf,
                            left_offset + h_offset, dest_v_position);

      remaining_width -= slab_width;
      h_offset += slab_width;
    }
}

/* utility to draw the middle section of the frame in a loop */
static void
draw_frame_column (GdkPixbuf *frame_image,
                   gint       target_height,
                   gint       source_height,
                   gint       source_h_position,
                   gint       dest_h_position,
                   GdkPixbuf *result_pixbuf,
                   gint       top_offset, int width)
{
  gint remaining_height = target_height;
  gint v_offset         = 0;

  while (remaining_height > 0)
    {
      gint slab_height = (remaining_height > source_height ?
                          source_height : remaining_height);

      gdk_pixbuf_copy_area (frame_image,
                            source_h_position, top_offset,
                            width, slab_height,
                            result_pixbuf,
                            dest_h_position, top_offset + v_offset);

      remaining_height -= slab_height;
      v_offset += slab_height;
    }
}

static GdkPixbuf *
stretch_frame_image (GdkPixbuf *frame_image,
                     gint       left_offset,
                     gint       top_offset,
                     gint       right_offset,
                     gint       bottom_offset,
                     gint       dest_width,
                     gint       dest_height)
{
  GdkPixbuf *pixbuf;
  gint       frame_width, frame_height;
  gint       target_width,  target_frame_width;
  gint       target_height, target_frame_height;

  frame_width  = gdk_pixbuf_get_width  (frame_image);
  frame_height = gdk_pixbuf_get_height (frame_image );

  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
                           dest_width, dest_height);
  gdk_pixbuf_fill (pixbuf, 0);

  target_width = dest_width - left_offset - right_offset;
  target_height = dest_height - top_offset - bottom_offset;
  target_frame_width  = frame_width - left_offset - right_offset;
  target_frame_height = frame_height - top_offset - bottom_offset;

  left_offset   += MIN (target_width / 4, target_frame_width / 4);
  right_offset  += MIN (target_width / 4, target_frame_width / 4);
  top_offset    += MIN (target_height / 4, target_frame_height / 4);
  bottom_offset += MIN (target_height / 4, target_frame_height / 4);

  target_width = dest_width - left_offset - right_offset;
  target_height = dest_height - top_offset - bottom_offset;
  target_frame_width  = frame_width - left_offset - right_offset;
  target_frame_height = frame_height - top_offset - bottom_offset;

  /* draw the left top corner  and top row */
  gdk_pixbuf_copy_area (frame_image,
                        0, 0, left_offset, top_offset,
                        pixbuf, 0,  0);
  draw_frame_row (frame_image, target_width, target_frame_width,
                  0, 0,
                  pixbuf,
                  left_offset, top_offset);

  /* draw the right top corner and left column */
  gdk_pixbuf_copy_area (frame_image,
                        frame_width - right_offset, 0,
                        right_offset, top_offset,

                        pixbuf,
                        dest_width - right_offset,  0);
  draw_frame_column (frame_image, target_height, target_frame_height, 0, 0,
                     pixbuf, top_offset, left_offset);

  /* draw the bottom right corner and bottom row */
  gdk_pixbuf_copy_area (frame_image,
                        frame_width - right_offset, frame_height - bottom_offset,
                        right_offset, bottom_offset,
                        pixbuf,
                        dest_width - right_offset, dest_height - bottom_offset);
  draw_frame_row (frame_image, target_width, target_frame_width,
                  frame_height - bottom_offset, dest_height - bottom_offset,
                  pixbuf, left_offset, bottom_offset);

  /* draw the bottom left corner and the right column */
  gdk_pixbuf_copy_area (frame_image,
                        0, frame_height - bottom_offset,
                        left_offset, bottom_offset,
                        pixbuf,
                        0,  dest_height - bottom_offset);
  draw_frame_column (frame_image, target_height, target_frame_height,
                     frame_width - right_offset, dest_width - right_offset,
                     pixbuf, top_offset, right_offset);

  return pixbuf;
}

#define FRAME_LEFT   2
#define FRAME_TOP    2
#define FRAME_RIGHT  4
#define FRAME_BOTTOM 4

static GdkPixbuf *
gimp_page_selector_add_frame (GtkWidget *widget,
                              GdkPixbuf *pixbuf)
{
  GdkPixbuf *frame;
  gint       width, height;

  width  = gdk_pixbuf_get_width (pixbuf);
  height = gdk_pixbuf_get_height (pixbuf);

  frame = g_object_get_data (G_OBJECT (widget), "frame");

  if (! frame)
    {
      GError *error = NULL;

      frame = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
                                        GIMP_ICON_FRAME, 64, 0, &error);
      if (error)
        {
          g_printerr ("%s: %s\n", G_STRFUNC, error->message);
          g_error_free (error);
        }
      g_return_val_if_fail (frame, NULL);
      g_object_set_data_full (G_OBJECT (widget), "frame", frame,
                              (GDestroyNotify) g_object_unref);
    }

  frame = stretch_frame_image (frame,
                               FRAME_LEFT,
                               FRAME_TOP,
                               FRAME_RIGHT,
                               FRAME_BOTTOM,
                               width  + FRAME_LEFT + FRAME_RIGHT,
                               height + FRAME_TOP  + FRAME_BOTTOM);

  gdk_pixbuf_copy_area (pixbuf, 0, 0, width, height,
                        frame, FRAME_LEFT, FRAME_TOP);

  return frame;
}

Messung
CHZG
839610093

¤ Dauer der Verarbeitung: 0.28 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=1104845
#Domains=499264