Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gimp/app/widgets/   (Gimp Bildeditor Version 3.2.0©)  Datei vom 14.2.2026 mit Größe 46 kB image not shown  

Quelle  gimpdockwindow.c   Sprache: C

 

/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * gimpdockwindow.c
 * Copyright (C) 2001-2005 Michael Natterer <mitch@gimp.org>
 * Copyright (C)      2009 Martin Nordholts <martinn@src.gnome.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 "dialogs/dialogs.h" /* FIXME, we are in the widget layer */

#include "config/gimpguiconfig.h"

#include "core/gimp.h"
#include "core/gimpcontext.h"
#include "core/gimpcontainer.h"
#include "core/gimpcontainer.h"
#include "core/gimplist.h"
#include "core/gimpimage.h"

#include "menus/menus.h"

#include "gimpcontainercombobox.h"
#include "gimpcontainerview.h"
#include "gimpdialogfactory.h"
#include "gimpdock.h"
#include "gimpdockbook.h"
#include "gimpdockcolumns.h"
#include "gimpdockcontainer.h"
#include "gimpdockwindow.h"
#include "gimphelp-ids.h"
#include "gimpmenufactory.h"
#include "gimpsessioninfo-aux.h"
#include "gimpsessioninfo.h"
#include "gimpsessionmanaged.h"
#include "gimptoolbox.h"
#include "gimpuimanager.h"
#include "gimpwidgets-utils.h"
#include "gimpwindow.h"

#include "gimp-intl.h"


#define DEFAULT_DOCK_HEIGHT          300
#define DEFAULT_MENU_VIEW_SIZE       GTK_ICON_SIZE_SMALL_TOOLBAR
#define AUX_INFO_SHOW_IMAGE_MENU     "show-image-menu"
#define AUX_INFO_FOLLOW_ACTIVE_IMAGE "follow-active-image"


enum
{
  PROP_0,
  PROP_CONTEXT,
  PROP_DIALOG_FACTORY,
  PROP_UI_MANAGER_NAME,
  PROP_IMAGE_CONTAINER,
  PROP_DISPLAY_CONTAINER,
  PROP_ALLOW_DOCKBOOK_ABSENCE
};


struct _GimpDockWindowPrivate
{
  GimpContext       *context;

  GimpDialogFactory *dialog_factory;

  gchar             *ui_manager_name;
  GimpUIManager     *ui_manager;
  GQuark             image_flush_handler_id;

  GimpDockColumns   *dock_columns;

  gboolean           allow_dockbook_absence;

  guint              update_title_idle_id;

  gint               ID;

  GimpContainer     *image_container;
  GimpContainer     *display_container;

  gboolean           show_image_menu;
  gboolean           auto_follow_active;

  GtkWidget         *image_combo;
  GtkWidget         *auto_button;
};


static void            gimp_dock_window_dock_container_iface_init (GimpDockContainerInterface *iface);
static void            gimp_dock_window_session_managed_iface_init(GimpSessionManagedInterface*iface);
static void            gimp_dock_window_constructed               (GObject                    *object);
static void            gimp_dock_window_dispose                   (GObject                    *object);
static void            gimp_dock_window_finalize                  (GObject                    *object);
static void            gimp_dock_window_set_property              (GObject                    *object,
                                                                   guint                       property_id,
                                                                   const GValue               *value,
                                                                   GParamSpec                 *pspec);
static void            gimp_dock_window_get_property              (GObject                    *object,
                                                                   guint                       property_id,
                                                                   GValue                     *value,
                                                                   GParamSpec                 *pspec);
static void            gimp_dock_window_style_updated             (GtkWidget                  *widget);
static gboolean        gimp_dock_window_delete_event              (GtkWidget                  *widget,
                                                                   GdkEventAny                *event);
#ifdef G_OS_WIN32
static void            gimp_dock_window_realize                   (GimpDockWindow             *dock_window,
                                                                   gpointer                    data);
#endif
static GList         * gimp_dock_window_get_docks                 (GimpDockContainer          *dock_container);
static GList         * gimp_dock_window_get_docks_self            (GimpDockWindow             *self);
static GimpDialogFactory * gimp_dock_window_get_dialog_factory    (GimpDockContainer          *dock_container);
static GimpUIManager * gimp_dock_window_get_ui_manager            (GimpDockContainer          *dock_container);
static void            gimp_dock_window_add_dock_from_session     (GimpDockContainer          *dock_container,
                                                                   GimpDock                   *dock,
                                                                   GimpSessionInfoDock        *dock_info);
static GList         * gimp_dock_window_get_aux_info              (GimpSessionManaged         *session_managed);
static void            gimp_dock_window_set_aux_info              (GimpSessionManaged         *session_managed,
                                                                   GList                      *aux_info);
static GimpAlignmentType
                       gimp_dock_window_get_dock_side             (GimpDockContainer          *dock_container,
                                                                   GimpDock                   *dock);
static gboolean        gimp_dock_window_should_add_to_recent      (GimpDockWindow             *dock_window);
static void            gimp_dock_window_display_changed           (GimpDockWindow             *dock_window,
                                                                   GimpDisplay                *display,
                                                                   GimpContext                *context);
