1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimptoolwidgetgroup.c
5 * Copyright (C) 2018 Ell
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25
26 #include "display-types.h"
27
28 #include "core/gimpcontainer.h"
29 #include "core/gimplist.h"
30
31 #include "gimpcanvasgroup.h"
32 #include "gimpdisplayshell.h"
33 #include "gimptoolwidgetgroup.h"
34
35
36 struct _GimpToolWidgetGroupPrivate
37 {
38 GimpContainer *children;
39
40 GimpToolWidget *focus_widget;
41 GimpToolWidget *hover_widget;
42
43 gboolean auto_raise;
44 };
45
46
47 /* local function prototypes */
48
49 static void gimp_tool_widget_group_finalize (GObject *object);
50
51 static void gimp_tool_widget_group_focus_changed (GimpToolWidget *widget);
52 static gint gimp_tool_widget_group_button_press (GimpToolWidget *widget,
53 const GimpCoords *coords,
54 guint32 time,
55 GdkModifierType state,
56 GimpButtonPressType press_type);
57 static void gimp_tool_widget_group_button_release (GimpToolWidget *widget,
58 const GimpCoords *coords,
59 guint32 time,
60 GdkModifierType state,
61 GimpButtonReleaseType release_type);
62 static void gimp_tool_widget_group_motion (GimpToolWidget *widget,
63 const GimpCoords *coords,
64 guint32 time,
65 GdkModifierType state);
66 static GimpHit gimp_tool_widget_group_hit (GimpToolWidget *widget,
67 const GimpCoords *coords,
68 GdkModifierType state,
69 gboolean proximity);
70 static void gimp_tool_widget_group_hover (GimpToolWidget *widget,
71 const GimpCoords *coords,
72 GdkModifierType state,
73 gboolean proximity);
74 static void gimp_tool_widget_group_leave_notify (GimpToolWidget *widget);
75 static gboolean gimp_tool_widget_group_key_press (GimpToolWidget *widget,
76 GdkEventKey *kevent);
77 static gboolean gimp_tool_widget_group_key_release (GimpToolWidget *widget,
78 GdkEventKey *kevent);
79 static void gimp_tool_widget_group_motion_modifier (GimpToolWidget *widget,
80 GdkModifierType key,
81 gboolean press,
82 GdkModifierType state);
83 static void gimp_tool_widget_group_hover_modifier (GimpToolWidget *widget,
84 GdkModifierType key,
85 gboolean press,
86 GdkModifierType state);
87 static gboolean gimp_tool_widget_group_get_cursor (GimpToolWidget *widget,
88 const GimpCoords *coords,
89 GdkModifierType state,
90 GimpCursorType *cursor,
91 GimpToolCursorType *tool_cursor,
92 GimpCursorModifier *modifier);
93
94 static void gimp_tool_widget_group_children_add (GimpContainer *container,
95 GimpToolWidget *child,
96 GimpToolWidgetGroup *group);
97 static void gimp_tool_widget_group_children_remove (GimpContainer *container,
98 GimpToolWidget *child,
99 GimpToolWidgetGroup *group);
100 static void gimp_tool_widget_group_children_reorder (GimpContainer *container,
101 GimpToolWidget *child,
102 gint new_index,
103 GimpToolWidgetGroup *group);
104
105 static void gimp_tool_widget_group_child_changed (GimpToolWidget *child,
106 GimpToolWidgetGroup *group);
107 static void gimp_tool_widget_group_child_response (GimpToolWidget *child,
108 gint response_id,
109 GimpToolWidgetGroup *group);
110 static void gimp_tool_widget_group_child_snap_offsets (GimpToolWidget *child,
111 gint offset_x,
112 gint offset_y,
113 gint width,
114 gint height,
115 GimpToolWidgetGroup *group);
116 static void gimp_tool_widget_group_child_status (GimpToolWidget *child,
117 const gchar *status,
118 GimpToolWidgetGroup *group);
119 static void gimp_tool_widget_group_child_status_coords (GimpToolWidget *child,
120 const gchar *title,
121 gdouble x,
122 const gchar *separator,
123 gdouble y,
124 const gchar *help,
125 GimpToolWidgetGroup *group);
126 static void gimp_tool_widget_group_child_message (GimpToolWidget *child,
127 const gchar *message,
128 GimpToolWidgetGroup *group);
129 static void gimp_tool_widget_group_child_focus_changed (GimpToolWidget *child,
130 GimpToolWidgetGroup *group);
131
132 static GimpToolWidget * gimp_tool_widget_group_get_hover_widget (GimpToolWidgetGroup *group,
133 const GimpCoords *coords,
134 GdkModifierType state,
135 gboolean proximity,
136 GimpHit *hit);
137
138
G_DEFINE_TYPE_WITH_PRIVATE(GimpToolWidgetGroup,gimp_tool_widget_group,GIMP_TYPE_TOOL_WIDGET)139 G_DEFINE_TYPE_WITH_PRIVATE (GimpToolWidgetGroup, gimp_tool_widget_group,
140 GIMP_TYPE_TOOL_WIDGET)
141
142 #define parent_class gimp_tool_widget_group_parent_class
143
144
145 /* priv functions */
146
147
148 static void
149 gimp_tool_widget_group_class_init (GimpToolWidgetGroupClass *klass)
150 {
151 GObjectClass *object_class = G_OBJECT_CLASS (klass);
152 GimpToolWidgetClass *widget_class = GIMP_TOOL_WIDGET_CLASS (klass);
153
154 object_class->finalize = gimp_tool_widget_group_finalize;
155
156 widget_class->focus_changed = gimp_tool_widget_group_focus_changed;
157 widget_class->button_press = gimp_tool_widget_group_button_press;
158 widget_class->button_release = gimp_tool_widget_group_button_release;
159 widget_class->motion = gimp_tool_widget_group_motion;
160 widget_class->hit = gimp_tool_widget_group_hit;
161 widget_class->hover = gimp_tool_widget_group_hover;
162 widget_class->leave_notify = gimp_tool_widget_group_leave_notify;
163 widget_class->key_press = gimp_tool_widget_group_key_press;
164 widget_class->key_release = gimp_tool_widget_group_key_release;
165 widget_class->motion_modifier = gimp_tool_widget_group_motion_modifier;
166 widget_class->hover_modifier = gimp_tool_widget_group_hover_modifier;
167 widget_class->get_cursor = gimp_tool_widget_group_get_cursor;
168 }
169
170 static void
gimp_tool_widget_group_init(GimpToolWidgetGroup * group)171 gimp_tool_widget_group_init (GimpToolWidgetGroup *group)
172 {
173 GimpToolWidgetGroupPrivate *priv;
174
175 priv = group->priv = gimp_tool_widget_group_get_instance_private (group);
176
177 priv->children = g_object_new (GIMP_TYPE_LIST,
178 "children-type", GIMP_TYPE_TOOL_WIDGET,
179 "append", TRUE,
180 NULL);
181
182 g_signal_connect (priv->children, "add",
183 G_CALLBACK (gimp_tool_widget_group_children_add),
184 group);
185 g_signal_connect (priv->children, "remove",
186 G_CALLBACK (gimp_tool_widget_group_children_remove),
187 group);
188 g_signal_connect (priv->children, "reorder",
189 G_CALLBACK (gimp_tool_widget_group_children_reorder),
190 group);
191
192 gimp_container_add_handler (priv->children, "changed",
193 G_CALLBACK (gimp_tool_widget_group_child_changed),
194 group);
195 gimp_container_add_handler (priv->children, "response",
196 G_CALLBACK (gimp_tool_widget_group_child_response),
197 group);
198 gimp_container_add_handler (priv->children, "snap-offsets",
199 G_CALLBACK (gimp_tool_widget_group_child_snap_offsets),
200 group);
201 gimp_container_add_handler (priv->children, "status",
202 G_CALLBACK (gimp_tool_widget_group_child_status),
203 group);
204 gimp_container_add_handler (priv->children, "status-coords",
205 G_CALLBACK (gimp_tool_widget_group_child_status_coords),
206 group);
207 gimp_container_add_handler (priv->children, "message",
208 G_CALLBACK (gimp_tool_widget_group_child_message),
209 group);
210 gimp_container_add_handler (priv->children, "focus-changed",
211 G_CALLBACK (gimp_tool_widget_group_child_focus_changed),
212 group);
213 }
214
215 static void
gimp_tool_widget_group_finalize(GObject * object)216 gimp_tool_widget_group_finalize (GObject *object)
217 {
218 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (object);
219 GimpToolWidgetGroupPrivate *priv = group->priv;
220
221 g_clear_object (&priv->children);
222
223 G_OBJECT_CLASS (parent_class)->finalize (object);
224 }
225
226 static gint
gimp_tool_widget_group_button_press(GimpToolWidget * widget,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpButtonPressType press_type)227 gimp_tool_widget_group_button_press (GimpToolWidget *widget,
228 const GimpCoords *coords,
229 guint32 time,
230 GdkModifierType state,
231 GimpButtonPressType press_type)
232 {
233 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
234 GimpToolWidgetGroupPrivate *priv = group->priv;
235
236 gimp_tool_widget_group_hover (widget, coords, state, TRUE);
237
238 if (priv->focus_widget != priv->hover_widget)
239 {
240 if (priv->hover_widget)
241 gimp_tool_widget_set_focus (priv->hover_widget, TRUE);
242 else if (priv->focus_widget)
243 gimp_tool_widget_set_focus (priv->focus_widget, FALSE);
244 }
245
246 if (priv->hover_widget)
247 {
248 if (priv->auto_raise)
249 {
250 gimp_container_reorder (priv->children,
251 GIMP_OBJECT (priv->hover_widget), -1);
252 }
253
254 return gimp_tool_widget_button_press (priv->hover_widget,
255 coords, time, state, press_type);
256 }
257
258 return FALSE;
259 }
260
261 static void
gimp_tool_widget_group_focus_changed(GimpToolWidget * widget)262 gimp_tool_widget_group_focus_changed (GimpToolWidget *widget)
263 {
264 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
265 GimpToolWidgetGroupPrivate *priv = group->priv;
266
267 if (priv->focus_widget)
268 {
269 GimpToolWidget *focus_widget = priv->focus_widget;
270
271 gimp_tool_widget_set_focus (priv->focus_widget,
272 gimp_tool_widget_get_focus (widget));
273
274 priv->focus_widget = focus_widget;
275 }
276 }
277
278 static void
gimp_tool_widget_group_button_release(GimpToolWidget * widget,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpButtonReleaseType release_type)279 gimp_tool_widget_group_button_release (GimpToolWidget *widget,
280 const GimpCoords *coords,
281 guint32 time,
282 GdkModifierType state,
283 GimpButtonReleaseType release_type)
284 {
285 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
286 GimpToolWidgetGroupPrivate *priv = group->priv;
287
288 if (priv->hover_widget)
289 {
290 gimp_tool_widget_button_release (priv->hover_widget,
291 coords, time, state, release_type);
292 }
293 }
294
295 static void
gimp_tool_widget_group_motion(GimpToolWidget * widget,const GimpCoords * coords,guint32 time,GdkModifierType state)296 gimp_tool_widget_group_motion (GimpToolWidget *widget,
297 const GimpCoords *coords,
298 guint32 time,
299 GdkModifierType state)
300 {
301 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
302 GimpToolWidgetGroupPrivate *priv = group->priv;
303
304 if (priv->hover_widget)
305 gimp_tool_widget_motion (priv->hover_widget, coords, time, state);
306 }
307
308 static GimpHit
gimp_tool_widget_group_hit(GimpToolWidget * widget,const GimpCoords * coords,GdkModifierType state,gboolean proximity)309 gimp_tool_widget_group_hit (GimpToolWidget *widget,
310 const GimpCoords *coords,
311 GdkModifierType state,
312 gboolean proximity)
313 {
314 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
315 GimpHit hit;
316
317 gimp_tool_widget_group_get_hover_widget (group,
318 coords, state, proximity,
319 &hit);
320
321 return hit;
322 }
323
324 static void
gimp_tool_widget_group_hover(GimpToolWidget * widget,const GimpCoords * coords,GdkModifierType state,gboolean proximity)325 gimp_tool_widget_group_hover (GimpToolWidget *widget,
326 const GimpCoords *coords,
327 GdkModifierType state,
328 gboolean proximity)
329 {
330 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
331 GimpToolWidgetGroupPrivate *priv = group->priv;
332 GimpToolWidget *hover_widget;
333
334 hover_widget =
335 gimp_tool_widget_group_get_hover_widget (group,
336 coords, state, proximity,
337 NULL);
338
339 if (priv->hover_widget && priv->hover_widget != hover_widget)
340 gimp_tool_widget_leave_notify (priv->hover_widget);
341
342 priv->hover_widget = hover_widget;
343
344 if (priv->hover_widget)
345 gimp_tool_widget_hover (priv->hover_widget, coords, state, proximity);
346 }
347
348 static void
gimp_tool_widget_group_leave_notify(GimpToolWidget * widget)349 gimp_tool_widget_group_leave_notify (GimpToolWidget *widget)
350 {
351 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
352 GimpToolWidgetGroupPrivate *priv = group->priv;
353
354 if (priv->hover_widget)
355 {
356 gimp_tool_widget_leave_notify (priv->hover_widget);
357
358 priv->hover_widget = NULL;
359 }
360
361 GIMP_TOOL_WIDGET_CLASS (parent_class)->leave_notify (widget);
362 }
363
364 static gboolean
gimp_tool_widget_group_key_press(GimpToolWidget * widget,GdkEventKey * kevent)365 gimp_tool_widget_group_key_press (GimpToolWidget *widget,
366 GdkEventKey *kevent)
367 {
368 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
369 GimpToolWidgetGroupPrivate *priv = group->priv;
370
371 if (priv->focus_widget)
372 return gimp_tool_widget_key_press (priv->focus_widget, kevent);
373
374 return GIMP_TOOL_WIDGET_CLASS (parent_class)->key_press (widget, kevent);
375 }
376
377 static gboolean
gimp_tool_widget_group_key_release(GimpToolWidget * widget,GdkEventKey * kevent)378 gimp_tool_widget_group_key_release (GimpToolWidget *widget,
379 GdkEventKey *kevent)
380 {
381 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
382 GimpToolWidgetGroupPrivate *priv = group->priv;
383
384 if (priv->focus_widget)
385 return gimp_tool_widget_key_release (priv->focus_widget, kevent);
386
387 return FALSE;
388 }
389
390 static void
gimp_tool_widget_group_motion_modifier(GimpToolWidget * widget,GdkModifierType key,gboolean press,GdkModifierType state)391 gimp_tool_widget_group_motion_modifier (GimpToolWidget *widget,
392 GdkModifierType key,
393 gboolean press,
394 GdkModifierType state)
395 {
396 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
397 GimpToolWidgetGroupPrivate *priv = group->priv;
398
399 if (priv->hover_widget)
400 gimp_tool_widget_motion_modifier (priv->hover_widget, key, press, state);
401 }
402
403 static void
gimp_tool_widget_group_hover_modifier(GimpToolWidget * widget,GdkModifierType key,gboolean press,GdkModifierType state)404 gimp_tool_widget_group_hover_modifier (GimpToolWidget *widget,
405 GdkModifierType key,
406 gboolean press,
407 GdkModifierType state)
408 {
409 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
410 GimpToolWidgetGroupPrivate *priv = group->priv;
411 GList *iter;
412
413 for (iter = g_queue_peek_head_link (GIMP_LIST (priv->children)->queue);
414 iter;
415 iter = g_list_next (iter))
416 {
417 gimp_tool_widget_hover_modifier (iter->data, key, press, state);
418 }
419 }
420
421 static gboolean
gimp_tool_widget_group_get_cursor(GimpToolWidget * widget,const GimpCoords * coords,GdkModifierType state,GimpCursorType * cursor,GimpToolCursorType * tool_cursor,GimpCursorModifier * modifier)422 gimp_tool_widget_group_get_cursor (GimpToolWidget *widget,
423 const GimpCoords *coords,
424 GdkModifierType state,
425 GimpCursorType *cursor,
426 GimpToolCursorType *tool_cursor,
427 GimpCursorModifier *modifier)
428 {
429 GimpToolWidgetGroup *group = GIMP_TOOL_WIDGET_GROUP (widget);
430 GimpToolWidgetGroupPrivate *priv = group->priv;
431
432 if (priv->hover_widget)
433 {
434 return gimp_tool_widget_get_cursor (priv->hover_widget,
435 coords, state,
436 cursor, tool_cursor, modifier);
437 }
438
439 return FALSE;
440 }
441
442 static void
gimp_tool_widget_group_children_add(GimpContainer * container,GimpToolWidget * child,GimpToolWidgetGroup * group)443 gimp_tool_widget_group_children_add (GimpContainer *container,
444 GimpToolWidget *child,
445 GimpToolWidgetGroup *group)
446 {
447 GimpToolWidgetGroupPrivate *priv = group->priv;
448 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
449 GimpCanvasGroup *canvas_group;
450
451 canvas_group = GIMP_CANVAS_GROUP (gimp_tool_widget_get_item (widget));
452
453 gimp_canvas_group_add_item (canvas_group,
454 gimp_tool_widget_get_item (child));
455
456 if (gimp_tool_widget_get_focus (child) && priv->focus_widget)
457 {
458 gimp_tool_widget_set_focus (priv->focus_widget, FALSE);
459
460 priv->focus_widget = NULL;
461 }
462
463 if (! priv->focus_widget)
464 {
465 priv->focus_widget = child;
466
467 gimp_tool_widget_set_focus (child, gimp_tool_widget_get_focus (widget));
468 }
469
470 gimp_tool_widget_changed (widget);
471 }
472
473 static void
gimp_tool_widget_group_children_remove(GimpContainer * container,GimpToolWidget * child,GimpToolWidgetGroup * group)474 gimp_tool_widget_group_children_remove (GimpContainer *container,
475 GimpToolWidget *child,
476 GimpToolWidgetGroup *group)
477 {
478 GimpToolWidgetGroupPrivate *priv = group->priv;
479 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
480 GimpCanvasGroup *canvas_group;
481
482 canvas_group = GIMP_CANVAS_GROUP (gimp_tool_widget_get_item (widget));
483
484 if (priv->focus_widget == child)
485 {
486 gimp_tool_widget_set_focus (child, FALSE);
487
488 priv->focus_widget = NULL;
489 }
490
491 if (priv->hover_widget == child)
492 {
493 gimp_tool_widget_leave_notify (child);
494
495 priv->hover_widget = NULL;
496 }
497
498 if (! priv->focus_widget)
499 {
500 priv->focus_widget =
501 GIMP_TOOL_WIDGET (gimp_container_get_last_child (container));
502
503 if (priv->focus_widget)
504 gimp_tool_widget_set_focus (priv->focus_widget, TRUE);
505 }
506
507 gimp_canvas_group_remove_item (canvas_group,
508 gimp_tool_widget_get_item (child));
509
510 gimp_tool_widget_changed (widget);
511 }
512
513 static void
gimp_tool_widget_group_children_reorder(GimpContainer * container,GimpToolWidget * child,gint new_index,GimpToolWidgetGroup * group)514 gimp_tool_widget_group_children_reorder (GimpContainer *container,
515 GimpToolWidget *child,
516 gint new_index,
517 GimpToolWidgetGroup *group)
518 {
519 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
520 GimpCanvasGroup *canvas_group;
521 GList *iter;
522
523 canvas_group = GIMP_CANVAS_GROUP (gimp_tool_widget_get_item (widget));
524
525 for (iter = g_queue_peek_head_link (GIMP_LIST (container)->queue);
526 iter;
527 iter = g_list_next (iter))
528 {
529 GimpCanvasItem *item = gimp_tool_widget_get_item (iter->data);
530
531 gimp_canvas_group_remove_item (canvas_group, item);
532 gimp_canvas_group_add_item (canvas_group, item);
533 }
534
535 gimp_tool_widget_changed (widget);
536 }
537
538 static void
gimp_tool_widget_group_child_changed(GimpToolWidget * child,GimpToolWidgetGroup * group)539 gimp_tool_widget_group_child_changed (GimpToolWidget *child,
540 GimpToolWidgetGroup *group)
541 {
542 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
543
544 gimp_tool_widget_changed (widget);
545 }
546
547 static void
gimp_tool_widget_group_child_response(GimpToolWidget * child,gint response_id,GimpToolWidgetGroup * group)548 gimp_tool_widget_group_child_response (GimpToolWidget *child,
549 gint response_id,
550 GimpToolWidgetGroup *group)
551 {
552 GimpToolWidgetGroupPrivate *priv = group->priv;
553 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
554
555 if (priv->focus_widget == child)
556 gimp_tool_widget_response (widget, response_id);
557 }
558
559 static void
gimp_tool_widget_group_child_snap_offsets(GimpToolWidget * child,gint offset_x,gint offset_y,gint width,gint height,GimpToolWidgetGroup * group)560 gimp_tool_widget_group_child_snap_offsets (GimpToolWidget *child,
561 gint offset_x,
562 gint offset_y,
563 gint width,
564 gint height,
565 GimpToolWidgetGroup *group)
566 {
567 GimpToolWidgetGroupPrivate *priv = group->priv;
568 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
569
570 if (priv->hover_widget == child)
571 {
572 gimp_tool_widget_set_snap_offsets (widget,
573 offset_x, offset_y, width, height);
574 }
575 }
576
577 static void
gimp_tool_widget_group_child_status(GimpToolWidget * child,const gchar * status,GimpToolWidgetGroup * group)578 gimp_tool_widget_group_child_status (GimpToolWidget *child,
579 const gchar *status,
580 GimpToolWidgetGroup *group)
581 {
582 GimpToolWidgetGroupPrivate *priv = group->priv;
583 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
584
585 if (priv->hover_widget == child)
586 gimp_tool_widget_set_status (widget, status);
587 }
588
589 static void
gimp_tool_widget_group_child_status_coords(GimpToolWidget * child,const gchar * title,gdouble x,const gchar * separator,gdouble y,const gchar * help,GimpToolWidgetGroup * group)590 gimp_tool_widget_group_child_status_coords (GimpToolWidget *child,
591 const gchar *title,
592 gdouble x,
593 const gchar *separator,
594 gdouble y,
595 const gchar *help,
596 GimpToolWidgetGroup *group)
597 {
598 GimpToolWidgetGroupPrivate *priv = group->priv;
599 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
600
601 if (priv->hover_widget == child)
602 gimp_tool_widget_set_status_coords (widget, title, x, separator, y, help);
603 }
604
605 static void
gimp_tool_widget_group_child_message(GimpToolWidget * child,const gchar * message,GimpToolWidgetGroup * group)606 gimp_tool_widget_group_child_message (GimpToolWidget *child,
607 const gchar *message,
608 GimpToolWidgetGroup *group)
609 {
610 GimpToolWidgetGroupPrivate *priv = group->priv;
611 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
612
613 if (priv->focus_widget == child)
614 gimp_tool_widget_message_literal (widget, message);
615 }
616
617 static void
gimp_tool_widget_group_child_focus_changed(GimpToolWidget * child,GimpToolWidgetGroup * group)618 gimp_tool_widget_group_child_focus_changed (GimpToolWidget *child,
619 GimpToolWidgetGroup *group)
620 {
621 GimpToolWidgetGroupPrivate *priv = group->priv;
622 GimpToolWidget *widget = GIMP_TOOL_WIDGET (group);
623
624 if (gimp_tool_widget_get_focus (child))
625 {
626 if (priv->focus_widget && priv->focus_widget != child)
627 gimp_tool_widget_set_focus (priv->focus_widget, FALSE);
628
629 priv->focus_widget = child;
630
631 gimp_tool_widget_set_focus (widget, TRUE);
632 }
633 else
634 {
635 if (priv->focus_widget == child)
636 priv->focus_widget = NULL;
637 }
638 }
639
640 static GimpToolWidget *
gimp_tool_widget_group_get_hover_widget(GimpToolWidgetGroup * group,const GimpCoords * coords,GdkModifierType state,gboolean proximity,GimpHit * hit)641 gimp_tool_widget_group_get_hover_widget (GimpToolWidgetGroup *group,
642 const GimpCoords *coords,
643 GdkModifierType state,
644 gboolean proximity,
645 GimpHit *hit)
646 {
647 GimpToolWidgetGroupPrivate *priv = group->priv;
648 GimpToolWidget *indirect_child = NULL;
649 gboolean indirect = FALSE;
650 GList *iter;
651
652 for (iter = g_queue_peek_tail_link (GIMP_LIST (priv->children)->queue);
653 iter;
654 iter = g_list_previous (iter))
655 {
656 GimpToolWidget *child = iter->data;
657
658 switch (gimp_tool_widget_hit (child, coords, state, proximity))
659 {
660 case GIMP_HIT_DIRECT:
661 if (hit) *hit = GIMP_HIT_DIRECT;
662
663 return child;
664
665 case GIMP_HIT_INDIRECT:
666 if (! indirect || child == priv->focus_widget)
667 indirect_child = child;
668 else if (indirect_child != priv->focus_widget)
669 indirect_child = NULL;
670
671 indirect = TRUE;
672
673 break;
674
675 case GIMP_HIT_NONE:
676 break;
677 }
678 }
679
680 if (hit) *hit = indirect_child ? GIMP_HIT_INDIRECT : GIMP_HIT_NONE;
681
682 return indirect_child;
683 }
684
685
686 /* public functions */
687
688
689 GimpToolWidget *
gimp_tool_widget_group_new(GimpDisplayShell * shell)690 gimp_tool_widget_group_new (GimpDisplayShell *shell)
691 {
692 g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
693
694 return g_object_new (GIMP_TYPE_TOOL_WIDGET_GROUP,
695 "shell", shell,
696 NULL);
697 }
698
699 GimpContainer *
gimp_tool_widget_group_get_children(GimpToolWidgetGroup * group)700 gimp_tool_widget_group_get_children (GimpToolWidgetGroup *group)
701 {
702 g_return_val_if_fail (GIMP_IS_TOOL_WIDGET_GROUP (group), NULL);
703
704 return group->priv->children;
705 }
706
707 GimpToolWidget *
gimp_tool_widget_group_get_focus_widget(GimpToolWidgetGroup * group)708 gimp_tool_widget_group_get_focus_widget (GimpToolWidgetGroup *group)
709 {
710 g_return_val_if_fail (GIMP_IS_TOOL_WIDGET_GROUP (group), NULL);
711
712 return group->priv->focus_widget;
713 }
714
715 void
gimp_tool_widget_group_set_auto_raise(GimpToolWidgetGroup * group,gboolean auto_raise)716 gimp_tool_widget_group_set_auto_raise (GimpToolWidgetGroup *group,
717 gboolean auto_raise)
718 {
719 g_return_if_fail (GIMP_IS_TOOL_WIDGET_GROUP (group));
720
721 group->priv->auto_raise = auto_raise;
722 }
723
724 gboolean
gimp_tool_widget_group_get_auto_raise(GimpToolWidgetGroup * group)725 gimp_tool_widget_group_get_auto_raise (GimpToolWidgetGroup *group)
726 {
727 g_return_val_if_fail (GIMP_IS_TOOL_WIDGET_GROUP (group), FALSE);
728
729 return group->priv->auto_raise;
730 }
731
732