windows-actions.c 18 KB
Newer Older
1 2 3
/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7 8 9 10 11 12 13 14
 * (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
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 17 18 19
 */

#include "config.h"

20
#include <gegl.h>
21
#include <gtk/gtk.h>
22
#include <gdk/gdkkeysyms.h>
23 24 25 26 27 28

#include "libgimpbase/gimpbase.h"
#include "libgimpwidgets/gimpwidgets.h"

#include "actions-types.h"

Martin Nordholts's avatar
Martin Nordholts committed
29 30 31
#include "config/gimpdisplayconfig.h"
#include "config/gimpguiconfig.h"

32 33 34 35 36 37 38
#include "core/gimp.h"
#include "core/gimpimage.h"
#include "core/gimplist.h"

#include "file/file-utils.h"

#include "widgets/gimpactiongroup.h"
39 40
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdock.h"
41
#include "widgets/gimpdockwindow.h"
42 43 44 45
#include "widgets/gimphelp-ids.h"

#include "display/gimpdisplay.h"

46 47
#include "dialogs/dialogs.h"

48 49 50 51 52 53
#include "windows-actions.h"
#include "windows-commands.h"

#include "gimp-intl.h"


Martin Nordholts's avatar
Martin Nordholts committed
54 55 56 57 58 59 60 61 62
static void  windows_actions_display_add               (GimpContainer     *container,
                                                        GimpDisplay       *display,
                                                        GimpActionGroup   *group);
static void  windows_actions_display_remove            (GimpContainer     *container,
                                                        GimpDisplay       *display,
                                                        GimpActionGroup   *group);
static void  windows_actions_image_notify              (GimpDisplay       *display,
                                                        const GParamSpec  *unused,
                                                        GimpActionGroup   *group);
63 64
static void  windows_actions_update_display_accels     (GimpActionGroup   *group);

Martin Nordholts's avatar
Martin Nordholts committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
static void  windows_actions_dock_window_added         (GimpDialogFactory *factory,
                                                        GimpDockWindow    *dock_window,
                                                        GimpActionGroup   *group);
static void  windows_actions_dock_window_removed       (GimpDialogFactory *factory,
                                                        GimpDockWindow    *dock_window,
                                                        GimpActionGroup   *group);
static void  windows_actions_dock_window_notify        (GimpDockWindow    *dock,
                                                        const GParamSpec  *pspec,
                                                        GimpActionGroup   *group);
static void  windows_actions_recent_add                (GimpContainer     *container,
                                                        GimpSessionInfo   *info,
                                                        GimpActionGroup   *group);
static void  windows_actions_recent_remove             (GimpContainer     *container,
                                                        GimpSessionInfo   *info,
                                                        GimpActionGroup   *group);
static void  windows_actions_single_window_mode_notify (GimpDisplayConfig *config,
                                                        GParamSpec        *pspec,
                                                        GimpActionGroup   *group);
83

84

85 86 87 88 89 90 91
/* The only reason we have "Tab" in the action entries below is to
 * give away the hardcoded keyboard shortcut. If the user changes the
 * shortcut to something else, both that shortcut and Tab will
 * work. The reason we have the shortcut hardcoded is beccause
 * gtk_accelerator_valid() returns FALSE for GDK_tab.
 */

92 93
static const GimpActionEntry windows_actions[] =
{
94 95 96 97 98 99
  { "windows-menu",         NULL, NC_("windows-action",
                                      "_Windows")               },
  { "windows-docks-menu",   NULL, NC_("windows-action",
                                      "_Recently Closed Docks") },
  { "windows-dialogs-menu", NULL, NC_("windows-action",
                                      "_Dockable Dialogs")      },
100 101 102 103 104 105 106 107 108 109 110 111

  { "windows-show-display-next", NULL,
    NC_("windows-action", "Next Image"), "<alt>Tab",
    NC_("windows-action", "Switch to the next image"),
    G_CALLBACK (windows_show_display_next_cmd_callback),
    NULL },

  { "windows-show-display-previous", NULL,
    NC_("windows-action", "Previous Image"), "<alt><shift>Tab",
    NC_("windows-action", "Switch to the previous image"),
    G_CALLBACK (windows_show_display_previous_cmd_callback),
    NULL }
112 113
};

Martin Nordholts's avatar
Martin Nordholts committed
114 115
static const GimpToggleActionEntry windows_toggle_actions[] =
{
116
  { "windows-hide-docks", NULL,
117
    NC_("windows-action", "Hide Docks"), "Tab",
118 119 120 121 122
    NC_("windows-action", "When enabled docks and other dialogs are hidden, leaving only image windows."),
    G_CALLBACK (windows_hide_docks_cmd_callback),
    FALSE,
    GIMP_HELP_WINDOWS_HIDE_DOCKS },

Martin Nordholts's avatar
Martin Nordholts committed
123
  { "windows-use-single-window-mode", NULL,
124
    NC_("windows-action", "Single-Window Mode"), NULL,
125
    NC_("windows-action", "When enabled GIMP is in a single-window mode."),
Martin Nordholts's avatar
Martin Nordholts committed
126 127 128 129 130
    G_CALLBACK (windows_use_single_window_mode_cmd_callback),
    FALSE,
    GIMP_HELP_WINDOWS_USE_SINGLE_WINDOW_MODE }
};

131 132 133 134 135 136

void
windows_actions_setup (GimpActionGroup *group)
{
  GList *list;

137
  gimp_action_group_add_actions (group, "windows-action",
138 139 140
                                 windows_actions,
                                 G_N_ELEMENTS (windows_actions));

Martin Nordholts's avatar
Martin Nordholts committed
141 142 143 144
  gimp_action_group_add_toggle_actions (group, "windows-action",
                                        windows_toggle_actions,
                                        G_N_ELEMENTS (windows_toggle_actions));

145 146
  gimp_action_group_set_action_hide_empty (group, "windows-docks-menu", FALSE);

147 148 149 150 151 152 153
  g_signal_connect_object (group->gimp->displays, "add",
                           G_CALLBACK (windows_actions_display_add),
                           group, 0);
  g_signal_connect_object (group->gimp->displays, "remove",
                           G_CALLBACK (windows_actions_display_remove),
                           group, 0);

154
  for (list = gimp_get_display_iter (group->gimp);
155 156 157 158 159 160 161
       list;
       list = g_list_next (list))
    {
      GimpDisplay *display = list->data;

      windows_actions_display_add (group->gimp->displays, display, group);
    }
162

163
  g_signal_connect_object (gimp_dialog_factory_get_singleton (), "dock-window-added",
164
                           G_CALLBACK (windows_actions_dock_window_added),
165
                           group, 0);
166
  g_signal_connect_object (gimp_dialog_factory_get_singleton (), "dock-window-removed",
167
                           G_CALLBACK (windows_actions_dock_window_removed),
168 169
                           group, 0);

170
  for (list = gimp_dialog_factory_get_open_dialogs (gimp_dialog_factory_get_singleton ());
171 172 173
       list;
       list = g_list_next (list))
    {
174
      GimpDockWindow *dock_window = list->data;
175

176
      if (GIMP_IS_DOCK_WINDOW (dock_window))
177
        windows_actions_dock_window_added (gimp_dialog_factory_get_singleton (),
178 179
                                           dock_window,
                                           group);
180
    }
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

  g_signal_connect_object (global_recent_docks, "add",
                           G_CALLBACK (windows_actions_recent_add),
                           group, 0);
  g_signal_connect_object (global_recent_docks, "remove",
                           G_CALLBACK (windows_actions_recent_remove),
                           group, 0);

  for (list = GIMP_LIST (global_recent_docks)->list;
       list;
       list = g_list_next (list))
    {
      GimpSessionInfo *info = list->data;

      windows_actions_recent_add (global_recent_docks, info, group);
    }
Martin Nordholts's avatar
Martin Nordholts committed
197 198 199 200

  g_signal_connect_object (group->gimp->config, "notify::single-window-mode",
                           G_CALLBACK (windows_actions_single_window_mode_notify),
                           group, 0);
201 202 203 204 205 206
}

void
windows_actions_update (GimpActionGroup *group,
                        gpointer         data)
{
Martin Nordholts's avatar
Martin Nordholts committed
207 208 209 210 211 212
  GimpGuiConfig *config = GIMP_GUI_CONFIG (group->gimp->config);

#define SET_ACTIVE(action,condition) \
        gimp_action_group_set_action_active (group, action, (condition) != 0)

  SET_ACTIVE ("windows-use-single-window-mode", config->single_window_mode);
213
  SET_ACTIVE ("windows-hide-docks", config->hide_docks);
Martin Nordholts's avatar
Martin Nordholts committed
214 215

#undef SET_ACTIVE
216 217
}

218
gchar *
219
windows_actions_dock_window_to_action_name (GimpDockWindow *dock_window)
220 221
{
  return g_strdup_printf ("windows-dock-%04d",
222
                          gimp_dock_window_get_id (dock_window));
223 224
}

225 226 227 228 229 230 231 232 233 234 235 236

/*  private functions  */

static void
windows_actions_display_add (GimpContainer   *container,
                             GimpDisplay     *display,
                             GimpActionGroup *group)
{
  g_signal_connect_object (display, "notify::image",
                           G_CALLBACK (windows_actions_image_notify),
                           group, 0);

237
  if (gimp_display_get_image (display))
238 239 240 241 242 243 244 245 246
    windows_actions_image_notify (display, NULL, group);
}

static void
windows_actions_display_remove (GimpContainer   *container,
                                GimpDisplay     *display,
                                GimpActionGroup *group)
{
  GtkAction *action;
247
  gchar     *action_name = gimp_display_get_action_name (display);
248 249 250 251 252 253 254

  action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name);

  if (action)
    gtk_action_group_remove_action (GTK_ACTION_GROUP (group), action);

  g_free (action_name);
255 256

  windows_actions_update_display_accels (group);
257 258 259 260 261 262 263
}