static void            gimp_dock_window_image_changed             (GimpDockWindow             *dock_window,
                                                                   GimpImage                  *image,
                                                                   GimpContext                *context);
static void            gimp_dock_window_image_flush               (GimpImage                  *image,
                                                                   gboolean                    invalidate_preview,
                                                                   GimpDockWindow             *dock_window);
static void            gimp_dock_window_update_title              (GimpDockWindow             *dock_window);
static gboolean        gimp_dock_window_update_title_idle         (GimpDockWindow             *dock_window);
static gchar         * gimp_dock_window_get_description           (GimpDockWindow             *dock_window,
                                                                   gboolean                    complete);
static void            gimp_dock_window_dock_removed              (GimpDockWindow             *dock_window,
                                                                   GimpDock                   *dock,
                                                                   GimpDockColumns            *dock_columns);
static void            gimp_dock_window_factory_display_changed   (GimpContext                *context,
                                                                   GimpDisplay                *display,
                                                                   GimpDock                   *dock);
static void            gimp_dock_window_factory_image_changed     (GimpContext                *context,
                                                                   GimpImage                  *image,
                                                                   GimpDock                   *dock);
static void            gimp_dock_window_auto_clicked              (GtkWidget                  *widget,
                                                                   GimpDock                   *dock);


G_DEFINE_TYPE_WITH_CODE (GimpDockWindow, gimp_dock_window, GIMP_TYPE_WINDOW,
                         G_ADD_PRIVATE (GimpDockWindow)
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCK_CONTAINER,
                                                gimp_dock_window_dock_container_iface_init)
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_SESSION_MANAGED,
                                                gimp_dock_window_session_managed_iface_init))

#define parent_class gimp_dock_window_parent_class


