1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2
3 /*
4 * GImageView
5 * Copyright (C) 2001 Takuro Ashie
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 2 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, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * $Id: gimv_paned.c,v 1.2 2003/06/13 09:43:32 makeinu Exp $
22 */
23
24 /*
25 * These codes are taken from gThumb.
26 * gThumb code Copyright (C) 2001 The Free Software Foundation, Inc.
27 * gThumb author: Paolo Bacchilega
28 */
29
30 #include "gimv_paned.h"
31
32 #ifndef USE_NORMAL_PANED
33
34 #ifndef GTK_OBJECT_GET_CLASS
35 #define GTK_OBJECT_GET_CLASS(object) \
36 GTK_OBJECT (object)->klass
37 #endif
38
39 char gray50_bits[] = {0x02, 0x01};
40
41 enum {
42 ARG_0,
43 ARG_GUTTER_SIZE
44 };
45
46 static void gimv_paned_class_init (GimvPanedClass *klass);
47 static void gimv_paned_init (GimvPaned *paned);
48 static void gimv_paned_set_arg (GtkObject *object,
49 GtkArg *arg,
50 guint arg_id);
51 static void gimv_paned_get_arg (GtkObject *object,
52 GtkArg *arg,
53 guint arg_id);
54 static void gimv_paned_realize (GtkWidget *widget);
55 static void gimv_paned_map (GtkWidget *widget);
56 static void gimv_paned_unmap (GtkWidget *widget);
57 static void gimv_paned_unrealize (GtkWidget *widget);
58 static gint gimv_paned_expose (GtkWidget *widget,
59 GdkEventExpose *event);
60 static void gimv_paned_add (GtkContainer *container,
61 GtkWidget *widget);
62 static void gimv_paned_remove (GtkContainer *container,
63 GtkWidget *widget);
64 static void gimv_paned_forall (GtkContainer *container,
65 gboolean include_internals,
66 GtkCallback callback,
67 gpointer callback_data);
68 static GtkType gimv_paned_child_type (GtkContainer *container);
69 static gint gimv_paned_motion (GtkWidget *widget,
70 GdkEventMotion *event);
71
72
73 static GtkContainerClass *parent_class = NULL;
74
75
76 GtkType
gimv_paned_get_type(void)77 gimv_paned_get_type (void)
78 {
79 static GtkType paned_type = 0;
80
81 if (!paned_type) {
82 static const GtkTypeInfo paned_info = {
83 "GimvPaned",
84 sizeof (GimvPaned),
85 sizeof (GimvPanedClass),
86 (GtkClassInitFunc) gimv_paned_class_init,
87 (GtkObjectInitFunc) gimv_paned_init,
88 /* reserved_1 */ NULL,
89 /* reserved_2 */ NULL,
90 (GtkClassInitFunc) NULL,
91 };
92 paned_type = gtk_type_unique (GTK_TYPE_CONTAINER, &paned_info);
93 }
94
95 return paned_type;
96 }
97
98
99 static void
gimv_paned_virtual_xor_line(GimvPaned * paned)100 gimv_paned_virtual_xor_line (GimvPaned *paned)
101 {
102 g_warning ("gimv_paned_virtual_xor_line reached !");
103 }
104
105
106 static void
gimv_paned_class_init(GimvPanedClass * class)107 gimv_paned_class_init (GimvPanedClass *class)
108 {
109 GtkObjectClass *object_class;
110 GtkWidgetClass *widget_class;
111 GtkContainerClass *container_class;
112
113 object_class = (GtkObjectClass*) class;
114 widget_class = (GtkWidgetClass*) class;
115 container_class = (GtkContainerClass*) class;
116
117 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
118
119 object_class->set_arg = gimv_paned_set_arg;
120 object_class->get_arg = gimv_paned_get_arg;
121
122 widget_class->realize = gimv_paned_realize;
123 widget_class->map = gimv_paned_map;
124 widget_class->unmap = gimv_paned_unmap;
125 widget_class->unrealize = gimv_paned_unrealize;
126 widget_class->expose_event = gimv_paned_expose;
127 widget_class->motion_notify_event = gimv_paned_motion;
128
129 container_class->add = gimv_paned_add;
130 container_class->remove = gimv_paned_remove;
131 container_class->forall = gimv_paned_forall;
132 container_class->child_type = gimv_paned_child_type;
133
134 class->xor_line = gimv_paned_virtual_xor_line;
135
136 gtk_object_add_arg_type ("GimvPaned::gutter_size", GTK_TYPE_UINT,
137 GTK_ARG_READWRITE, ARG_GUTTER_SIZE);
138 }
139
140
141 static GtkType
gimv_paned_child_type(GtkContainer * container)142 gimv_paned_child_type (GtkContainer *container)
143 {
144 if (!GIMV_PANED (container)->child1 || !GIMV_PANED (container)->child2)
145 return GTK_TYPE_WIDGET;
146 else
147 return GTK_TYPE_NONE;
148 }
149
150
151 static void
gimv_paned_init(GimvPaned * paned)152 gimv_paned_init (GimvPaned *paned)
153 {
154 GTK_WIDGET_UNSET_FLAGS (paned, GTK_NO_WINDOW);
155
156 paned->child1 = NULL;
157 paned->child2 = NULL;
158 paned->handle = NULL;
159 paned->xor_gc = NULL;
160
161 paned->gutter_size = 6;
162 paned->position_set = FALSE;
163 paned->last_allocation = -1;
164 paned->in_drag = FALSE;
165
166 paned->handle_xpos = -1;
167 paned->handle_ypos = -1;
168
169 paned->horizontal = TRUE;
170
171 paned->child1_minsize = 0;
172 paned->child2_minsize = 0;
173 paned->child1_use_minsize = FALSE;
174 paned->child2_use_minsize = FALSE;
175
176 paned->child_hidden = 0;
177 }
178
179
180 static void
gimv_paned_set_arg(GtkObject * object,GtkArg * arg,guint arg_id)181 gimv_paned_set_arg (GtkObject *object,
182 GtkArg *arg,
183 guint arg_id)
184 {
185 GimvPaned *paned = GIMV_PANED (object);
186
187 switch (arg_id) {
188 case ARG_GUTTER_SIZE:
189 gimv_paned_set_gutter_size (paned, GTK_VALUE_UINT (*arg));
190 break;
191 }
192 }
193
194
195 static void
gimv_paned_get_arg(GtkObject * object,GtkArg * arg,guint arg_id)196 gimv_paned_get_arg (GtkObject *object,
197 GtkArg *arg,
198 guint arg_id)
199 {
200 GimvPaned *paned = GIMV_PANED (object);
201
202 switch (arg_id) {
203 case ARG_GUTTER_SIZE:
204 GTK_VALUE_UINT (*arg) = paned->gutter_size;
205 break;
206 default:
207 arg->type = GTK_TYPE_INVALID;
208 break;
209 }
210 }
211
212
213 static void
gimv_paned_realize(GtkWidget * widget)214 gimv_paned_realize (GtkWidget *widget)
215 {
216 GimvPaned *paned;
217 GdkWindowAttr attributes;
218 gint attributes_mask;
219
220 g_return_if_fail (widget != NULL);
221 g_return_if_fail (GIMV_IS_PANED (widget));
222
223 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
224 paned = GIMV_PANED (widget);
225
226 attributes.x = widget->allocation.x;
227 attributes.y = widget->allocation.y;
228 attributes.width = widget->allocation.width;
229 attributes.height = widget->allocation.height;
230 attributes.window_type = GDK_WINDOW_CHILD;
231 attributes.wclass = GDK_INPUT_OUTPUT;
232 attributes.visual = gtk_widget_get_visual (widget);
233 attributes.colormap = gtk_widget_get_colormap (widget);
234 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
235 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
236
237 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
238 &attributes, attributes_mask);
239 gdk_window_set_user_data (widget->window, paned);
240
241 attributes.x = paned->handle_xpos;
242 attributes.y = paned->handle_ypos;
243 if (paned->horizontal) {
244 attributes.width = paned->gutter_size;
245 attributes.height = widget->allocation.height;
246 attributes.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
247 } else {
248 attributes.width = widget->allocation.width;
249 attributes.height = paned->gutter_size;
250 attributes.cursor = gdk_cursor_new (GDK_SB_V_DOUBLE_ARROW);
251 }
252 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
253 GDK_BUTTON_RELEASE_MASK |
254 GDK_POINTER_MOTION_MASK |
255 GDK_POINTER_MOTION_HINT_MASK);
256 attributes_mask |= GDK_WA_CURSOR;
257
258 paned->handle = gdk_window_new (widget->window,
259 &attributes, attributes_mask);
260 gdk_window_set_user_data (paned->handle, paned);
261 gdk_cursor_destroy (attributes.cursor);
262
263 widget->style = gtk_style_attach (widget->style, widget->window);
264
265 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
266 gtk_style_set_background (widget->style, paned->handle, GTK_STATE_NORMAL);
267
268 gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
269
270 gdk_window_show (paned->handle);
271 }
272
273
274 static void
gimv_paned_map(GtkWidget * widget)275 gimv_paned_map (GtkWidget *widget)
276 {
277 GimvPaned *paned;
278
279 g_return_if_fail (widget != NULL);
280 g_return_if_fail (GIMV_IS_PANED (widget));
281
282 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
283 paned = GIMV_PANED (widget);
284
285 if (paned->child1
286 && GTK_WIDGET_VISIBLE (paned->child1)
287 && !GTK_WIDGET_MAPPED (paned->child1))
288 gtk_widget_map (paned->child1);
289 if (paned->child2
290 && GTK_WIDGET_VISIBLE (paned->child2)
291 && !GTK_WIDGET_MAPPED (paned->child2))
292 gtk_widget_map (paned->child2);
293
294 gdk_window_show (widget->window);
295 }
296
297
298 static void
gimv_paned_unmap(GtkWidget * widget)299 gimv_paned_unmap (GtkWidget *widget)
300 {
301 g_return_if_fail (widget != NULL);
302 g_return_if_fail (GIMV_IS_PANED (widget));
303
304 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
305
306 gdk_window_hide (widget->window);
307 }
308
309
310 static void
gimv_paned_unrealize(GtkWidget * widget)311 gimv_paned_unrealize (GtkWidget *widget)
312 {
313 GimvPaned *paned;
314
315 g_return_if_fail (widget != NULL);
316 g_return_if_fail (GIMV_IS_PANED (widget));
317
318 paned = GIMV_PANED (widget);
319
320 if (paned->xor_gc) {
321 gdk_gc_destroy (paned->xor_gc);
322 paned->xor_gc = NULL;
323 }
324
325 if (paned->handle) {
326 gdk_window_set_user_data (paned->handle, NULL);
327 gdk_window_destroy (paned->handle);
328 paned->handle = NULL;
329 }
330
331 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
332 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
333 }
334
335
336 static gint
gimv_paned_expose(GtkWidget * widget,GdkEventExpose * event)337 gimv_paned_expose (GtkWidget *widget,
338 GdkEventExpose *event)
339 {
340 GimvPaned *paned;
341 GdkEventExpose child_event;
342
343 g_return_val_if_fail (widget != NULL, FALSE);
344 g_return_val_if_fail (GIMV_IS_PANED (widget), FALSE);
345 g_return_val_if_fail (event != NULL, FALSE);
346
347 if (GTK_WIDGET_DRAWABLE (widget)) {
348 paned = GIMV_PANED (widget);
349
350 /* An expose event for the handle */
351 if (event->window == paned->handle) {
352 gint width, height;
353
354 gdk_window_get_size (paned->handle, &width, &height);
355
356 gtk_paint_flat_box (widget->style, paned->handle,
357 GTK_WIDGET_STATE (widget),
358 GTK_SHADOW_NONE,
359 &event->area, widget, "paned",
360 0, 0,
361 width, height);
362 } else {
363 child_event = *event;
364 if (paned->child1
365 && GTK_WIDGET_NO_WINDOW (paned->child1)
366 && gtk_widget_intersect (paned->child1,
367 &event->area,
368 &child_event.area))
369 gtk_widget_event (paned->child1,
370 (GdkEvent*) &child_event);
371
372 if (paned->child2
373 && GTK_WIDGET_NO_WINDOW (paned->child2)
374 && gtk_widget_intersect (paned->child2,
375 &event->area,
376 &child_event.area))
377 gtk_widget_event (paned->child2,
378 (GdkEvent*) &child_event);
379 }
380 }
381 return FALSE;
382 }
383
384
385 void
gimv_paned_add1(GimvPaned * paned,GtkWidget * widget)386 gimv_paned_add1 (GimvPaned *paned,
387 GtkWidget *widget)
388 {
389 gimv_paned_pack1 (paned, widget, FALSE, TRUE);
390 }
391
392
393 void
gimv_paned_add2(GimvPaned * paned,GtkWidget * widget)394 gimv_paned_add2 (GimvPaned *paned, GtkWidget *widget)
395 {
396 gimv_paned_pack2 (paned, widget, TRUE, TRUE);
397 }
398
399
400 void
gimv_paned_pack1(GimvPaned * paned,GtkWidget * child,gboolean resize,gboolean shrink)401 gimv_paned_pack1 (GimvPaned *paned,
402 GtkWidget *child,
403 gboolean resize,
404 gboolean shrink)
405 {
406 g_return_if_fail (paned != NULL);
407 g_return_if_fail (GIMV_IS_PANED (paned));
408 g_return_if_fail (GTK_IS_WIDGET (child));
409
410 if (!paned->child1) {
411 paned->child1 = child;
412 paned->child1_resize = resize;
413 paned->child1_shrink = shrink;
414
415 gtk_widget_set_parent (child, GTK_WIDGET (paned));
416
417 if (GTK_WIDGET_REALIZED (child->parent))
418 gtk_widget_realize (child);
419
420 if (GTK_WIDGET_VISIBLE (child->parent)
421 && GTK_WIDGET_VISIBLE (child))
422 {
423 if (GTK_WIDGET_MAPPED (child->parent))
424 gtk_widget_map (child);
425
426 gtk_widget_queue_resize (child);
427 }
428 }
429 }
430
431
432 void
gimv_paned_pack2(GimvPaned * paned,GtkWidget * child,gboolean resize,gboolean shrink)433 gimv_paned_pack2 (GimvPaned *paned,
434 GtkWidget *child,
435 gboolean resize,
436 gboolean shrink)
437 {
438 g_return_if_fail (paned != NULL);
439 g_return_if_fail (GIMV_IS_PANED (paned));
440 g_return_if_fail (GTK_IS_WIDGET (child));
441
442 if (!paned->child2) {
443 paned->child2 = child;
444 paned->child2_resize = resize;
445 paned->child2_shrink = shrink;
446
447 gtk_widget_set_parent (child, GTK_WIDGET (paned));
448
449 if (GTK_WIDGET_REALIZED (child->parent))
450 gtk_widget_realize (child);
451
452 if (GTK_WIDGET_VISIBLE (child->parent)
453 && GTK_WIDGET_VISIBLE (child))
454 {
455 if (GTK_WIDGET_MAPPED (child->parent))
456 gtk_widget_map (child);
457
458 gtk_widget_queue_resize (child);
459 }
460 }
461 }
462
463
464 static void
gimv_paned_add(GtkContainer * container,GtkWidget * widget)465 gimv_paned_add (GtkContainer *container,
466 GtkWidget *widget)
467 {
468 GimvPaned *paned;
469
470 g_return_if_fail (container != NULL);
471 g_return_if_fail (GIMV_IS_PANED (container));
472 g_return_if_fail (widget != NULL);
473
474 paned = GIMV_PANED (container);
475
476 if (!paned->child1)
477 gimv_paned_add1 (GIMV_PANED (container),widget);
478 else if (!paned->child2)
479 gimv_paned_add2 (GIMV_PANED (container),widget);
480 }
481
482
483 static void
gimv_paned_remove(GtkContainer * container,GtkWidget * widget)484 gimv_paned_remove (GtkContainer *container,
485 GtkWidget *widget)
486 {
487 GimvPaned *paned;
488 gboolean was_visible;
489
490 g_return_if_fail (container != NULL);
491 g_return_if_fail (GIMV_IS_PANED (container));
492 g_return_if_fail (widget != NULL);
493
494 paned = GIMV_PANED (container);
495 was_visible = GTK_WIDGET_VISIBLE (widget);
496
497 if (paned->child1 == widget) {
498 gtk_widget_unparent (widget);
499
500 paned->child1 = NULL;
501
502 if (was_visible && GTK_WIDGET_VISIBLE (container))
503 gtk_widget_queue_resize (GTK_WIDGET (container));
504 } else if (paned->child2 == widget) {
505 gtk_widget_unparent (widget);
506
507 paned->child2 = NULL;
508
509 if (was_visible && GTK_WIDGET_VISIBLE (container))
510 gtk_widget_queue_resize (GTK_WIDGET (container));
511 }
512 }
513
514
515 static void
gimv_paned_forall(GtkContainer * container,gboolean include_internals,GtkCallback callback,gpointer callback_data)516 gimv_paned_forall (GtkContainer *container,
517 gboolean include_internals,
518 GtkCallback callback,
519 gpointer callback_data)
520 {
521 GimvPaned *paned;
522
523 g_return_if_fail (container != NULL);
524 g_return_if_fail (GIMV_IS_PANED (container));
525 g_return_if_fail (callback != NULL);
526
527 paned = GIMV_PANED (container);
528
529 if (paned->child1)
530 (* callback) (paned->child1, callback_data);
531 if (paned->child2)
532 (* callback) (paned->child2, callback_data);
533 }
534
535
536 void
gimv_paned_set_position(GimvPaned * paned,gint position)537 gimv_paned_set_position (GimvPaned *paned,
538 gint position)
539 {
540 g_return_if_fail (paned != NULL);
541 g_return_if_fail (GIMV_IS_PANED (paned));
542
543 if (position >= 0) {
544 /* We don't clamp here - the assumption is that
545 * if the total allocation changes at the same time
546 * as the position, the position set is with reference
547 * to the new total size. If only the position changes,
548 * then clamping will occur in gimv_paned_compute_position()
549 */
550 paned->child1_size = position;
551 paned->position_set = TRUE;
552
553 paned->child_hidden = 0;
554 } else
555 paned->position_set = FALSE;
556
557 gtk_widget_queue_resize (GTK_WIDGET (paned));
558 }
559
560
561 gint
gimv_paned_get_position(GimvPaned * paned)562 gimv_paned_get_position (GimvPaned *paned)
563 {
564 g_return_val_if_fail (paned != NULL, 0);
565 g_return_val_if_fail (GIMV_IS_PANED (paned), 0);
566
567 return paned->child1_size;
568 }
569
570
571 void
gimv_paned_set_gutter_size(GimvPaned * paned,guint16 size)572 gimv_paned_set_gutter_size (GimvPaned *paned,
573 guint16 size)
574 {
575 g_return_if_fail (paned != NULL);
576 g_return_if_fail (GIMV_IS_PANED (paned));
577
578 paned->gutter_size = size;
579
580 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (paned)))
581 gtk_widget_queue_resize (GTK_WIDGET (paned));
582 }
583
584
585 void
gimv_paned_xor_line(GimvPaned * paned)586 gimv_paned_xor_line (GimvPaned *paned)
587 {
588 GIMV_PANED_CLASS (GTK_OBJECT_GET_CLASS (paned))->xor_line (paned);
589 }
590
591
592 /**
593 * gimv_paned_child1_use_minsize: Set a minimum size for child 1.
594 * @paned: The paned object.
595 * @use_minsize: Whether or not to use the minimum size option.
596 * @minsize: The minimun size to use if the option is enabled.
597 *
598 * If @use_minsize = TRUE then set @minsize as the minimal size child 1 can
599 * be set to.
600 * If @use_minsize = FALSE then disable this option, that is, child 1 can have
601 * any size.
602 **/
603 void
gimv_paned_child1_use_minsize(GimvPaned * paned,gboolean use_minsize,gint minsize)604 gimv_paned_child1_use_minsize (GimvPaned *paned,
605 gboolean use_minsize,
606 gint minsize)
607 {
608 g_return_if_fail (paned != NULL);
609 g_return_if_fail (GIMV_IS_PANED (paned));
610
611 paned->child1_use_minsize = use_minsize;
612 if (use_minsize)
613 paned->child1_minsize = minsize;
614 }
615
616
617 /**
618 * gimv_paned_child1_use_minsize: Set a minimum size for child 2.
619 * @paned: The paned object.
620 * @use_minsize: Whether or not to use the minimum size option.
621 * @minsize: The minimun size to use if the option is enabled.
622 *
623 * If @use_minsize = TRUE then set @minsize as the minimal size child 2 can
624 * be set to.
625 * If @use_minsize = FALSE then disable this option, that is, child 2 can have
626 * any size.
627 **/
628 void
gimv_paned_child2_use_minsize(GimvPaned * paned,gboolean use_minsize,gint minsize)629 gimv_paned_child2_use_minsize (GimvPaned *paned,
630 gboolean use_minsize,
631 gint minsize)
632 {
633 g_return_if_fail (paned != NULL);
634 g_return_if_fail (GIMV_IS_PANED (paned));
635
636 paned->child2_use_minsize = use_minsize;
637 if (use_minsize)
638 paned->child2_minsize = minsize;
639 }
640
641
642 void
gimv_paned_compute_position(GimvPaned * paned,gint allocation,gint child1_req,gint child2_req)643 gimv_paned_compute_position (GimvPaned *paned,
644 gint allocation,
645 gint child1_req,
646 gint child2_req)
647 {
648 gint child2_size;
649
650 g_return_if_fail (paned != NULL);
651 g_return_if_fail (GIMV_IS_PANED (paned));
652
653 paned->min_position = paned->child1_shrink ? 0 : child1_req;
654
655 paned->max_position = allocation;
656 if (!paned->child2_shrink)
657 paned->max_position = MAX (1, paned->max_position - child2_req);
658
659 if (!paned->position_set) {
660 if (paned->child1_resize && !paned->child2_resize)
661 paned->child1_size = MAX (1, allocation - child2_req);
662 else if (!paned->child1_resize && paned->child2_resize)
663 paned->child1_size = child1_req;
664 else if (child1_req + child2_req != 0)
665 paned->child1_size = allocation * ((gdouble)child1_req / (child1_req + child2_req));
666 else
667 paned->child1_size = allocation * 0.5;
668 } else {
669 /* If the position was set before the initial allocation.
670 * (paned->last_allocation <= 0) just clamp it and leave it.
671 */
672 if (paned->last_allocation > 0) {
673 if (paned->child1_resize && !paned->child2_resize)
674 paned->child1_size += (allocation - paned->last_allocation);
675 else if (!(!paned->child1_resize && paned->child2_resize))
676 paned->child1_size = allocation * ((gdouble)paned->child1_size / (paned->last_allocation));
677 }
678 }
679
680 paned->child1_size = CLAMP (paned->child1_size,
681 paned->min_position,
682 paned->max_position);
683
684 child2_size = allocation - paned->child1_size;
685
686
687 /* Ensure that minimum sizes, if enabled, are respected. */
688 if (paned->child1_use_minsize) {
689 if (paned->child1_size < paned->child1_minsize)
690 paned->child1_size = paned->child1_minsize;
691 } else if (paned->child2_use_minsize) {
692 if (child2_size < paned->child2_minsize)
693 paned->child1_size = paned->child2_minsize;
694 }
695
696 if (paned->child_hidden == 1)
697 paned->child1_size = 0;
698 else if (paned->child_hidden == 2) {
699 paned->child1_size = allocation;
700 paned->child1_size += paned->gutter_size;
701 }
702
703 paned->last_allocation = allocation;
704 }
705
706
707 /**
708 * gimv_paned_hide_child1: hide child 1.
709 * @paned: The paned widget.
710 *
711 * Hide the child number 1.
712 **/
713 void
gimv_paned_hide_child1(GimvPaned * paned)714 gimv_paned_hide_child1 (GimvPaned *paned)
715 {
716 g_return_if_fail (paned != NULL);
717 g_return_if_fail (GIMV_IS_PANED (paned));
718
719 if (paned->child_hidden != 0)
720 return;
721
722 paned->child_hidden = 1;
723 gtk_widget_queue_resize (GTK_WIDGET (paned));
724 }
725
726
727 /**
728 * gimv_paned_hide_child2: collapse child 2.
729 * @paned: The paned widget.
730 *
731 * Hide the child number 2.
732 **/
733 void
gimv_paned_hide_child2(GimvPaned * paned)734 gimv_paned_hide_child2 (GimvPaned *paned)
735 {
736 g_return_if_fail (paned != NULL);
737 g_return_if_fail (GIMV_IS_PANED (paned));
738
739 if (paned->child_hidden != 0)
740 return;
741
742 paned->child_hidden = 2;
743 gtk_widget_queue_resize (GTK_WIDGET (paned));
744 }
745
746
747 /**
748 * gimv_paned_split: split the paned widget in two halves.
749 * @paned: The paned widget.
750 *
751 * Give both children the same size.
752 **/
753 void
gimv_paned_split(GimvPaned * paned)754 gimv_paned_split (GimvPaned *paned)
755 {
756 g_return_if_fail (paned != NULL);
757 g_return_if_fail (GIMV_IS_PANED (paned));
758
759 gimv_paned_set_position (paned, paned->last_allocation / 2);
760 }
761
762
763 guint
gimv_paned_which_hidden(GimvPaned * paned)764 gimv_paned_which_hidden (GimvPaned *paned)
765 {
766 g_return_val_if_fail (paned != NULL, 0);
767 g_return_val_if_fail (GIMV_IS_PANED (paned), 0);
768
769 return paned->child_hidden;
770 }
771
772
773 static gint
gimv_paned_motion(GtkWidget * widget,GdkEventMotion * event)774 gimv_paned_motion (GtkWidget *widget,
775 GdkEventMotion *event)
776 {
777 GimvPaned *paned;
778 gint pos;
779 static gint last_size = -1;
780
781 g_return_val_if_fail (widget != NULL, FALSE);
782 g_return_val_if_fail (GIMV_IS_PANED (widget), FALSE);
783
784 paned = GIMV_PANED (widget);
785
786 if (event->is_hint || event->window != widget->window) {
787 if (paned->horizontal)
788 gtk_widget_get_pointer (widget, &pos, NULL);
789 else
790 gtk_widget_get_pointer (widget, NULL, &pos);
791 } else
792 pos = (paned->horizontal) ? event->x : event->y;
793
794 if (paned->in_drag) {
795 gint child1_size, child2_size;
796
797 child1_size = (pos - GTK_CONTAINER (paned)->border_width
798 - paned->gutter_size / 2);
799 child2_size = paned->last_allocation - child1_size;
800
801 if (paned->child1_use_minsize
802 && (child1_size < paned->child1_minsize))
803 child1_size = paned->child1_minsize;
804
805 if (paned->child2_use_minsize
806 && (child2_size < paned->child2_minsize))
807 child1_size = paned->last_allocation - paned->child2_minsize;
808
809 /* Avoid blinking. */
810 if (child1_size == last_size)
811 return FALSE;
812
813 last_size = child1_size;
814
815 gimv_paned_xor_line (paned);
816 paned->child1_size = CLAMP (child1_size,
817 paned->min_position,
818 paned->max_position);
819 gimv_paned_xor_line (paned);
820 }
821
822 return FALSE;
823 }
824
825 #else
826
827 guint
gimv_paned_which_hidden(GimvPaned * paned)828 gimv_paned_which_hidden (GimvPaned *paned)
829 {
830 g_return_val_if_fail (GIMV_IS_PANED (paned), 0);
831 g_return_val_if_fail (paned->child1 && paned->child2, 0);
832
833 if (!GTK_WIDGET_VISIBLE (paned->child1)
834 && GTK_WIDGET_VISIBLE (paned->child2))
835 {
836 return 1;
837
838 } else if (GTK_WIDGET_VISIBLE (paned->child1)
839 && !GTK_WIDGET_VISIBLE (paned->child2))
840 {
841 return 2;
842
843 } else {
844 return 0;
845 }
846 }
847
848 #endif /* USE_NORMAL_PANED */
849