2525 * don't make a big deal out of it. */
2626
2727#include "config.h"
28-
2928#include <gtk/gtk.h>
3029
3130#include "na-grid.h"
3231
3332#include "system-tray/na-tray.h"
3433#include "status-notifier/sn-host-v0.h"
3534
36- #define ICON_SPACING 1
37- #define MIN_GRID_SIZE 3
35+ #define MIN_ICON_SIZE_DEFAULT 24
36+
37+ typedef struct
38+ {
39+ GtkOrientation orientation ;
40+ gint index ;
41+ NaGrid * grid ;
42+ } SortData ;
3843
3944struct _NaGrid
4045{
41- GtkBox parent ;
46+ GtkGrid parent ;
47+
48+ gint icon_padding ;
49+ gint icon_size ;
4250
43- gint icon_padding ;
44- gint icon_size ;
51+ gint min_icon_size ;
52+ gint cols ;
53+ gint rows ;
54+ gint length ;
4555
46- GSList * hosts ;
47- GSList * items ;
56+ GSList * hosts ;
57+ GSList * items ;
4858};
4959
5060enum
5464 PROP_ICON_SIZE
5565};
5666
57- G_DEFINE_TYPE (NaGrid , na_grid , GTK_TYPE_BOX )
67+ G_DEFINE_TYPE (NaGrid , na_grid , GTK_TYPE_GRID )
5868
5969static gint
6070compare_items (gconstpointer a ,
@@ -85,16 +95,95 @@ compare_items (gconstpointer a,
8595}
8696
8797static void
88- reorder_items (GtkWidget * widget ,
89- gpointer user_data )
98+ sort_items (GtkWidget * item ,
99+ SortData * data )
90100{
91- NaGrid * nb ;
92- gint position ;
101+ gint col , row , left_attach , top_attach ;
93102
94- nb = NA_GRID (user_data );
103+ /* row / col number depends on whether we are horizontal or vertical */
104+ if (data -> orientation == GTK_ORIENTATION_HORIZONTAL )
105+ {
106+ col = data -> index / data -> grid -> rows ;
107+ row = data -> index % data -> grid -> rows ;
108+ }
109+ else
110+ {
111+ row = data -> index / data -> grid -> cols ;
112+ col = data -> index % data -> grid -> cols ;
113+ }
114+
115+ /* only update item position if it has changed from current */
116+ gtk_container_child_get (GTK_CONTAINER (data -> grid ),
117+ item ,
118+ "left-attach" , & left_attach ,
119+ "top-attach" , & top_attach ,
120+ NULL );
121+
122+ if (left_attach != col || top_attach != row )
123+ {
124+ gtk_container_child_set (GTK_CONTAINER (data -> grid ),
125+ item ,
126+ "left-attach" , col ,
127+ "top-attach" , row ,
128+ NULL );
129+ }
95130
96- position = g_slist_index (nb -> items , widget );
97- gtk_box_reorder_child (GTK_BOX (nb ), widget , position );
131+ /* increment to index of next item */
132+ data -> index ++ ;
133+ }
134+
135+ static void
136+ refresh_grid (NaGrid * self )
137+ {
138+ GtkOrientation orientation ;
139+ GtkAllocation allocation ;
140+ gint rows , cols , length ;
141+
142+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (self ));
143+ gtk_widget_get_allocation (GTK_WIDGET (self ), & allocation );
144+ length = g_slist_length (self -> items );
145+
146+ if (orientation == GTK_ORIENTATION_HORIZONTAL )
147+ {
148+ rows = MAX (1 , allocation .height / self -> min_icon_size );
149+ cols = MAX (1 , length / rows );
150+ if (length % rows )
151+ cols ++ ;
152+ }
153+ else
154+ {
155+ cols = MAX (1 , allocation .width / self -> min_icon_size );
156+ rows = MAX (1 , length / cols );
157+ if (length % cols )
158+ rows ++ ;
159+ }
160+
161+ if (self -> cols != cols || self -> rows != rows || self -> length != length )
162+ {
163+ self -> cols = cols ;
164+ self -> rows = rows ;
165+ self -> length = length ;
166+
167+ SortData data ;
168+ data .orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (self ));
169+ data .index = 0 ;
170+ data .grid = self ;
171+
172+ g_slist_foreach (self -> items ,
173+ (GFunc ) sort_items ,
174+ & data );
175+ }
176+ }
177+
178+ void
179+ na_grid_set_min_icon_size (NaGrid * grid ,
180+ gint min_icon_size )
181+ {
182+ grid -> min_icon_size = min_icon_size ;
183+
184+ g_return_if_fail (NA_IS_GRID (grid ));
185+
186+ refresh_grid (grid );
98187}
99188
100189static void
@@ -111,10 +200,17 @@ item_added_cb (NaHost *host,
111200 G_BINDING_SYNC_CREATE );
112201
113202 self -> items = g_slist_prepend (self -> items , item );
114- gtk_box_pack_start (GTK_BOX (self ), GTK_WIDGET (item ), FALSE, FALSE, 0 );
203+
204+ gtk_widget_set_hexpand (GTK_WIDGET (item ), TRUE);
205+ gtk_widget_set_vexpand (GTK_WIDGET (item ), TRUE);
206+ gtk_grid_attach (GTK_GRID (self ),
207+ GTK_WIDGET (item ),
208+ self -> cols - 1 ,
209+ self -> rows - 1 ,
210+ 1 , 1 );
115211
116212 self -> items = g_slist_sort (self -> items , compare_items );
117- gtk_container_foreach ( GTK_CONTAINER ( self ), reorder_items , self );
213+ refresh_grid ( self );
118214}
119215
120216static void
@@ -128,52 +224,25 @@ item_removed_cb (NaHost *host,
128224
129225 gtk_container_remove (GTK_CONTAINER (self ), GTK_WIDGET (item ));
130226 self -> items = g_slist_remove (self -> items , item );
131- }
132-
133- static void
134- update_size_and_orientation (NaGrid * self ,
135- GtkOrientation orientation )
136- {
137- /* FIXME: do we really need that? comes from NaTray */
138- /* FIXME: if we do, do that in overridden preferred size handlers */
139-
140- /* note, you want this larger if the frame has non-NONE relief by default. */
141- switch (orientation )
142- {
143- case GTK_ORIENTATION_VERTICAL :
144- /* Give grid a min size so the frame doesn't look dumb */
145- gtk_widget_set_size_request (GTK_WIDGET (self ), MIN_GRID_SIZE , -1 );
146- break ;
147- case GTK_ORIENTATION_HORIZONTAL :
148- gtk_widget_set_size_request (GTK_WIDGET (self ), -1 , MIN_GRID_SIZE );
149- break ;
150- }
151- }
152-
153- static void
154- orientation_notify (GObject * object ,
155- GParamSpec * pspec ,
156- gpointer data )
157- {
158- update_size_and_orientation (NA_GRID (object ),
159- gtk_orientable_get_orientation (GTK_ORIENTABLE (object )));
227+ refresh_grid (self );
160228}
161229
162230static void
163231na_grid_init (NaGrid * self )
164232{
165- GtkOrientation orientation ;
166-
167233 self -> icon_padding = 0 ;
168234 self -> icon_size = 0 ;
169235
236+ self -> min_icon_size = MIN_ICON_SIZE_DEFAULT ;
237+ self -> cols = 1 ;
238+ self -> rows = 1 ;
239+ self -> length = 0 ;
240+
170241 self -> hosts = NULL ;
171242 self -> items = NULL ;
172-
173- orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (self ));
174- update_size_and_orientation (self , orientation );
175-
176- g_signal_connect (self , "notify::orientation" , G_CALLBACK (orientation_notify ), NULL );
243+
244+ gtk_grid_set_row_homogeneous (GTK_GRID (self ), TRUE);
245+ gtk_grid_set_column_homogeneous (GTK_GRID (self ), TRUE);
177246}
178247
179248static void
@@ -275,6 +344,14 @@ na_grid_unrealize (GtkWidget *widget)
275344 GTK_WIDGET_CLASS (na_grid_parent_class )-> unrealize (widget );
276345}
277346
347+ static void
348+ na_grid_size_allocate (GtkWidget * widget ,
349+ GtkAllocation * allocation )
350+ {
351+ GTK_WIDGET_CLASS (na_grid_parent_class )-> size_allocate (widget , allocation );
352+ refresh_grid (NA_GRID (widget ));
353+ }
354+
278355static void
279356na_grid_get_property (GObject * object ,
280357 guint property_id ,
@@ -336,6 +413,7 @@ na_grid_class_init (NaGridClass *klass)
336413 widget_class -> realize = na_grid_realize ;
337414 widget_class -> unrealize = na_grid_unrealize ;
338415 widget_class -> style_updated = na_grid_style_updated ;
416+ widget_class -> size_allocate = na_grid_size_allocate ;
339417
340418 g_object_class_install_property (gobject_class , PROP_ICON_PADDING ,
341419 g_param_spec_int ("icon-padding" ,
@@ -357,7 +435,6 @@ na_grid_new (GtkOrientation orientation)
357435{
358436 return g_object_new (NA_TYPE_GRID ,
359437 "orientation" , orientation ,
360- "spacing" , ICON_SPACING ,
361438 NULL );
362439}
363440
0 commit comments