static void
gimp_dock_window_class_init (GimpDockWindowClass *klass)
{
  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);

  object_class->constructed   = gimp_dock_window_constructed;
  object_class->dispose       = gimp_dock_window_dispose;
  object_class->finalize      = gimp_dock_window_finalize;
  object_class->set_property  = gimp_dock_window_set_property;
  object_class->get_property  = gimp_dock_window_get_property;

  widget_class->style_updated = gimp_dock_window_style_updated;
  widget_class->delete_event  = gimp_dock_window_delete_event;

  g_object_class_install_property (object_class, PROP_CONTEXT,
                                   g_param_spec_object ("context", NULL, NULL,
                                                        GIMP_TYPE_CONTEXT,
                                                        GIMP_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (object_class, PROP_DIALOG_FACTORY,
                                   g_param_spec_object ("dialog-factory",
                                                        NULL, NULL,
                                                        GIMP_TYPE_DIALOG_FACTORY,
                                                        GIMP_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (object_class, PROP_UI_MANAGER_NAME,
                                   g_param_spec_string ("ui-manager-name",
                                                        NULL, NULL,
                                                        NULL,
                                                        GIMP_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (object_class, PROP_IMAGE_CONTAINER,
                                   g_param_spec_object ("image-container",
                                                        NULL, NULL,
                                                        GIMP_TYPE_CONTAINER,
                                                        GIMP_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (object_class, PROP_DISPLAY_CONTAINER,
                                   g_param_spec_object ("display-container",
                                                        NULL, NULL,
                                                        GIMP_TYPE_CONTAINER,
                                                        GIMP_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (object_class, PROP_ALLOW_DOCKBOOK_ABSENCE,
                                   g_param_spec_boolean ("allow-dockbook-absence",
                                                         NULL, NULL,
                                                         FALSE,
                                                         GIMP_PARAM_READWRITE |
                                                         G_PARAM_CONSTRUCT_ONLY));


  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("default-height",
                                                             NULL, NULL,
                                                             -1, G_MAXINT,
                                                             DEFAULT_DOCK_HEIGHT,
                                                             GIMP_PARAM_READABLE));

  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_enum ("menu-preview-size",
                                                              NULL, NULL,
                                                              GTK_TYPE_ICON_SIZE,
                                                              DEFAULT_MENU_VIEW_SIZE,
                                                              GIMP_PARAM_READABLE));
}

static void
gimp_dock_window_init (GimpDockWindow *dock_window)
{
  static gint  dock_window_ID = 1;
  gchar       *name           = NULL;

  dock_window->p = gimp_dock_window_get_instance_private (dock_window);
  dock_window->p->ID                 = dock_window_ID++;
  dock_window->p->auto_follow_active = TRUE;

  name = g_strdup_printf ("gimp-dock-%d", dock_window->p->ID);
  gtk_widget_set_name (GTK_WIDGET (dock_window), name);
  g_free (name);

  gtk_window_set_resizable (GTK_WINDOW (dock_window), TRUE);
  gtk_window_set_focus_on_map (GTK_WINDOW (dock_window), FALSE);
  gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dock_window), FALSE);

#ifdef G_OS_WIN32
  g_signal_connect (dock_window, "realize",
                    G_CALLBACK (gimp_dock_window_realize),
                    NULL);
#endif
}

static void
gimp_dock_window_dock_container_iface_init (GimpDockContainerInterface *iface)
{
  iface->get_docks          = gimp_dock_window_get_docks;
  iface->get_dialog_factory = gimp_dock_window_get_dialog_factory;
  iface->get_ui_manager     = gimp_dock_window_get_ui_manager;
  iface->add_dock           = gimp_dock_window_add_dock_from_session;
  iface->get_dock_side      = gimp_dock_window_get_dock_side;
}

static void
gimp_dock_window_session_managed_iface_init (GimpSessionManagedInterface *iface)
{
  iface->get_aux_info = gimp_dock_window_get_aux_info;
  iface->set_aux_info = gimp_dock_window_set_aux_info;
}

static void
gimp_dock_window_constructed (GObject *object)
{
  GimpDockWindow  *dock_window = GIMP_DOCK_WINDOW (object);
  GimpGuiConfig   *config;
  GimpContext     *factory_context;
  GimpMenuFactory *menu_factory;
  Gimp            *gimp;
  gint             menu_view_width  = -1;
  gint             menu_view_height = -1;

  G_OBJECT_CLASS (parent_class)->constructed (object);

  gimp   = GIMP (dock_window->p->context->gimp);
  config = GIMP_GUI_CONFIG (gimp->config);

  /* Create a separate context per dock so that docks can be bound to
   * a specific image and does not necessarily have to follow the
   * active image in the user context
   */

  g_object_unref (dock_window->p->context);
  dock_window->p->context           = gimp_context_new (gimp, "Dock Context", NULL);
  dock_window->p->image_container   = gimp->images;
  dock_window->p->display_container = gimp->displays;

  factory_context =
    gimp_dialog_factory_get_context (dock_window->p->dialog_factory);

  /* Setup hints */
  gimp_window_set_hint (GTK_WINDOW (dock_window), config->dock_window_hint);

  menu_factory = menus_get_global_menu_factory (gimp);

  /* Make image window related keyboard shortcuts work also when a
   * dock window is the focused window
   */

  dock_window->p->ui_manager =
    gimp_menu_factory_get_manager (menu_factory,
                                   dock_window->p->ui_manager_name,
                                   dock_window);

  g_signal_connect_object (dock_window->p->context, "display-changed",
                           G_CALLBACK (gimp_dock_window_display_changed),
                           dock_window,
                           G_CONNECT_SWAPPED);
  g_signal_connect_object (dock_window->p->context, "image-changed",
                           G_CALLBACK (gimp_dock_window_image_changed),
                           dock_window,
                           G_CONNECT_SWAPPED);

  dock_window->p->image_flush_handler_id =
    gimp_container_add_handler (gimp->images, "flush",
                                G_CALLBACK (gimp_dock_window_image_flush),
                                dock_window);

  gimp_context_define_properties (dock_window->p->context,
                                  GIMP_CONTEXT_PROP_MASK_ALL &
                                  ~(GIMP_CONTEXT_PROP_MASK_IMAGE |
                                    GIMP_CONTEXT_PROP_MASK_DISPLAY),
                                  FALSE);
  gimp_context_set_parent (dock_window->p->context,
                           factory_context);

  /* Setup widget hierarchy */
  {
    GtkWidget *vbox = NULL;

    /* Top-level GtkVBox */
    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_container_add (GTK_CONTAINER (dock_window), vbox);
    gtk_widget_show (vbox);

    /* Image selection menu */
    {
      GtkWidget *hbox = NULL;

      /* GtkHBox */
      hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
      gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
      if (dock_window->p->show_image_menu)
        gtk_widget_show (hbox);

      /* Image combo */
      dock_window->p->image_combo = gimp_container_combo_box_new (NULL, NULL, 16, 1);
      gtk_box_pack_start (GTK_BOX (hbox), dock_window->p->image_combo, TRUE, TRUE, 0);
      g_signal_connect (dock_window->p->image_combo, "destroy",
                        G_CALLBACK (gtk_widget_destroyed),
                        &dock_window->p->image_combo);
      gimp_help_set_help_data (dock_window->p->image_combo,
                               NULL, GIMP_HELP_DOCK_IMAGE_MENU);
      gtk_widget_show (dock_window->p->image_combo);

      /* Auto button */
      dock_window->p->auto_button = gtk_toggle_button_new_with_label (_("Auto"));
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dock_window->p->auto_button),
                                    dock_window->p->auto_follow_active);
      gtk_box_pack_start (GTK_BOX (hbox), dock_window->p->auto_button, FALSE, FALSE, 0);
      gtk_widget_show (dock_window->p->auto_button);

      g_signal_connect (dock_window->p->auto_button, "clicked",
                        G_CALLBACK (gimp_dock_window_auto_clicked),
                        dock_window);

      gimp_help_set_help_data (dock_window->p->auto_button,
                               _("When enabled, the dialog automatically "
                                 "follows the image you are working on."),
                               GIMP_HELP_DOCK_AUTO_BUTTON);
    }

    /* GimpDockColumns */
    /* Let the GimpDockColumns mirror the context so that a GimpDock can
     * get it when inside a dock window. We do the same thing in the
     * GimpImageWindow so docks can get the GimpContext there as well
     */

    dock_window->p->dock_columns =
      GIMP_DOCK_COLUMNS (gimp_dock_columns_new (dock_window->p->context,
                                                dock_window->p->dialog_factory,
                                                dock_window->p->ui_manager));
    gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (dock_window->p->dock_columns),
                        TRUE, TRUE, 0);
    gtk_widget_show (GTK_WIDGET (dock_window->p->dock_columns));
    g_signal_connect_object (dock_window->p->dock_columns, "dock-removed",
                             G_CALLBACK (gimp_dock_window_dock_removed),
                             dock_window,
                             G_CONNECT_SWAPPED);

    g_signal_connect_object (dock_window->p->dock_columns, "dock-added",
                             G_CALLBACK (gimp_dock_window_update_title),
                             dock_window,
                             G_CONNECT_SWAPPED);
    g_signal_connect_object (dock_window->p->dock_columns, "dock-removed",
                             G_CALLBACK (gimp_dock_window_update_title),
                             dock_window,
                             G_CONNECT_SWAPPED);
  }

  if (dock_window->p->auto_follow_active)
    {
      if (gimp_context_get_display (factory_context))
        gimp_context_copy_property (factory_context,
                                    dock_window->p->context,
                                    GIMP_CONTEXT_PROP_DISPLAY);
      else
        gimp_context_copy_property (factory_context,
                                    dock_window->p->context,
                                    GIMP_CONTEXT_PROP_IMAGE);
    }

  g_signal_connect_object (factory_context, "display-changed",
                           G_CALLBACK (gimp_dock_window_factory_display_changed),
                           dock_window,
                           0);
  g_signal_connect_object (factory_context, "image-changed",
                           G_CALLBACK (gimp_dock_window_factory_image_changed),
                           dock_window,
                           0);

  gtk_icon_size_lookup (DEFAULT_MENU_VIEW_SIZE,
                        &menu_view_width,
                        &menu_view_height);

  g_object_set (dock_window->p->image_combo,
                "container", dock_window->p->image_container,
                "context",   dock_window->p->context,
                NULL);

  gimp_help_connect (GTK_WIDGET (dock_window), NULL, gimp_standard_help_func,
                     GIMP_HELP_DOCK, NULL, NULL);

  if (dock_window->p->auto_follow_active)
    {
      if (gimp_context_get_display (factory_context))
        gimp_context_copy_property (factory_context,
                                    dock_window->p->context,
                                    GIMP_CONTEXT_PROP_DISPLAY);
      else
        gimp_context_copy_property (factory_context,
                                    dock_window->p->context,
                                    GIMP_CONTEXT_PROP_IMAGE);
    }
}

static void
gimp_dock_window_dispose (GObject *object)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (object);

  if (dock_window->p->update_title_idle_id)
    {
      g_source_remove (dock_window->p->update_title_idle_id);
      dock_window->p->update_title_idle_id = 0;
    }

  if (dock_window->p->image_flush_handler_id)
    {
      gimp_container_remove_handler (dock_window->p->context->gimp->images,
                                     dock_window->p->image_flush_handler_id);
      dock_window->p->image_flush_handler_id = 0;
    }

  g_clear_object (&dock_window->p->dialog_factory);

  /* Null our reference, that update_title callback dereferences.
   * Gtk will dispose the widget but doesn't know of our reference.
   */

  dock_window->p->dock_columns = NULL;

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

static void
gimp_dock_window_finalize (GObject *object)
{
  GimpDockWindow  *dock_window = GIMP_DOCK_WINDOW (object);
  GimpMenuFactory *menu_factory;
  Gimp            *gimp;

  gimp         = GIMP (dock_window->p->context->gimp);
  menu_factory = menus_get_global_menu_factory (gimp);

  /* If the whole GUI is in destruction, global menu factory might already not
   * exist anymore.
   */

  if (menu_factory != NULL)
    gimp_menu_factory_delete_manager (menu_factory,
                                      dock_window->p->ui_manager_name,
                                      dock_window);
  g_clear_pointer (&dock_window->p->ui_manager_name, g_free);
  g_clear_object (&dock_window->p->context);

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

static void
gimp_dock_window_set_property (GObject      *object,
                               guint         property_id,
                               const GValue *value,
                               GParamSpec   *pspec)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (object);

  switch (property_id)
    {
    case PROP_CONTEXT:
      dock_window->p->context = g_value_dup_object (value);
      break;

    case PROP_DIALOG_FACTORY:
      dock_window->p->dialog_factory = g_value_dup_object (value);
      break;

    case PROP_UI_MANAGER_NAME:
      dock_window->p->ui_manager_name = g_value_dup_string (value);
      break;

    case PROP_IMAGE_CONTAINER:
      dock_window->p->image_container = g_value_dup_object (value);
      break;

    case PROP_DISPLAY_CONTAINER:
      dock_window->p->display_container = g_value_dup_object (value);
      break;

    case PROP_ALLOW_DOCKBOOK_ABSENCE:
      dock_window->p->allow_dockbook_absence = g_value_get_boolean (value);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_dock_window_get_property (GObject    *object,
                               guint       property_id,
                               GValue     *value,
                               GParamSpec *pspec)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (object);

  switch (property_id)
    {
    case PROP_CONTEXT:
      g_value_set_object (value, dock_window->p->context);
      break;

    case PROP_DIALOG_FACTORY:
      g_value_set_object (value, dock_window->p->dialog_factory);
      break;

    case PROP_UI_MANAGER_NAME:
      g_value_set_string (value, dock_window->p->ui_manager_name);
      break;

    case PROP_IMAGE_CONTAINER:
      g_value_set_object (value, dock_window->p->image_container);
      break;

    case PROP_DISPLAY_CONTAINER:
      g_value_set_object (value, dock_window->p->display_container);
      break;

    case PROP_ALLOW_DOCKBOOK_ABSENCE:
      g_value_set_boolean (value, dock_window->p->allow_dockbook_absence);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_dock_window_style_updated (GtkWidget *widget)
{
  GimpDockWindow  *dock_window      = GIMP_DOCK_WINDOW (widget);
  GtkStyleContext *button_style;
  GtkIconSize      menu_view_size;
  gint             default_height = DEFAULT_DOCK_HEIGHT;

  GTK_WIDGET_CLASS (parent_class)->style_updated (widget);

  gtk_widget_style_get (widget,
                        "default-height", &default_height,
                        "menu-preview-size", &menu_view_size,
                        NULL);

  gtk_window_set_default_size (GTK_WINDOW (widget), -1, default_height);

  if (dock_window->p->image_combo)
    {
      GtkBorder border;
      gint      menu_view_width  = 18;
      gint      menu_view_height = 18;
      gint      focus_line_width;
      gint      focus_padding;

      gtk_icon_size_lookup (menu_view_size,
                            &menu_view_width,
                            &menu_view_height);

      gtk_widget_style_get (dock_window->p->auto_button,
                            "focus-line-width", &focus_line_width,
                            "focus-padding",    &focus_padding,
                            NULL);

      button_style = gtk_widget_get_style_context (widget);
      gtk_style_context_get_border (button_style,
                                    gtk_widget_get_state_flags (widget),
                                    &border);

      gimp_container_view_set_view_size (GIMP_CONTAINER_VIEW (dock_window->p->image_combo),
                                         menu_view_height, 1);

      gtk_widget_set_size_request (dock_window->p->auto_button, -1,
                                   menu_view_height +
                                   2 * (1 /* CHILD_SPACING */ +
                                        border.top            +
                                        border.bottom         +
                                        focus_padding         +
                                        focus_line_width));
    }
}

/**
 * gimp_dock_window_delete_event:
 * @widget:
 * @event:
 *
 * Makes sure that when dock windows are closed they are added to the
 * list of recently closed docks so that they are easy to bring back.
 **/

static gboolean
gimp_dock_window_delete_event (GtkWidget   *widget,
                               GdkEventAny *event)
{
  GimpDockWindow         *dock_window = GIMP_DOCK_WINDOW (widget);
  GimpSessionInfo        *info        = NULL;
  const gchar            *entry_name  = NULL;
  GimpDialogFactoryEntry *entry       = NULL;
  gchar                  *name        = NULL;

  /* Don't add docks with just a single dockable to the list of
   * recently closed dock since those can be brought back through the
   * normal Windows->Dockable Dialogs menu
   */

  if (! gimp_dock_window_should_add_to_recent (dock_window))
    return FALSE;

  info = gimp_session_info_new ();

  name = gimp_dock_window_get_description (dock_window, TRUE /*complete*/);
  gimp_object_set_name (GIMP_OBJECT (info), name);
  g_free (name);

  gimp_session_info_get_info_with_widget (info, GTK_WIDGET (dock_window));

  entry_name = (gimp_dock_window_has_toolbox (dock_window) ?
                "gimp-toolbox-window" :
                "gimp-dock-window");
  entry = gimp_dialog_factory_find_entry (dock_window->p->dialog_factory,
                                          entry_name);
  gimp_session_info_set_factory_entry (info, entry);

  gimp_container_add (global_recent_docks, GIMP_OBJECT (info));
  g_object_unref (info);

  return FALSE;
}

#ifdef G_OS_WIN32
static void
gimp_dock_window_realize (GimpDockWindow *dock_window,
                          gpointer        data)
{
  dock_window->p = gimp_dock_window_get_instance_private (dock_window);

  if (dock_window->p->context && dock_window->p->context->gimp)
    gimp_window_set_title_bar_theme (dock_window->p->context->gimp,
                                     GTK_WIDGET (dock_window));
}
#endif

/* Returns list of docks from self.
 * Delegate to self's dock_columns, when it exists.
 *
 * Returns NULL when self has no dock_columns,
 * which can happen during destroy.
 *
 * A returned non-null list is owned by self's dock_columns
 * and need not be freed.
 */

static GList *
gimp_dock_window_get_docks_self (GimpDockWindow *self)
{
  if (self->p->dock_columns)
    return gimp_dock_columns_get_docks (self->p->dock_columns);
  else
    return NULL;
}

/* Implementation of GimpDockContainer interface method get_docks
 * Transfers ownership of list to caller.
 */

static GList *
gimp_dock_window_get_docks (GimpDockContainer *dock_container)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock_container);

  return g_list_copy (gimp_dock_window_get_docks_self (dock_window));
}

static GimpDialogFactory *
gimp_dock_window_get_dialog_factory (GimpDockContainer *dock_container)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock_container);

  return dock_window->p->dialog_factory;
}

static GimpUIManager *
gimp_dock_window_get_ui_manager (GimpDockContainer *dock_container)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock_container);

  return dock_window->p->ui_manager;
}

