1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
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 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <string.h>
21
22 #undef GSEAL_ENABLE
23
24 #include <gegl.h>
25 #include <gtk/gtk.h>
26
27 #include "libgimpbase/gimpbase.h"
28 #include "libgimpwidgets/gimpwidgets.h"
29
30 #include "widgets-types.h"
31
32 #include "config/gimpguiconfig.h"
33
34 #include "core/gimp.h"
35 #include "core/gimpcontext.h"
36
37 #include "file/file-open.h"
38
39 #include "gimpcairo-wilber.h"
40 #include "gimpdevices.h"
41 #include "gimpdialogfactory.h"
42 #include "gimpdockwindow.h"
43 #include "gimphelp-ids.h"
44 #include "gimppanedbox.h"
45 #include "gimptoolbox.h"
46 #include "gimptoolbox-color-area.h"
47 #include "gimptoolbox-dnd.h"
48 #include "gimptoolbox-image-area.h"
49 #include "gimptoolbox-indicator-area.h"
50 #include "gimptoolpalette.h"
51 #include "gimpuimanager.h"
52 #include "gimpwidgets-utils.h"
53 #include "gtkhwrapbox.h"
54
55 #include "about.h"
56
57 #include "gimp-intl.h"
58
59
60 enum
61 {
62 PROP_0,
63 PROP_CONTEXT
64 };
65
66
67 struct _GimpToolboxPrivate
68 {
69 GimpContext *context;
70
71 GtkWidget *vbox;
72
73 GtkWidget *header;
74 GtkWidget *tool_palette;
75 GtkWidget *area_wbox;
76 GtkWidget *color_area;
77 GtkWidget *foo_area;
78 GtkWidget *image_area;
79
80 gint area_rows;
81 gint area_columns;
82
83 GimpPanedBox *drag_handler;
84
85 gboolean in_destruction;
86 };
87
88
89 static void gimp_toolbox_constructed (GObject *object);
90 static void gimp_toolbox_dispose (GObject *object);
91 static void gimp_toolbox_set_property (GObject *object,
92 guint property_id,
93 const GValue *value,
94 GParamSpec *pspec);
95 static void gimp_toolbox_get_property (GObject *object,
96 guint property_id,
97 GValue *value,
98 GParamSpec *pspec);
99 static void gimp_toolbox_size_allocate (GtkWidget *widget,
100 GtkAllocation *allocation);
101 static gboolean gimp_toolbox_button_press_event (GtkWidget *widget,
102 GdkEventButton *event);
103 static void gimp_toolbox_drag_leave (GtkWidget *widget,
104 GdkDragContext *context,
105 guint time,
106 GimpToolbox *toolbox);
107 static gboolean gimp_toolbox_drag_motion (GtkWidget *widget,
108 GdkDragContext *context,
109 gint x,
110 gint y,
111 guint time,
112 GimpToolbox *toolbox);
113 static gboolean gimp_toolbox_drag_drop (GtkWidget *widget,
114 GdkDragContext *context,
115 gint x,
116 gint y,
117 guint time,
118 GimpToolbox *toolbox);
119 static gchar * gimp_toolbox_get_description (GimpDock *dock,
120 gboolean complete);
121 static void gimp_toolbox_set_host_geometry_hints (GimpDock *dock,
122 GtkWindow *window);
123 static void gimp_toolbox_book_added (GimpDock *dock,
124 GimpDockbook *dockbook);
125 static void gimp_toolbox_book_removed (GimpDock *dock,
126 GimpDockbook *dockbook);
127 static void gimp_toolbox_size_request_wilber (GtkWidget *widget,
128 GtkRequisition *requisition,
129 GimpToolbox *toolbox);
130 static gboolean gimp_toolbox_expose_wilber (GtkWidget *widget,
131 GdkEventExpose *event);
132 static GtkWidget * toolbox_create_color_area (GimpToolbox *toolbox,
133 GimpContext *context);
134 static GtkWidget * toolbox_create_foo_area (GimpToolbox *toolbox,
135 GimpContext *context);
136 static GtkWidget * toolbox_create_image_area (GimpToolbox *toolbox,
137 GimpContext *context);
138 static void toolbox_area_notify (GimpGuiConfig *config,
139 GParamSpec *pspec,
140 GtkWidget *area);
141 static void toolbox_paste_received (GtkClipboard *clipboard,
142 const gchar *text,
143 gpointer data);
144
145
G_DEFINE_TYPE_WITH_PRIVATE(GimpToolbox,gimp_toolbox,GIMP_TYPE_DOCK)146 G_DEFINE_TYPE_WITH_PRIVATE (GimpToolbox, gimp_toolbox, GIMP_TYPE_DOCK)
147
148 #define parent_class gimp_toolbox_parent_class
149
150
151 static void
152 gimp_toolbox_class_init (GimpToolboxClass *klass)
153 {
154 GObjectClass *object_class = G_OBJECT_CLASS (klass);
155 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
156 GimpDockClass *dock_class = GIMP_DOCK_CLASS (klass);
157
158 object_class->constructed = gimp_toolbox_constructed;
159 object_class->dispose = gimp_toolbox_dispose;
160 object_class->set_property = gimp_toolbox_set_property;
161 object_class->get_property = gimp_toolbox_get_property;
162
163 widget_class->size_allocate = gimp_toolbox_size_allocate;
164 widget_class->button_press_event = gimp_toolbox_button_press_event;
165
166 dock_class->get_description = gimp_toolbox_get_description;
167 dock_class->set_host_geometry_hints = gimp_toolbox_set_host_geometry_hints;
168 dock_class->book_added = gimp_toolbox_book_added;
169 dock_class->book_removed = gimp_toolbox_book_removed;
170
171 g_object_class_install_property (object_class, PROP_CONTEXT,
172 g_param_spec_object ("context",
173 NULL, NULL,
174 GIMP_TYPE_CONTEXT,
175 GIMP_PARAM_READWRITE |
176 G_PARAM_CONSTRUCT));
177 }
178
179 static void
gimp_toolbox_init(GimpToolbox * toolbox)180 gimp_toolbox_init (GimpToolbox *toolbox)
181 {
182 toolbox->p = gimp_toolbox_get_instance_private (toolbox);
183
184 gimp_help_connect (GTK_WIDGET (toolbox), gimp_standard_help_func,
185 GIMP_HELP_TOOLBOX, NULL);
186 }
187
188 static void
gimp_toolbox_constructed(GObject * object)189 gimp_toolbox_constructed (GObject *object)
190 {
191 GimpToolbox *toolbox = GIMP_TOOLBOX (object);
192 GimpGuiConfig *config;
193 GtkWidget *main_vbox;
194 GdkDisplay *display;
195 GList *list;
196
197 gimp_assert (GIMP_IS_CONTEXT (toolbox->p->context));
198
199 config = GIMP_GUI_CONFIG (toolbox->p->context->gimp->config);
200
201 main_vbox = gimp_dock_get_main_vbox (GIMP_DOCK (toolbox));
202
203 toolbox->p->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
204 gtk_box_pack_start (GTK_BOX (main_vbox), toolbox->p->vbox, FALSE, FALSE, 0);
205 gtk_box_reorder_child (GTK_BOX (main_vbox), toolbox->p->vbox, 0);
206 gtk_widget_show (toolbox->p->vbox);
207
208 /* Use g_signal_connect() also for the toolbox itself so we can pass
209 * data and reuse the same function for the vbox
210 */
211 g_signal_connect (toolbox, "drag-leave",
212 G_CALLBACK (gimp_toolbox_drag_leave),
213 toolbox);
214 g_signal_connect (toolbox, "drag-motion",
215 G_CALLBACK (gimp_toolbox_drag_motion),
216 toolbox);
217 g_signal_connect (toolbox, "drag-drop",
218 G_CALLBACK (gimp_toolbox_drag_drop),
219 toolbox);
220 g_signal_connect (toolbox->p->vbox, "drag-leave",
221 G_CALLBACK (gimp_toolbox_drag_leave),
222 toolbox);
223 g_signal_connect (toolbox->p->vbox, "drag-motion",
224 G_CALLBACK (gimp_toolbox_drag_motion),
225 toolbox);
226 g_signal_connect (toolbox->p->vbox, "drag-drop",
227 G_CALLBACK (gimp_toolbox_drag_drop),
228 toolbox);
229
230 toolbox->p->header = gtk_frame_new (NULL);
231 gtk_frame_set_shadow_type (GTK_FRAME (toolbox->p->header), GTK_SHADOW_NONE);
232 gtk_box_pack_start (GTK_BOX (toolbox->p->vbox), toolbox->p->header,
233 FALSE, FALSE, 0);
234
235 g_object_bind_property (config, "toolbox-wilber",
236 toolbox->p->header, "visible",
237 G_BINDING_SYNC_CREATE);
238
239 g_signal_connect (toolbox->p->header, "size-request",
240 G_CALLBACK (gimp_toolbox_size_request_wilber),
241 toolbox);
242 g_signal_connect (toolbox->p->header, "expose-event",
243 G_CALLBACK (gimp_toolbox_expose_wilber),
244 toolbox);
245
246 gimp_help_set_help_data (toolbox->p->header,
247 _("Drop image files here to open them"), NULL);
248
249 toolbox->p->tool_palette = gimp_tool_palette_new ();
250 gimp_tool_palette_set_toolbox (GIMP_TOOL_PALETTE (toolbox->p->tool_palette),
251 toolbox);
252 gtk_box_pack_start (GTK_BOX (toolbox->p->vbox), toolbox->p->tool_palette,
253 FALSE, FALSE, 0);
254 gtk_widget_show (toolbox->p->tool_palette);
255
256 toolbox->p->area_wbox = gtk_hwrap_box_new (FALSE);
257 gtk_wrap_box_set_justify (GTK_WRAP_BOX (toolbox->p->area_wbox), GTK_JUSTIFY_TOP);
258 gtk_wrap_box_set_line_justify (GTK_WRAP_BOX (toolbox->p->area_wbox),
259 GTK_JUSTIFY_LEFT);
260 gtk_wrap_box_set_aspect_ratio (GTK_WRAP_BOX (toolbox->p->area_wbox),
261 2.0 / 15.0);
262
263 gtk_box_pack_start (GTK_BOX (toolbox->p->vbox), toolbox->p->area_wbox,
264 FALSE, FALSE, 0);
265 gtk_widget_show (toolbox->p->area_wbox);
266
267 /* We need to know when the current device changes, so we can update
268 * the correct tool - to do this we connect to motion events.
269 * We can't just use EXTENSION_EVENTS_CURSOR though, since that
270 * would get us extension events for the mouse pointer, and our
271 * device would change to that and not change back. So we check
272 * manually that all devices have a cursor, before establishing the check.
273 */
274 display = gtk_widget_get_display (GTK_WIDGET (toolbox));
275 for (list = gdk_display_list_devices (display); list; list = list->next)
276 if (! ((GdkDevice *) (list->data))->has_cursor)
277 break;
278
279 if (! list) /* all devices have cursor */
280 {
281 gtk_widget_add_events (GTK_WIDGET (toolbox), GDK_POINTER_MOTION_MASK);
282 gimp_devices_add_widget (toolbox->p->context->gimp, GTK_WIDGET (toolbox));
283 }
284
285 toolbox->p->color_area = toolbox_create_color_area (toolbox,
286 toolbox->p->context);
287 gtk_wrap_box_pack_wrapped (GTK_WRAP_BOX (toolbox->p->area_wbox),
288 toolbox->p->color_area,
289 TRUE, TRUE, FALSE, TRUE, TRUE);
290 if (config->toolbox_color_area)
291 gtk_widget_show (toolbox->p->color_area);
292
293 g_signal_connect_object (config, "notify::toolbox-color-area",
294 G_CALLBACK (toolbox_area_notify),
295 toolbox->p->color_area, 0);
296
297 toolbox->p->foo_area = toolbox_create_foo_area (toolbox, toolbox->p->context);
298 gtk_wrap_box_pack (GTK_WRAP_BOX (toolbox->p->area_wbox), toolbox->p->foo_area,
299 TRUE, TRUE, FALSE, TRUE);
300 if (config->toolbox_foo_area)
301 gtk_widget_show (toolbox->p->foo_area);
302
303 g_signal_connect_object (config, "notify::toolbox-foo-area",
304 G_CALLBACK (toolbox_area_notify),
305 toolbox->p->foo_area, 0);
306
307 toolbox->p->image_area = toolbox_create_image_area (toolbox,
308 toolbox->p->context);
309 gtk_wrap_box_pack (GTK_WRAP_BOX (toolbox->p->area_wbox), toolbox->p->image_area,
310 TRUE, TRUE, FALSE, TRUE);
311 if (config->toolbox_image_area)
312 gtk_widget_show (toolbox->p->image_area);
313
314 g_signal_connect_object (config, "notify::toolbox-image-area",
315 G_CALLBACK (toolbox_area_notify),
316 toolbox->p->image_area, 0);
317
318 gimp_toolbox_dnd_init (GIMP_TOOLBOX (toolbox), toolbox->p->vbox);
319 }
320
321 static void
gimp_toolbox_dispose(GObject * object)322 gimp_toolbox_dispose (GObject *object)
323 {
324 GimpToolbox *toolbox = GIMP_TOOLBOX (object);
325
326 toolbox->p->in_destruction = TRUE;
327
328 g_clear_object (&toolbox->p->context);
329
330 G_OBJECT_CLASS (parent_class)->dispose (object);
331
332 toolbox->p->in_destruction = FALSE;
333 }
334
335 static void
gimp_toolbox_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)336 gimp_toolbox_set_property (GObject *object,
337 guint property_id,
338 const GValue *value,
339 GParamSpec *pspec)
340 {
341 GimpToolbox *toolbox = GIMP_TOOLBOX (object);
342
343 switch (property_id)
344 {
345 case PROP_CONTEXT:
346 toolbox->p->context = g_value_dup_object (value);
347 break;
348
349 default:
350 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
351 break;
352 }
353 }
354
355 static void
gimp_toolbox_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)356 gimp_toolbox_get_property (GObject *object,
357 guint property_id,
358 GValue *value,
359 GParamSpec *pspec)
360 {
361 GimpToolbox *toolbox = GIMP_TOOLBOX (object);
362
363 switch (property_id)
364 {
365 case PROP_CONTEXT:
366 g_value_set_object (value, toolbox->p->context);
367 break;
368
369 default:
370 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
371 break;
372 }
373 }
374
375 static void
gimp_toolbox_size_allocate(GtkWidget * widget,GtkAllocation * allocation)376 gimp_toolbox_size_allocate (GtkWidget *widget,
377 GtkAllocation *allocation)
378 {
379 GimpToolbox *toolbox = GIMP_TOOLBOX (widget);
380 GimpGuiConfig *config;
381 GtkRequisition color_requisition;
382 GtkRequisition foo_requisition;
383 GtkRequisition image_requisition;
384 gint width;
385 gint height;
386 gint n_areas;
387 gint area_rows;
388 gint area_columns;
389
390 GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
391
392 config = GIMP_GUI_CONFIG (toolbox->p->context->gimp->config);
393
394 gtk_widget_size_request (toolbox->p->color_area, &color_requisition);
395 gtk_widget_size_request (toolbox->p->foo_area, &foo_requisition);
396 gtk_widget_size_request (toolbox->p->image_area, &image_requisition);
397
398 width = MAX (color_requisition.width,
399 MAX (foo_requisition.width,
400 image_requisition.width));
401 height = MAX (color_requisition.height,
402 MAX (foo_requisition.height,
403 image_requisition.height));
404
405 n_areas = (config->toolbox_color_area +
406 config->toolbox_foo_area +
407 config->toolbox_image_area);
408
409 area_columns = MAX (1, (allocation->width / width));
410 area_rows = n_areas / area_columns;
411
412 if (n_areas % area_columns)
413 area_rows++;
414
415 if (toolbox->p->area_rows != area_rows ||
416 toolbox->p->area_columns != area_columns)
417 {
418 toolbox->p->area_rows = area_rows;
419 toolbox->p->area_columns = area_columns;
420
421 gtk_widget_set_size_request (toolbox->p->area_wbox, -1,
422 area_rows * height);
423 }
424 }
425
426 static gboolean
gimp_toolbox_button_press_event(GtkWidget * widget,GdkEventButton * event)427 gimp_toolbox_button_press_event (GtkWidget *widget,
428 GdkEventButton *event)
429 {
430 GimpToolbox *toolbox = GIMP_TOOLBOX (widget);
431
432 if (event->type == GDK_BUTTON_PRESS && event->button == 2)
433 {
434 GtkClipboard *clipboard;
435
436 clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_PRIMARY);
437 gtk_clipboard_request_text (clipboard,
438 toolbox_paste_received,
439 g_object_ref (toolbox));
440
441 return TRUE;
442 }
443
444 return FALSE;
445 }
446
447 static void
gimp_toolbox_drag_leave(GtkWidget * widget,GdkDragContext * context,guint time,GimpToolbox * toolbox)448 gimp_toolbox_drag_leave (GtkWidget *widget,
449 GdkDragContext *context,
450 guint time,
451 GimpToolbox *toolbox)
452 {
453 gimp_highlight_widget (widget, FALSE);
454 }
455
456 static gboolean
gimp_toolbox_drag_motion(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time,GimpToolbox * toolbox)457 gimp_toolbox_drag_motion (GtkWidget *widget,
458 GdkDragContext *context,
459 gint x,
460 gint y,
461 guint time,
462 GimpToolbox *toolbox)
463 {
464 gboolean handle;
465
466 if (gimp_paned_box_will_handle_drag (toolbox->p->drag_handler,
467 widget,
468 context,
469 x, y,
470 time))
471 {
472 gdk_drag_status (context, 0, time);
473 gimp_highlight_widget (widget, FALSE);
474
475 return FALSE;
476 }
477
478 handle = (gtk_drag_dest_find_target (widget, context, NULL) != GDK_NONE);
479
480 gdk_drag_status (context, handle ? GDK_ACTION_MOVE : 0, time);
481 gimp_highlight_widget (widget, handle);
482
483 /* Return TRUE so drag_leave() is called */
484 return TRUE;
485 }
486
487 static gboolean
gimp_toolbox_drag_drop(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time,GimpToolbox * toolbox)488 gimp_toolbox_drag_drop (GtkWidget *widget,
489 GdkDragContext *context,
490 gint x,
491 gint y,
492 guint time,
493 GimpToolbox *toolbox)
494 {
495 GdkAtom target;
496 gboolean dropped = FALSE;
497
498 if (gimp_paned_box_will_handle_drag (toolbox->p->drag_handler,
499 widget,
500 context,
501 x, y,
502 time))
503 {
504 return FALSE;
505 }
506
507 target = gtk_drag_dest_find_target (widget, context, NULL);
508
509 if (target != GDK_NONE)
510 {
511 /* The URI handlers etc will handle this */
512 gtk_drag_get_data (widget, context, target, time);
513 dropped = TRUE;
514 }
515
516 gtk_drag_finish (context, dropped, (context->action == GDK_ACTION_MOVE), time);
517
518 return TRUE;
519 }
520
521 static gchar *
gimp_toolbox_get_description(GimpDock * dock,gboolean complete)522 gimp_toolbox_get_description (GimpDock *dock,
523 gboolean complete)
524 {
525 GString *desc = g_string_new (_("Toolbox"));
526 gchar *dock_desc = GIMP_DOCK_CLASS (parent_class)->get_description (dock,
527 complete);
528
529 if (dock_desc && strlen (dock_desc) > 0)
530 {
531 g_string_append (desc, GIMP_DOCK_BOOK_SEPARATOR);
532 g_string_append (desc, dock_desc);
533 }
534
535 g_free (dock_desc);
536
537 return g_string_free (desc, FALSE /*free_segment*/);
538 }
539
540 static void
gimp_toolbox_book_added(GimpDock * dock,GimpDockbook * dockbook)541 gimp_toolbox_book_added (GimpDock *dock,
542 GimpDockbook *dockbook)
543 {
544 if (GIMP_DOCK_CLASS (parent_class)->book_added)
545 GIMP_DOCK_CLASS (parent_class)->book_added (dock, dockbook);
546
547 if (g_list_length (gimp_dock_get_dockbooks (dock)) == 1)
548 {
549 gimp_dock_invalidate_geometry (dock);
550 }
551 }
552
553 static void
gimp_toolbox_book_removed(GimpDock * dock,GimpDockbook * dockbook)554 gimp_toolbox_book_removed (GimpDock *dock,
555 GimpDockbook *dockbook)
556 {
557 GimpToolbox *toolbox = GIMP_TOOLBOX (dock);
558
559 if (GIMP_DOCK_CLASS (parent_class)->book_removed)
560 GIMP_DOCK_CLASS (parent_class)->book_removed (dock, dockbook);
561
562 if (! gimp_dock_get_dockbooks (dock) &&
563 ! toolbox->p->in_destruction)
564 {
565 gimp_dock_invalidate_geometry (dock);
566 }
567 }
568
569 static void
gimp_toolbox_set_host_geometry_hints(GimpDock * dock,GtkWindow * window)570 gimp_toolbox_set_host_geometry_hints (GimpDock *dock,
571 GtkWindow *window)
572 {
573 GimpToolbox *toolbox = GIMP_TOOLBOX (dock);
574 gint button_width;
575 gint button_height;
576
577 if (gimp_tool_palette_get_button_size (GIMP_TOOL_PALETTE (toolbox->p->tool_palette),
578 &button_width, &button_height))
579 {
580 GdkGeometry geometry;
581
582 geometry.min_width = 2 * button_width;
583 geometry.min_height = -1;
584 geometry.base_width = button_width;
585 geometry.base_height = 0;
586 geometry.width_inc = button_width;
587 geometry.height_inc = 1;
588
589 gtk_window_set_geometry_hints (window,
590 NULL,
591 &geometry,
592 GDK_HINT_MIN_SIZE |
593 GDK_HINT_BASE_SIZE |
594 GDK_HINT_RESIZE_INC |
595 GDK_HINT_USER_POS);
596
597 gimp_dialog_factory_set_has_min_size (window, TRUE);
598 }
599 }
600
601 GtkWidget *
gimp_toolbox_new(GimpDialogFactory * factory,GimpContext * context,GimpUIManager * ui_manager)602 gimp_toolbox_new (GimpDialogFactory *factory,
603 GimpContext *context,
604 GimpUIManager *ui_manager)
605 {
606 g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (factory), NULL);
607 g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
608 g_return_val_if_fail (GIMP_IS_UI_MANAGER (ui_manager), NULL);
609
610 return g_object_new (GIMP_TYPE_TOOLBOX,
611 "context", context,
612 NULL);
613 }
614
615 GimpContext *
gimp_toolbox_get_context(GimpToolbox * toolbox)616 gimp_toolbox_get_context (GimpToolbox *toolbox)
617 {
618 g_return_val_if_fail (GIMP_IS_TOOLBOX (toolbox), NULL);
619
620 return toolbox->p->context;
621 }
622
623 void
gimp_toolbox_set_drag_handler(GimpToolbox * toolbox,GimpPanedBox * drag_handler)624 gimp_toolbox_set_drag_handler (GimpToolbox *toolbox,
625 GimpPanedBox *drag_handler)
626 {
627 g_return_if_fail (GIMP_IS_TOOLBOX (toolbox));
628
629 toolbox->p->drag_handler = drag_handler;
630 }
631
632
633 /* private functions */
634
635 static void
gimp_toolbox_size_request_wilber(GtkWidget * widget,GtkRequisition * requisition,GimpToolbox * toolbox)636 gimp_toolbox_size_request_wilber (GtkWidget *widget,
637 GtkRequisition *requisition,
638 GimpToolbox *toolbox)
639 {
640 gint button_width;
641 gint button_height;
642
643 if (gimp_tool_palette_get_button_size (GIMP_TOOL_PALETTE (toolbox->p->tool_palette),
644 &button_width, &button_height))
645 {
646 requisition->width = button_width * PANGO_SCALE_SMALL;
647 requisition->height = button_height * PANGO_SCALE_SMALL;
648 }
649 else
650 {
651 requisition->width = 16;
652 requisition->height = 16;
653 }
654 }
655
656 static gboolean
gimp_toolbox_expose_wilber(GtkWidget * widget,GdkEventExpose * event)657 gimp_toolbox_expose_wilber (GtkWidget *widget,
658 GdkEventExpose *event)
659 {
660 cairo_t *cr;
661
662 cr = gdk_cairo_create (gtk_widget_get_window (widget));
663 gdk_cairo_region (cr, event->region);
664 cairo_clip (cr);
665
666 gimp_cairo_draw_toolbox_wilber (widget, cr);
667
668 cairo_destroy (cr);
669
670 return FALSE;
671 }
672
673 static GtkWidget *
toolbox_create_color_area(GimpToolbox * toolbox,GimpContext * context)674 toolbox_create_color_area (GimpToolbox *toolbox,
675 GimpContext *context)
676 {
677 GtkWidget *alignment;
678 GtkWidget *col_area;
679
680 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
681 gtk_container_set_border_width (GTK_CONTAINER (alignment), 2);
682
683 gimp_help_set_help_data (alignment, NULL, GIMP_HELP_TOOLBOX_COLOR_AREA);
684
685 col_area = gimp_toolbox_color_area_create (toolbox, 40, 38);
686 gtk_container_add (GTK_CONTAINER (alignment), col_area);
687 gtk_widget_show (col_area);
688
689 return alignment;
690 }
691
692 static GtkWidget *
toolbox_create_foo_area(GimpToolbox * toolbox,GimpContext * context)693 toolbox_create_foo_area (GimpToolbox *toolbox,
694 GimpContext *context)
695 {
696 GtkWidget *alignment;
697 GtkWidget *foo_area;
698
699 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
700 gtk_container_set_border_width (GTK_CONTAINER (alignment), 2);
701
702 gimp_help_set_help_data (alignment, NULL, GIMP_HELP_TOOLBOX_INDICATOR_AREA);
703
704 foo_area = gimp_toolbox_indicator_area_create (toolbox);
705 gtk_container_add (GTK_CONTAINER (alignment), foo_area);
706 gtk_widget_show (foo_area);
707
708 return alignment;
709 }
710
711 static GtkWidget *
toolbox_create_image_area(GimpToolbox * toolbox,GimpContext * context)712 toolbox_create_image_area (GimpToolbox *toolbox,
713 GimpContext *context)
714 {
715 GtkWidget *alignment;
716 GtkWidget *image_area;
717
718 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
719 gtk_container_set_border_width (GTK_CONTAINER (alignment), 2);
720
721 gimp_help_set_help_data (alignment, NULL, GIMP_HELP_TOOLBOX_IMAGE_AREA);
722
723 image_area = gimp_toolbox_image_area_create (toolbox, 52, 42);
724 gtk_container_add (GTK_CONTAINER (alignment), image_area);
725 gtk_widget_show (image_area);
726
727 return alignment;
728 }
729
730 static void
toolbox_area_notify(GimpGuiConfig * config,GParamSpec * pspec,GtkWidget * area)731 toolbox_area_notify (GimpGuiConfig *config,
732 GParamSpec *pspec,
733 GtkWidget *area)
734 {
735 GtkWidget *parent = gtk_widget_get_parent (area);
736 gboolean visible;
737
738 if (config->toolbox_color_area ||
739 config->toolbox_foo_area ||
740 config->toolbox_image_area)
741 {
742 GtkRequisition req;
743
744 gtk_widget_show (parent);
745
746 gtk_widget_size_request (area, &req);
747 gtk_widget_set_size_request (parent, req.width, req.height);
748 }
749 else
750 {
751 gtk_widget_hide (parent);
752 gtk_widget_set_size_request (parent, -1, -1);
753 }
754
755 g_object_get (config, pspec->name, &visible, NULL);
756 g_object_set (area, "visible", visible, NULL);
757 }
758
759 static void
toolbox_paste_received(GtkClipboard * clipboard,const gchar * text,gpointer data)760 toolbox_paste_received (GtkClipboard *clipboard,
761 const gchar *text,
762 gpointer data)
763 {
764 GimpToolbox *toolbox = GIMP_TOOLBOX (data);
765 GimpContext *context = toolbox->p->context;
766
767 if (text)
768 {
769 const gchar *newline = strchr (text, '\n');
770 gchar *copy;
771 GFile *file = NULL;
772
773 if (newline)
774 copy = g_strndup (text, newline - text);
775 else
776 copy = g_strdup (text);
777
778 g_strstrip (copy);
779
780 if (strlen (copy))
781 file = g_file_new_for_commandline_arg (copy);
782
783 g_free (copy);
784
785 if (file)
786 {
787 GtkWidget *widget = GTK_WIDGET (toolbox);
788 GimpImage *image;
789 GimpPDBStatusType status;
790 GError *error = NULL;
791
792 image = file_open_with_display (context->gimp, context, NULL,
793 file, FALSE,
794 G_OBJECT (gtk_widget_get_screen (widget)),
795 gimp_widget_get_monitor (widget),
796 &status, &error);
797
798 if (! image && status != GIMP_PDB_CANCEL)
799 {
800 gimp_message (context->gimp, NULL, GIMP_MESSAGE_ERROR,
801 _("Opening '%s' failed:\n\n%s"),
802 gimp_file_get_utf8_name (file), error->message);
803 g_clear_error (&error);
804 }
805
806 g_object_unref (file);
807 }
808 }
809
810 g_object_unref (context);
811 }
812