static void
windows_actions_image_notify (GimpDisplay      *display,
                              const GParamSpec *unused,
                              GimpActionGroup  *group)
{
264 265 266
  GimpImage *image = gimp_display_get_image (display);

  if (image)
267 268
    {
      GtkAction *action;
269
      gchar     *action_name = gimp_display_get_action_name (display);
270 271 272 273 274 275 276 277 278 279 280 281 282 283

      action = gtk_action_group_get_action (GTK_ACTION_GROUP (group),
                                            action_name);

      if (! action)
        {
          GimpActionEntry entry;

          entry.name        = action_name;
          entry.stock_id    = GIMP_STOCK_IMAGE;
          entry.label       = "";
          entry.accelerator = NULL;
          entry.tooltip     = NULL;
          entry.callback    = G_CALLBACK (windows_show_display_cmd_callback);
284
          entry.help_id     = NULL;
285

286
          gimp_action_group_add_actions (group, NULL, &entry, 1);
287

288 289 290
          gimp_action_group_set_action_always_show_image (group, action_name,
                                                          TRUE);

291 292 293 294 295 296 297 298 299 300 301 302 303
          action = gtk_action_group_get_action (GTK_ACTION_GROUP (group),
                                                action_name);

          g_object_set_data (G_OBJECT (action), "display", display);
        }

      {
        const gchar *uri;
        gchar       *filename;
        gchar       *basename;
        gchar       *escaped;
        gchar       *title;

304
        uri = gimp_image_get_uri_or_untitled (image);
305 306 307 308 309 310 311 312

        filename = file_utils_uri_display_name (uri);
        basename = file_utils_uri_display_basename (uri);

        escaped = gimp_escape_uline (basename);
        g_free (basename);

        title = g_strdup_printf ("%s-%d.%d", escaped,
313
                                 gimp_image_get_ID (image),
314
                                 gimp_display_get_instance (display));
315 316 317 318 319
        g_free (escaped);

        g_object_set (action,
                      "label",    title,
                      "tooltip",  filename,
320
                      "viewable", image,
321 322 323 324 325 326 327 328
                      "context",  gimp_get_user_context (group->gimp),
                      NULL);

        g_free (filename);
        g_free (title);
      }

      g_free (action_name);
329 330

      windows_actions_update_display_accels (group);
331 332 333 334 335 336
    }
  else
    {
      windows_actions_display_remove (group->gimp->displays, display, group);
    }
}
337