static void
gimp_dock_window_add_dock_from_session (GimpDockContainer   *dock_container,
                                        GimpDock            *dock,
                                        GimpSessionInfoDock *dock_info)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock_container);

  gimp_dock_window_add_dock (dock_window,
                             dock,
                             -1 /*index*/);
}

static GList *
gimp_dock_window_get_aux_info (GimpSessionManaged *session_managed)
{
  GimpDockWindow     *dock_window = GIMP_DOCK_WINDOW (session_managed);
  GList              *aux_info    = NULL;
  GimpSessionInfoAux *aux;

  if (dock_window->p->allow_dockbook_absence)
    {
      /* Assume it is the toolbox; it does not have aux info */
      return NULL;
    }

  g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), NULL);

  aux = gimp_session_info_aux_new (AUX_INFO_SHOW_IMAGE_MENU,
                                   dock_window->p->show_image_menu ?
                                   "true" : "false");
  aux_info = g_list_append (aux_info, aux);

  aux = gimp_session_info_aux_new (AUX_INFO_FOLLOW_ACTIVE_IMAGE,
                                   dock_window->p->auto_follow_active ?
                                   "true" : "false");
  aux_info = g_list_append (aux_info, aux);

  return aux_info;
}

static void
gimp_dock_window_set_aux_info (GimpSessionManaged *session_managed,
                               GList              *aux_info)
{
  GimpDockWindow *dock_window;
  GList          *list;
  gboolean        menu_shown;
  gboolean        auto_follow;

  g_return_if_fail (GIMP_IS_DOCK_WINDOW (session_managed));

  dock_window = GIMP_DOCK_WINDOW (session_managed);
  menu_shown  = dock_window->p->show_image_menu;
  auto_follow = dock_window->p->auto_follow_active;

  for (list = aux_info; list; list = g_list_next (list))
    {
      GimpSessionInfoAux *aux = list->data;

      if (! strcmp (aux->name, AUX_INFO_SHOW_IMAGE_MENU))
        {
          menu_shown = ! g_ascii_strcasecmp (aux->value, "true");
        }
      else if (! strcmp (aux->name, AUX_INFO_FOLLOW_ACTIVE_IMAGE))
        {
          auto_follow = ! g_ascii_strcasecmp (aux->value, "true");
        }
    }

  if (menu_shown != dock_window->p->show_image_menu)
    gimp_dock_window_set_show_image_menu (dock_window, menu_shown);

  if (auto_follow != dock_window->p->auto_follow_active)
    gimp_dock_window_set_auto_follow_active (dock_window, auto_follow);
}

