1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library 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 GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27 #include "gtkbar.h"
28
29 //#define DEBUGPRN
30 #include "dbg.h"
31
32 #define MAX_CHILD_SIZE 150
33
34 static void gtk_bar_class_init (GtkBarClass *klass);
35 static void gtk_bar_size_request (GtkWidget *widget, GtkRequisition *requisition);
36 static void gtk_bar_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
37 //static gint gtk_bar_expose (GtkWidget *widget, GdkEventExpose *event);
38 float ceilf(float x);
39
40 static GtkBoxClass *parent_class = NULL;
41
42 GType
gtk_bar_get_type(void)43 gtk_bar_get_type (void)
44 {
45 static GType bar_type = 0;
46
47 if (!bar_type)
48 {
49 static const GTypeInfo bar_info =
50 {
51 sizeof (GtkBarClass),
52 NULL, /* base_init */
53 NULL, /* base_finalize */
54 (GClassInitFunc) gtk_bar_class_init,
55 NULL, /* class_finalize */
56 NULL, /* class_data */
57 sizeof (GtkBar),
58 0, /* n_preallocs */
59 NULL
60 };
61
62 bar_type = g_type_register_static (GTK_TYPE_BOX, "GtkBar",
63 &bar_info, 0);
64 }
65
66 return bar_type;
67 }
68
69 static void
gtk_bar_class_init(GtkBarClass * class)70 gtk_bar_class_init (GtkBarClass *class)
71 {
72 GtkWidgetClass *widget_class;
73
74 parent_class = g_type_class_peek_parent (class);
75 widget_class = (GtkWidgetClass*) class;
76
77 widget_class->size_request = gtk_bar_size_request;
78 widget_class->size_allocate = gtk_bar_size_allocate;
79 //widget_class->expose_event = gtk_bar_expose;
80
81 }
82
83
84 GtkWidget*
gtk_bar_new(GtkOrientation orient,gint spacing,gint child_height,gint child_width)85 gtk_bar_new(GtkOrientation orient, gint spacing,
86 gint child_height, gint child_width)
87 {
88 GtkBar *bar;
89
90 bar = g_object_new (GTK_TYPE_BAR, NULL);
91 GTK_BOX (bar)->spacing = spacing;
92 bar->orient = orient;
93 bar->child_width = MAX(1, child_width);
94 bar->child_height = MAX(1, child_height);
95 bar->dimension = 1;
96 return (GtkWidget *)bar;
97 }
98
99 void
gtk_bar_set_dimension(GtkBar * bar,gint dimension)100 gtk_bar_set_dimension(GtkBar *bar, gint dimension)
101 {
102 dimension = MAX(1, dimension);
103 if (bar->dimension != dimension) {
104 bar->dimension = MAX(1, dimension);
105 gtk_widget_queue_resize(GTK_WIDGET(bar));
106 }
107 }
108
gtk_bar_get_dimension(GtkBar * bar)109 gint gtk_bar_get_dimension(GtkBar *bar)
110 {
111 return bar->dimension;
112 }
113
114 static void
gtk_bar_size_request(GtkWidget * widget,GtkRequisition * requisition)115 gtk_bar_size_request(GtkWidget *widget, GtkRequisition *requisition)
116 {
117 GtkBox *box = GTK_BOX(widget);
118 GtkBar *bar = GTK_BAR(widget);;
119 GtkBoxChild *child;
120 GList *children;
121 gint nvis_children, rows, cols, dim;
122
123 nvis_children = 0;
124 children = box->children;
125 while (children) {
126 child = children->data;
127 children = children->next;
128
129 if (GTK_WIDGET_VISIBLE(child->widget)) {
130 GtkRequisition child_requisition;
131
132 /* Do not remove child request !!! Label's proper layout depends
133 * on request running before alloc. */
134 gtk_widget_size_request(child->widget, &child_requisition);
135 nvis_children++;
136 }
137 }
138 DBG("nvis_children=%d\n", nvis_children);
139 if (!nvis_children) {
140 requisition->width = 2;
141 requisition->height = 2;
142 return;
143 }
144 dim = MIN(bar->dimension, nvis_children);
145 if (bar->orient == GTK_ORIENTATION_HORIZONTAL) {
146 rows = dim;
147 cols = (gint) ceilf((float) nvis_children / rows);
148 } else {
149 cols = dim;
150 rows = (gint) ceilf((float) nvis_children / cols);
151 }
152
153 requisition->width = bar->child_width * cols
154 + box->spacing * (cols - 1);
155 requisition->height = bar->child_height * rows
156 + box->spacing * (rows - 1);
157 DBG("width=%d, height=%d\n", requisition->width, requisition->height);
158 }
159
160 static void
gtk_bar_size_allocate(GtkWidget * widget,GtkAllocation * allocation)161 gtk_bar_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
162 {
163 GtkBox *box;
164 GtkBar *bar;
165 GtkBoxChild *child;
166 GList *children;
167 GtkAllocation child_allocation;
168 gint nvis_children, tmp, rows, cols, dim;
169
170 ENTER;
171 DBG("a.w=%d a.h=%d\n", allocation->width, allocation->height);
172 box = GTK_BOX (widget);
173 bar = GTK_BAR (widget);
174 widget->allocation = *allocation;
175
176 nvis_children = 0;
177 children = box->children;
178 while (children) {
179 child = children->data;
180 children = children->next;
181
182 if (GTK_WIDGET_VISIBLE (child->widget))
183 nvis_children += 1;
184 }
185 gtk_widget_queue_draw(widget);
186 dim = MIN(bar->dimension, nvis_children);
187 if (nvis_children == 0)
188 RET();
189 if (bar->orient == GTK_ORIENTATION_HORIZONTAL) {
190 rows = dim;
191 cols = (gint) ceilf((float) nvis_children / rows);
192 } else {
193 cols = dim;
194 rows = (gint) ceilf((float) nvis_children / cols);
195 }
196 DBG("rows=%d cols=%d\n", rows, cols);
197 tmp = allocation->width - (cols - 1) * box->spacing;
198 child_allocation.width = MIN(tmp / cols, bar->child_width);
199 tmp = allocation->height - (rows - 1) * box->spacing;
200 child_allocation.height = MIN(tmp / rows, bar->child_height);
201
202 if (child_allocation.width < 1)
203 child_allocation.width = 1;
204 if (child_allocation.height < 1)
205 child_allocation.height = 1;
206 DBG("child alloc: width=%d height=%d\n",
207 child_allocation.width,
208 child_allocation.height);
209
210 child_allocation.x = allocation->x;
211 child_allocation.y = allocation->y;
212 children = box->children;
213 tmp = 0;
214 while (children) {
215 child = children->data;
216 children = children->next;
217
218 if (GTK_WIDGET_VISIBLE (child->widget)) {
219 DBG("allocate x=%d y=%d\n", child_allocation.x,
220 child_allocation.y);
221 gtk_widget_size_allocate(child->widget, &child_allocation);
222 tmp++;
223 if (tmp == cols) {
224 child_allocation.x = allocation->x;
225 child_allocation.y += child_allocation.height + box->spacing;
226 tmp = 0;
227 } else {
228 child_allocation.x += child_allocation.width + box->spacing;
229 }
230 }
231 }
232 RET();
233 }
234
235
236 #if 0
237 static gint
238 gtk_bar_expose (GtkWidget *widget, GdkEventExpose *event)
239 {
240 ENTER;
241
242 if (GTK_WIDGET_DRAWABLE (widget)) {
243 int w, h;
244
245 DBG("w, h = %d,%d\n", w, h);
246 if (!GTK_WIDGET_APP_PAINTABLE (widget))
247 gtk_paint_flat_box (widget->style, widget->window,
248 widget->state, GTK_SHADOW_NONE,
249 NULL /*&event->area*/, widget, NULL,
250 0, 0, w, h);
251 }
252 RET(FALSE);
253 }
254 #endif
255