windows-actions.c 17.8 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
#include "core/gimp.h"
#include "core/gimpimage.h"
#include "core/gimplist.h"

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

#include "display/gimpdisplay.h"

44 45
#include "dialogs/dialogs.h"

46 47 48 49 50 51
#include "windows-actions.h"
#include "windows-commands.h"

#include "gimp-intl.h"


Martin Nordholts's avatar
Martin Nordholts committed
52 53 54 55 56 57 58 59 60
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);
61 62
static void  windows_actions_update_display_accels     (GimpActionGroup   *group);

Martin Nordholts's avatar
Martin Nordholts committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
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);
81

82

83 84 85
/* 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
86
 * work. The reason we have the shortcut hardcoded is because
87 88 89
 * gtk_accelerator_valid() returns FALSE for GDK_tab.
 */

90 91
static const GimpActionEntry windows_actions[] =
{
92 93 94 95 96 97
  { "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")      },
98 99 100 101 102 103 104 105 106 107 108 109

  { "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 }
110 111
};

Martin Nordholts's avatar
Martin Nordholts committed
112 113
static const GimpToggleActionEntry windows_toggle_actions[] =
{
114
  { "windows-hide-docks", NULL,
115
    NC_("windows-action", "Hide Docks"), "Tab",
116 117 118 119 120
    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
121
  { "windows-use-single-window-mode", NULL,
122
    NC_("windows-action", "Single-Window Mode"), NULL,
123
    NC_("windows-action", "When enabled GIMP is in a single-window mode."),
Martin Nordholts's avatar
Martin Nordholts committed
124 125 126 127 128
    G_CALLBACK (windows_use_single_window_mode_cmd_callback),
    FALSE,
    GIMP_HELP_WINDOWS_USE_SINGLE_WINDOW_MODE }
};

129 130 131 132 133 134

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

135
  gimp_action_group_add_actions (group, "windows-action",
136 137 138
                                 windows_actions,
                                 G_N_ELEMENTS (windows_actions));

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

143 144
  gimp_action_group_set_action_hide_empty (group, "windows-docks-menu", FALSE);

145 146 147 148 149 150 151
  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);

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

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

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

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

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

  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
195 196 197 198

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

void
windows_actions_update (GimpActionGroup *group,
                        gpointer         data)
{
Martin Nordholts's avatar
Martin Nordholts committed
205 206 207 208 209 210
  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);
211
  SET_ACTIVE ("windows-hide-docks", config->hide_docks);
Martin Nordholts's avatar
Martin Nordholts committed
212 213

#undef SET_ACTIVE
214 215
}

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

223 224 225 226 227 228 229 230 231 232 233 234

/*  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);

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

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

  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);
253 254

  windows_actions_update_display_accels (group);
255 256 257 258 259 260 261
}

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

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

      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);
282
          entry.help_id     = NULL;
283

284
          gimp_action_group_add_actions (group, NULL, &entry, 1);
285

286 287 288
          gimp_action_group_set_action_always_show_image (group, action_name,
                                                          TRUE);

289 290 291 292 293 294 295
          action = gtk_action_group_get_action (GTK_ACTION_GROUP (group),
                                                action_name);

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

      {
296
        const gchar *display_name;
297 298 299
        gchar       *escaped;
        gchar       *title;

300 301
        display_name = gimp_image_get_display_name (image);
        escaped = gimp_escape_uline (display_name);
302 303

        title = g_strdup_printf ("%s-%d.%d", escaped,
304
                                 gimp_image_get_ID (image),
305
                                 gimp_display_get_instance (display));
306 307 308 309
        g_free (escaped);

        g_object_set (action,
                      "label",    title,
310
                      "tooltip",  gimp_image_get_display_path (image),
311
                      "viewable", image,
312 313 314 315 316 317 318
                      "context",  gimp_get_user_context (group->gimp),
                      NULL);

        g_free (title);
      }

      g_free (action_name);
319 320

      windows_actions_update_display_accels (group);
321 322 323 324 325 326
    }
  else
    {
      windows_actions_display_remove (group->gimp->displays, display, group);
    }
}
327

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
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
349
      g_free (action_name);
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369

      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);
        }
    }
}

370
static void
371 372 373
windows_actions_dock_window_added (GimpDialogFactory *factory,
                                   GimpDockWindow    *dock_window,
                                   GimpActionGroup   *group)
374 375 376
{
  GtkAction       *action;
  GimpActionEntry  entry;
377
  gchar           *action_name = windows_actions_dock_window_to_action_name (dock_window);
378 379 380 381 382 383 384

  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);
385
  entry.help_id     = GIMP_HELP_WINDOWS_SHOW_DOCK;
386

387
  gimp_action_group_add_actions (group, NULL, &entry, 1);
388 389 390 391

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

392 393 394 395
  g_object_set (action,
                "ellipsize", PANGO_ELLIPSIZE_END,
                NULL);

396
  g_object_set_data (G_OBJECT (action), "dock-window", dock_window);
397 398 399

  g_free (action_name);

400 401
  g_signal_connect_object (dock_window, "notify::title",
                           G_CALLBACK (windows_actions_dock_window_notify),
402 403
                           group, 0);

404 405
  if (gtk_window_get_title (GTK_WINDOW (dock_window)))
    windows_actions_dock_window_notify (dock_window, NULL, group);
406 407 408
}

static void
409 410 411
windows_actions_dock_window_removed (GimpDialogFactory *factory,
                                     GimpDockWindow    *dock_window,
                                     GimpActionGroup   *group)
412 413
{
  GtkAction *action;
414
  gchar     *action_name = windows_actions_dock_window_to_action_name (dock_window);
415 416 417 418 419 420 421 422 423 424

  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
425 426 427
windows_actions_dock_window_notify (GimpDockWindow   *dock_window,
                                    const GParamSpec *pspec,
                                    GimpActionGroup  *group)
428 429
{
  GtkAction *action;
430
  gchar     *action_name;
431

432
  action_name = windows_actions_dock_window_to_action_name (dock_window);
433
  action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name);
434
  g_free (action_name);
435 436 437

  if (action)
    g_object_set (action,
438 439
                  "label",   gtk_window_get_title (GTK_WINDOW (dock_window)),
                  "tooltip", gtk_window_get_title (GTK_WINDOW (dock_window)),
440 441
                  NULL);
}
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468

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;
469
  entry.label       = gimp_object_get_name (info);
470
  entry.accelerator = NULL;
471
  entry.tooltip     = gimp_object_get_name (info);
472
  entry.callback    = G_CALLBACK (windows_open_recent_cmd_callback);
473
  entry.help_id     = GIMP_HELP_WINDOWS_OPEN_RECENT_DOCK;
474

475
  gimp_action_group_add_actions (group, NULL, &entry, 1);
476 477 478 479 480 481 482 483 484 485 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

  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
511 512 513 514 515 516 517 518 519 520

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);
}