338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
static void
windows_actions_update_display_accels (GimpActionGroup *group)
{
  GList *list;
  gint   i;

  for (list = gimp_get_display_iter (group->gimp), i = 0;
       list && i < 10;
       list = g_list_next (list), i++)
    {
      GimpDisplay *display = list->data;
      GtkAction   *action;
      gchar       *action_name;

      if (! gimp_display_get_image (display))
        break;

      action_name = gimp_display_get_action_name (display);

      action = gtk_action_group_get_action (GTK_ACTION_GROUP (group),
                                            action_name);
Massimo Valentini's avatar
Massimo Valentini committed
359
      g_free (action_name);
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379

      if (action)
        {
          const gchar *accel_path;
          guint        accel_key;

          accel_path = gtk_action_get_accel_path (action);

          if (i < 9)
            accel_key = GDK_KEY_1 + i;
          else
            accel_key = GDK_KEY_0;

          gtk_accel_map_change_entry (accel_path,
                                      accel_key, GDK_MOD1_MASK,
                                      TRUE);
        }
    }
}

380
static void
381 382 383
windows_actions_dock_window_added (GimpDialogFactory *factory,
                                   GimpDockWindow    *dock_window,
                                   GimpActionGroup   *group)
384 385 386
{
  GtkAction       *action;
  GimpActionEntry  entry;
387
  gchar           *action_name = windows_actions_dock_window_to_action_name (dock_window);
388 389 390 391 392 393 394

  entry.name        = action_name;
  entry.stock_id    = NULL;
  entry.label       = "";
  entry.accelerator = NULL;
  entry.tooltip     = NULL;
  entry.callback    = G_CALLBACK (windows_show_dock_cmd_callback);
395
  entry.help_id     = GIMP_HELP_WINDOWS_SHOW_DOCK;
396

397
  gimp_action_group_add_actions (group, NULL, &entry, 1);
398 399 400 401

  action = gtk_action_group_get_action (GTK_ACTION_GROUP (group),
                                        action_name);

402 403 404 405
  g_object_set (action,
                "ellipsize", PANGO_ELLIPSIZE_END,
                NULL);

406
  g_object_set_data (G_OBJECT (action), "dock-window", dock_window);
407 408 409

  g_free (action_name);

410 411
  g_signal_connect_object (dock_window, "notify::title",
                           G_CALLBACK (windows_actions_dock_window_notify),
412 413
                           group, 0);

414 415
  if (gtk_window_get_title (GTK_WINDOW (dock_window)))
    windows_actions_dock_window_notify (dock_window, NULL, group);
416 417 418
}