static GimpAlignmentType
gimp_dock_window_get_dock_side (GimpDockContainer *dock_container,
                                GimpDock          *dock)
{
  g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_container), -1);
  g_return_val_if_fail (GIMP_IS_DOCK (dock), -1);

  /* A GimpDockWindow don't have docks on different sides, it's just
   * one set of columns
   */

  return -1;
}

/**
 * gimp_dock_window_should_add_to_recent:
 * @dock_window:
 *
 * Returns: %FALSE if the dock window can be recreated with one
 *          Windows menu item such as Windows->Toolbox or
 *          Windows->Dockable Dialogs->Layers, %TRUE if not. It should
 *          then be added to the list of recently closed docks.
 **/

static gboolean
gimp_dock_window_should_add_to_recent (GimpDockWindow *dock_window)
{
  GList    *docks;
  gboolean  should_add = TRUE;

  docks = gimp_dock_window_get_docks_self (dock_window);

  if (! docks)
    {
      should_add = FALSE;
    }
  else if (g_list_length (docks) == 1)
    {
      GimpDock *dock = GIMP_DOCK (g_list_nth_data (docks, 0));

      if (GIMP_IS_TOOLBOX (dock) &&
          gimp_dock_get_n_dockables (dock) == 0)
        {
          should_add = FALSE;
        }
      else if (! GIMP_IS_TOOLBOX (dock) &&
               gimp_dock_get_n_dockables (dock) == 1)
        {
          should_add = FALSE;
        }
    }

  return should_add;
}

