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