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