static void
gimp_dock_window_image_flush (GimpImage      *image,
                              gboolean        invalidate_preview,
                              GimpDockWindow *dock_window)
{
  if (image == gimp_context_get_image (dock_window->p->context))
    {
      GimpDisplay *display = gimp_context_get_display (dock_window->p->context);

      if (display)
        gimp_ui_manager_update (dock_window->p->ui_manager, display);
    }
}

static void
gimp_dock_window_update_title (GimpDockWindow *dock_window)
{
  if (dock_window->p->update_title_idle_id)
    g_source_remove (dock_window->p->update_title_idle_id);

  dock_window->p->update_title_idle_id =
    g_idle_add ((GSourceFunc) gimp_dock_window_update_title_idle,
                dock_window);
}

static gboolean
gimp_dock_window_update_title_idle (GimpDockWindow *dock_window)
{
  gchar *desc = gimp_dock_window_get_description (dock_window,
                                                  FALSE /*complete*/);
  if (desc)
    {
      gtk_window_set_title (GTK_WINDOW (dock_window), desc);
      g_free (desc);
    }

  dock_window->p->update_title_idle_id = 0;

  return FALSE;
}

static gchar *
gimp_dock_window_get_description (GimpDockWindow *dock_window,
                                  gboolean        complete)
{
  GString *complete_desc = g_string_new (NULL);
  GList   *docks         = NULL;
  GList   *iter          = NULL;

  docks = gimp_dock_window_get_docks_self (dock_window);

  for (iter = docks;
       iter;
       iter = g_list_next (iter))
    {
      gchar *desc = gimp_dock_get_description (GIMP_DOCK (iter->data), complete);
      g_string_append (complete_desc, desc);
      g_free (desc);

      if (g_list_next (iter))
        g_string_append (complete_desc, GIMP_DOCK_COLUMN_SEPARATOR);
    }

  return g_string_free (complete_desc, FALSE /*free_segment*/);
}

