]> git.draconx.ca Git - aspectbin.git/blob - aspectbin.c
Initial Commit
[aspectbin.git] / aspectbin.c
1 #include <stdio.h>
2 #include "aspectbin.h"
3
4 static void aspect_bin_size_request(GtkWidget *, GtkRequisition *);
5 static void aspect_bin_size_allocate(GtkWidget *, GtkAllocation *);
6 static void aspect_bin_remove(GtkContainer *, GtkWidget *);
7 static void aspect_bin_forall(GtkContainer *, gboolean, GtkCallback, gpointer);
8
9 G_DEFINE_TYPE(AspectBin, aspect_bin, GTK_TYPE_BIN)
10
11 static void aspect_bin_init(AspectBin *ab)
12 {
13         ab->child = NULL;
14         ab->ratio = 1;
15 }
16
17 static void aspect_bin_class_init(AspectBinClass *abc)
18 {
19         GtkWidgetClass    *widget_class    = GTK_WIDGET_CLASS(abc);
20         GtkContainerClass *container_class = GTK_CONTAINER_CLASS(abc);
21
22         widget_class->size_request  = aspect_bin_size_request;
23         widget_class->size_allocate = aspect_bin_size_allocate;
24
25         container_class->remove = aspect_bin_remove;
26         container_class->forall = aspect_bin_forall;
27 }
28
29 GtkWidget *aspect_bin_new(void)
30 {
31         return GTK_WIDGET(g_object_new(ASPECT_BIN_TYPE, NULL));
32 }
33
34 static void aspect_bin_remove(GtkContainer *container, GtkWidget *child)
35 {
36         AspectBin *abin = ASPECT_BIN(container);
37
38         if (abin->child == child) {
39                 aspect_bin_set_body_widget(abin, NULL, 1);
40         } else {
41                 GTK_CONTAINER_CLASS(aspect_bin_parent_class)->remove
42                         (container, child);
43         }
44 }
45
46 static void aspect_bin_forall(GtkContainer *container,
47                               gboolean      include_internals,
48                               GtkCallback   callback,
49                               gpointer      callback_data)
50 {
51         AspectBin *abin = ASPECT_BIN(container);
52         GtkBin     *bin = GTK_BIN(container);
53
54         if (bin->child)
55                 callback(bin->child, callback_data);
56         
57         if (abin->child)
58                 callback(abin->child, callback_data);
59 }
60
61 static void
62 aspect_bin_size_request(GtkWidget *widget, GtkRequisition *requisition)
63 {
64         AspectBin *abin = ASPECT_BIN(widget);
65         GtkBin    *bin  = GTK_BIN(widget);
66         GtkRequisition creq = {0}, areq = {0};
67
68         if (bin->child && GTK_WIDGET_VISIBLE(bin->child)) {
69                 gtk_widget_size_request(bin->child, &creq);
70         }
71
72         if (abin->child && GTK_WIDGET_VISIBLE(abin->child)) {
73                 int wtmp, htmp;
74                 gtk_widget_size_request(abin->child, &areq);
75                 wtmp = areq.height * abin->ratio + 0.5;
76                 htmp = areq.width  / abin->ratio + 0.5;
77
78                 if (wtmp > areq.width) {
79                         areq.width  = wtmp;
80                 } else {
81                         areq.height = htmp;
82                 }
83         }
84
85         requisition->width  = areq.width + creq.width;
86         requisition->height = MAX(areq.height, creq.height);
87 }
88
89 static void
90 aspect_bin_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
91 {
92         AspectBin *abin = ASPECT_BIN(widget);
93         GtkBin    *bin  = GTK_BIN(widget);
94         GtkRequisition creq = {0};
95         GtkAllocation csize = {0}, asize = {0};
96         
97         if (abin->child && GTK_WIDGET_VISIBLE(abin->child)) {
98                 asize.height = allocation->height;
99                 asize.width  = asize.height * abin->ratio + 0.5;
100
101                 if (asize.width > allocation->width) {
102                         asize.width  = allocation->width;
103                         asize.height = asize.width / abin->ratio + 0.5;
104                 }
105         }
106
107         if (bin->child && GTK_WIDGET_VISIBLE(bin->child)) {
108                 gtk_widget_get_child_requisition(bin->child, &creq);
109
110                 if (allocation->width - asize.width < creq.width) {
111                         asize.width  = allocation->width - creq.width;
112                         asize.height = asize.width / abin->ratio + 0.5;
113                 }
114
115                 csize.width = allocation->width - asize.width;
116                 csize.height = allocation->height;
117                 csize.x = asize.width;
118                 csize.y = 0;
119         }
120
121         if (bin->child)
122                 gtk_widget_size_allocate(bin->child, &csize);
123         if (abin->child)
124                 gtk_widget_size_allocate(abin->child, &asize);
125 }
126
127 void
128 aspect_bin_set_body_widget(AspectBin *ab, GtkWidget *widget, gfloat ratio)
129 {
130         gboolean need_resize = FALSE;
131
132         g_return_if_fail(IS_ASPECT_BIN(ab));
133         g_return_if_fail(widget == NULL || GTK_IS_WIDGET(widget));
134         g_return_if_fail(widget == NULL || widget->parent == NULL);
135
136         if (ab->child == widget)
137                 return;
138         
139         if (ab->child) {
140                 need_resize |= GTK_WIDGET_VISIBLE(ab->child);
141                 gtk_widget_unparent(ab->child);
142         }
143
144         ab->child = widget;
145         if (widget) {
146                 gtk_widget_set_parent(widget, GTK_WIDGET(ab));
147                 need_resize |= GTK_WIDGET_VISIBLE(widget);
148         }
149
150         if (GTK_WIDGET_VISIBLE(ab) && need_resize)
151                 gtk_widget_queue_resize(GTK_WIDGET(ab));
152 }