static void
419 420 421
windows_actions_dock_window_removed (GimpDialogFactory *factory,
                                     GimpDockWindow    *dock_window,
                                     GimpActionGroup   *group)
422 423
{
  GtkAction *action;
424
  gchar     *action_name = windows_actions_dock_window_to_action_name (dock_window);
425 426 427 428 429 430 431 432 433 434

  action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name);

  if (action)
    gtk_action_group_remove_action (GTK_ACTION_GROUP (group), action);

  g_free (action_name);
}

static void
435 436 437
windows_actions_dock_window_notify (GimpDockWindow   *dock_window,
                                    const GParamSpec *pspec,
                                    GimpActionGroup  *group)
438 439
{
  GtkAction *action;
440
  gchar     *action_name;
441

442
  action_name = windows_actions_dock_window_to_action_name (dock_window);
443
  action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name);
444
  g_free (action_name);
445 446 447

  if (action)
    g_object_set (action,
448 449
                  "label",   gtk_window_get_title (GTK_WINDOW (dock_window)),
                  "tooltip", gtk_window_get_title (GTK_WINDOW (dock_window)),
450 451
                  NULL);
}
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478

static void
windows_actions_recent_add (GimpContainer   *container,
                            GimpSessionInfo *info,
                            GimpActionGroup *group)
{
  GtkAction       *action;
  GimpActionEntry  entry;
  gint             info_id;
  static gint      info_id_counter = 1;
  gchar           *action_name;

  info_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info),
                                                "recent-action-id"));

  if (! info_id)
    {
      info_id = info_id_counter++;

      g_object_set_data (G_OBJECT (info), "recent-action-id",
                         GINT_TO_POINTER (info_id));
    }

  action_name = g_strdup_printf ("windows-recent-%04d", info_id);

  entry.name        = action_name;
  entry.stock_id    = NULL;
479
  entry.label       = gimp_object_get_name (info);
480
  entry.accelerator = NULL;
481
  entry.tooltip     = gimp_object_get_name (info);
482
  entry.callback    = G_CALLBACK (windows_open_recent_cmd_callback);
483
  entry.help_id     = GIMP_HELP_WINDOWS_OPEN_RECENT_DOCK;
484

485
  gimp_action_group_add_actions (group, NULL, &entry, 1);
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520

  action = gtk_action_group_get_action (GTK_ACTION_GROUP (group),
                                        action_name);

  g_object_set (action,
                "ellipsize",       PANGO_ELLIPSIZE_END,
                "max-width-chars", 30,
                NULL);

  g_object_set_data (G_OBJECT (action), "info", info);

  g_free (action_name);
}

static void
windows_actions_recent_remove (GimpContainer   *container,
                               GimpSessionInfo *info,
                               GimpActionGroup *group)
{
  GtkAction *action;
  gint       info_id;
  gchar     *action_name;

  info_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info),
                                                "recent-action-id"));

  action_name = g_strdup_printf ("windows-recent-%04d", info_id);

  action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name);

  if (action)
    gtk_action_group_remove_action (GTK_ACTION_GROUP (group), action);

  g_free (action_name);
}
Martin Nordholts's avatar
Martin Nordholts committed
521 522 523 524 525 526 527 528 529 530

static void
windows_actions_single_window_mode_notify (GimpDisplayConfig *config,
                                           GParamSpec        *pspec,
                                           GimpActionGroup   *group)
{
  gimp_action_group_set_action_active (group,
                                       "windows-use-single-window-mode",
                                       GIMP_GUI_CONFIG (config)->single_window_mode);
}