static void
gimp_dock_window_dock_removed (GimpDockWindow  *dock_window,
                               GimpDock        *dock,
                               GimpDockColumns *dock_columns)
{
  g_return_if_fail (GIMP_IS_DOCK (dock));

  if (gimp_dock_columns_get_docks (dock_columns) == NULL &&
      ! dock_window->p->allow_dockbook_absence)
    gtk_widget_destroy (GTK_WIDGET (dock_window));
}

static void
gimp_dock_window_factory_display_changed (GimpContext *context,
                                          GimpDisplay *display,
                                          GimpDock    *dock)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock);

  if (display && dock_window->p->auto_follow_active)
    gimp_context_set_display (dock_window->p->context, display);
}

static void
gimp_dock_window_factory_image_changed (GimpContext *context,
                                        GimpImage   *image,
                                        GimpDock    *dock)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock);

  /*  won't do anything if we already set the display above  */
  if (image && dock_window->p->auto_follow_active)
    gimp_context_set_image (dock_window->p->context, image);
}

static void
gimp_dock_window_display_changed (GimpDockWindow *dock_window,
                                  GimpDisplay    *display,
                                  GimpContext    *context)
{
  /*  make sure auto-follow-active works both ways  */
  if (display && dock_window->p->auto_follow_active)
    {
      GimpContext *factory_context =
        gimp_dialog_factory_get_context (dock_window->p->dialog_factory);

      gimp_context_set_display (factory_context, display);
    }

  gimp_ui_manager_update (dock_window->p->ui_manager,
                          display);
}

static void
gimp_dock_window_image_changed (GimpDockWindow *dock_window,
                                GimpImage      *image,
                                GimpContext    *context)
{
  GimpContainer *display_container = dock_window->p->display_container;

  /*  make sure auto-follow-active works both ways  */
  if (image && dock_window->p->auto_follow_active)
    {
      GimpContext *factory_context =
        gimp_dialog_factory_get_context (dock_window->p->dialog_factory);

      gimp_context_set_image (factory_context, image);
    }

  if (image != NULL && ! gimp_container_is_empty (display_container))
    {
      GimpDisplay *display;
      GimpImage   *display_image;
      gboolean     find_display = TRUE;

      display = gimp_context_get_display (context);

      if (display)
        {
          g_object_get (display, "image", &display_image, NULL);

          if (display_image)
            {
              g_object_unref (display_image);

              if (display_image == image)
                find_display = FALSE;
            }
        }

      if (find_display)
        {
          GList *list;

          for (list = GIMP_LIST (display_container)->queue->head;
               list;
               list = g_list_next (list))
            {
              display = list->data;

              g_object_get (display, "image", &display_image, NULL);

              if (display_image)
                {
                  g_object_unref (display_image);

                  if (display_image == image)
                    {
                      /*  this invokes this function recursively but we
                       *  don't enter the if(find_display) branch the
                       *  second time
                       */

                      gimp_context_set_display (context, display);

                      /*  don't stop signal emission here because the
                       *  context's image was not changed by the
                       *  recursive call
                       */

                      break;
                    }
                }
            }
        }
    }

  gimp_ui_manager_update (dock_window->p->ui_manager,
                          gimp_context_get_display (context));
}

static void
gimp_dock_window_auto_clicked (GtkWidget *widget,
                               GimpDock  *dock)
{
  GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock);

  gimp_toggle_button_update (widget, &dock_window->p->auto_follow_active);

  if (dock_window->p->auto_follow_active)
    {
      GimpContext *context;

      context = gimp_dialog_factory_get_context (dock_window->p->dialog_factory);

      gimp_context_copy_properties (context,
                                    dock_window->p->context,
                                    GIMP_CONTEXT_PROP_MASK_DISPLAY |
                                    GIMP_CONTEXT_PROP_MASK_IMAGE);
    }
}


void
gimp_dock_window_add_dock (GimpDockWindow *dock_window,
                           GimpDock       *dock,
                           gint            index)
{
  g_return_if_fail (GIMP_IS_DOCK_WINDOW (dock_window));
  g_return_if_fail (GIMP_IS_DOCK (dock));

  gimp_dock_columns_add_dock (dock_window->p->dock_columns,
                              GIMP_DOCK (dock),
                              index);

  g_signal_connect_object (dock, "description-invalidated",
                           G_CALLBACK (gimp_dock_window_update_title),
                           dock_window,
                           G_CONNECT_SWAPPED);

  /* Some docks like the toolbox dock needs to maintain special hints
   * on its container GtkWindow, allow those to do so
   */

  gimp_dock_set_host_geometry_hints (dock, GTK_WINDOW (dock_window));
  g_signal_connect_object (dock, "geometry-invalidated",
                           G_CALLBACK (gimp_dock_set_host_geometry_hints),
                           dock_window, 0);
}

void
gimp_dock_window_remove_dock (GimpDockWindow *dock_window,
                              GimpDock       *dock)
{
  gimp_dock_columns_remove_dock (dock_window->p->dock_columns,
                                 GIMP_DOCK (dock));

  g_signal_handlers_disconnect_by_func (dock,
                                        gimp_dock_window_update_title,
                                        dock_window);
  g_signal_handlers_disconnect_by_func (dock,
                                        gimp_dock_set_host_geometry_hints,
                                        dock_window);
}

GtkWidget *
gimp_dock_window_new (const gchar       *role,
                      const gchar       *ui_manager_name,
                      gboolean           allow_dockbook_absence,
                      GimpDialogFactory *dialog_factory,
                      GimpContext       *context)
{
  g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (dialog_factory), NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);

  return g_object_new (GIMP_TYPE_DOCK_WINDOW,
                       "role",                   role,
                       "ui-manager-name",        ui_manager_name,
                       "allow-dockbook-absence", allow_dockbook_absence,
                       "dialog-factory",         dialog_factory,
                       "context",                context,
                       NULL);
}

gint
gimp_dock_window_get_id (GimpDockWindow *dock_window)
{
  g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), 0);

  return dock_window->p->ID;
}

GimpContext *
gimp_dock_window_get_context (GimpDockWindow *dock_window)
{
  g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), NULL);

  return dock_window->p->context;
}

gboolean
gimp_dock_window_get_auto_follow_active (GimpDockWindow *dock_window)
{
  g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), FALSE);

  return dock_window->p->auto_follow_active;
}

void
gimp_dock_window_set_auto_follow_active (GimpDockWindow *dock_window,
                                         gboolean        auto_follow_active)
{
  g_return_if_fail (GIMP_IS_DOCK_WINDOW (dock_window));

  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dock_window->p->auto_button),
                                auto_follow_active ? TRUE : FALSE);
}

gboolean
gimp_dock_window_get_show_image_menu (GimpDockWindow *dock_window)
{
  g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), FALSE);

  return dock_window->p->show_image_menu;
}

void
gimp_dock_window_set_show_image_menu (GimpDockWindow *dock_window,
                                      gboolean        show)
{
  GtkWidget *parent;

  g_return_if_fail (GIMP_IS_DOCK_WINDOW (dock_window));

  parent = gtk_widget_get_parent (dock_window->p->image_combo);

  gtk_widget_set_visible (parent, show);

  dock_window->p->show_image_menu = show ? TRUE : FALSE;
}

void
gimp_dock_window_setup (GimpDockWindow *dock_window,
                        GimpDockWindow *template)
{
  gimp_dock_window_set_auto_follow_active (GIMP_DOCK_WINDOW (dock_window),
                                           template->p->auto_follow_active);
  gimp_dock_window_set_show_image_menu (GIMP_DOCK_WINDOW (dock_window),
                                        template->p->show_image_menu);
}

/**
 * gimp_dock_window_has_toolbox:
 * @dock_window:
 *
 * Returns: %TRUE if the dock window has a GimpToolbox dock, %FALSE
 * otherwise.
 **/

gboolean
gimp_dock_window_has_toolbox (GimpDockWindow *dock_window)
{
  GList *iter = NULL;

  g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), FALSE);

  for (iter = gimp_dock_window_get_docks_self (dock_window);
       iter;
       iter = g_list_next (iter))
    {
      if (GIMP_IS_TOOLBOX (iter->data))
        return TRUE;
    }

  return FALSE;
}


/**
 * gimp_dock_window_from_dock:
 * @dock:
 *
 * For convenience.
 *
 * Returns: If the toplevel widget for the dock is a GimpDockWindow,
 * return that. Otherwise return %NULL.
 **/

GimpDockWindow *
gimp_dock_window_from_dock (GimpDock *dock)
{
  GtkWidget *toplevel = NULL;

  g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);

  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (dock));

  if (GIMP_IS_DOCK_WINDOW (toplevel))
    return GIMP_DOCK_WINDOW (toplevel);
  else
    return NULL;
}

Messung
CHZG
819910093

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© 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.