diff options
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ChangeLog | 11 | ||||
-rw-r--r-- | shell/e-sidebar.c | 199 |
2 files changed, 75 insertions, 135 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog index 99c7a79424..658dbc471f 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,14 @@ +2004-05-05 Dan Winship <danw@ximian.com> + + * e-sidebar.c (layout_buttons): Change the algorithm so that if + the buttons can't be laid out perfectly rectangularly, then the + extra space is given to the first button (ie, Mail), rather than + the last button (eg, Connector). Also, merge the icons-only and + icons-plus-text layout code together since they were nearly + identical. + (e_sidebar_add_button, e_sidebar_set_mode): Tweak things a bit so + that in icons-only mode, the icons are centered in the buttons. + 2004-05-03 Dan Winship <danw@ximian.com> * e-shell-importer.c (e_shell_importer_start_import): Fix warnings diff --git a/shell/e-sidebar.c b/shell/e-sidebar.c index d4362066c6..40a45b5581 100644 --- a/shell/e-sidebar.c +++ b/shell/e-sidebar.c @@ -40,7 +40,8 @@ static GtkContainerClass *parent_class = NULL; typedef struct { GtkWidget *button_widget; - GtkWidget *label_widget; + GtkWidget *label; + GtkWidget *icon; GtkWidget *hbox; int id; } Button; @@ -70,17 +71,20 @@ static unsigned int signals[NUM_SIGNALS] = { 0 }; /* Utility functions. */ static Button * -button_new (GtkWidget *button_widget, GtkWidget *label_widget, GtkWidget *hbox, int id) +button_new (GtkWidget *button_widget, GtkWidget *label, GtkWidget *icon, + GtkWidget *hbox, int id) { Button *button = g_new (Button, 1); button->button_widget = button_widget; - button->label_widget = label_widget; + button->label = label; + button->icon = icon; button->hbox = hbox; button->id = id; g_object_ref (button_widget); - g_object_ref (label_widget); + g_object_ref (label); + g_object_ref (icon); g_object_ref (hbox); return button; @@ -90,7 +94,8 @@ static void button_free (Button *button) { g_object_unref (button->button_widget); - g_object_unref (button->label_widget); + g_object_unref (button->label); + g_object_unref (button->icon); g_object_unref (button->hbox); g_free (button); } @@ -146,68 +151,75 @@ button_toggled_callback (GtkToggleButton *toggle_button, } -/* Layout. */ +/* Layout. */ static int -do_layout_text_buttons (ESidebar *sidebar) +layout_buttons (ESidebar *sidebar) { GtkAllocation *allocation = & GTK_WIDGET (sidebar)->allocation; - GSList *rows [g_slist_length (sidebar->priv->buttons)]; - GSList *p; + gboolean icons_only = (sidebar->priv->mode == E_SIDEBAR_MODE_ICON); + int num_btns = g_slist_length (sidebar->priv->buttons), btns_per_row; + GSList **rows, *p; + Button *button; int row_number; - int row_width; int max_btn_width = 0, max_btn_height = 0; - int btns_required; int row_last; int x, y; int i; - /* (Yes, this code calls gtk_widget_size_request() an ungodly number of times, but it's not - like we care about performance here, and this makes the code simpler.) */ - + /* (Yes, this code calls gtk_widget_size_request() an ungodly + * number of times, but it's not like we care about + * performance here, and this makes the code simpler.) + */ - /* 1. Figure out the max width and height */ + /* Figure out the max width and height */ for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; GtkRequisition requisition; + button = p->data; gtk_widget_size_request (GTK_WIDGET (button->button_widget), &requisition); - max_btn_height = MAX (max_btn_height, requisition.height); + max_btn_height = MAX (max_btn_height, requisition.height); max_btn_width = MAX (max_btn_width, requisition.width); + } + /* Figure out how many rows and columns we'll use. */ + btns_per_row = allocation->width / (max_btn_width + H_PADDING); + if (!icons_only) { + /* If using text buttons, we want to try to have a + * completely filled-in grid, but if we can't, we want + * the odd row to have just a single button. + */ + while (num_btns % btns_per_row > 1) + btns_per_row--; } - /* 2. Split the buttons into rows, depending on the max_btn_width. */ + /* Assign buttons to rows */ + rows = g_new0 (GSList *, num_btns / btns_per_row + 1); - row_number = 0; - rows [0] = NULL; - row_width = H_PADDING; - btns_required = allocation->width / (max_btn_width + H_PADDING); - for (; btns_required > 2; btns_required--) { - if (g_slist_length (sidebar->priv->buttons) % btns_required == 0) - break; + if (!icons_only && num_btns % btns_per_row != 0) { + button = sidebar->priv->buttons->data; + rows [0] = g_slist_append (rows [0], button->button_widget); + p = sidebar->priv->buttons->next; + row_number = 1; + } else { + p = sidebar->priv->buttons; + row_number = 0; } - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; - if (g_slist_length (rows[row_number]) % btns_required == 0 - && rows [row_number] != NULL) { + for (; p != NULL; p = p->next) { + button = p->data; + + if (g_slist_length (rows [row_number]) == btns_per_row) row_number ++; - rows [row_number] = NULL; - row_width = H_PADDING; - } - row_width += max_btn_width + H_PADDING; rows [row_number] = g_slist_append (rows [row_number], button->button_widget); } row_last = row_number; - /* 3. Layout the buttons. */ - + /* Layout the buttons. */ y = allocation->y + allocation->height - V_PADDING - 1; for (i = row_last; i >= 0; i --) { int len, extra_width; @@ -215,7 +227,10 @@ do_layout_text_buttons (ESidebar *sidebar) y -= max_btn_height; x = H_PADDING + allocation->x; len = g_slist_length (rows[i]); - extra_width = (allocation->width - (len * max_btn_width ) - (len * H_PADDING)) / len; + if (sidebar->priv->mode == E_SIDEBAR_MODE_TEXT) + extra_width = (allocation->width - (len * max_btn_width ) - (len * H_PADDING)) / len; + else + extra_width = 0; for (p = rows [i]; p != NULL; p = p->next) { GtkAllocation child_allocation; @@ -232,91 +247,9 @@ do_layout_text_buttons (ESidebar *sidebar) y -= V_PADDING; } - /* 4. Free stuff */ - - for (i = 0; i <= row_last; i ++) - g_slist_free (rows [i]); - - return y; -} - -static int -do_layout_icon_buttons (ESidebar *sidebar) -{ - GtkAllocation *allocation = & GTK_WIDGET (sidebar)->allocation; - GSList *rows [g_slist_length (sidebar->priv->buttons)]; - GSList *p; - int row_number; - int row_width; - int row_last; - int x, y; - int i; - - /* (Yes, this code calls gtk_widget_size_request() an ungodly number of times, but it's not - like we care about performance here, and this makes the code simpler.) */ - - /* 1. Split the buttons into rows, depending on their width. */ - - row_number = 0; - rows [0] = NULL; - row_width = H_PADDING; - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; - GtkRequisition requisition; - - gtk_widget_size_request (GTK_WIDGET (button->button_widget), &requisition); - - if (row_width + requisition.width + H_PADDING >= allocation->width - && rows [row_number] != NULL) { - row_number ++; - rows [row_number] = NULL; - row_width = H_PADDING; - } - - row_width += requisition.width + H_PADDING; - rows [row_number] = g_slist_append (rows [row_number], button->button_widget); - } - - row_last = row_number; - - /* 2. Layout the buttons. */ - - y = allocation->y + allocation->height - V_PADDING - 1; - for (i = row_last; i >= 0; i --) { - int row_height = 0; - - for (p = rows [i]; p != NULL; p = p->next) { - GtkRequisition requisition; - - gtk_widget_size_request (GTK_WIDGET (p->data), &requisition); - row_height = MAX (row_height, requisition.height); - } - - y -= row_height; - x = H_PADDING; - for (p = rows [i]; p != NULL; p = p->next) { - GtkRequisition requisition; - GtkAllocation child_allocation; - - gtk_widget_size_request (GTK_WIDGET (p->data), &requisition); - - child_allocation.x = x; - child_allocation.y = y; - child_allocation.width = requisition.width; - child_allocation.height = requisition.height; - - gtk_widget_size_allocate (GTK_WIDGET (p->data), &child_allocation); - - x += requisition.width + H_PADDING; - } - - y -= V_PADDING; - } - - /* 3. Free stuff */ - for (i = 0; i <= row_last; i ++) g_slist_free (rows [i]); + g_free (rows); return y; } @@ -328,17 +261,7 @@ do_layout (ESidebar *sidebar) GtkAllocation child_allocation; int y; - switch (sidebar->priv->mode) { - case E_SIDEBAR_MODE_TEXT: - y = do_layout_text_buttons (sidebar); - break; - case E_SIDEBAR_MODE_ICON: - y = do_layout_icon_buttons (sidebar); - break; - default: - g_assert_not_reached (); - return; - } + y = layout_buttons (sidebar); /* Place the selection widget. */ child_allocation.x = allocation->x; @@ -546,11 +469,11 @@ e_sidebar_add_button (ESidebar *sidebar, icon_widget = gtk_image_new_from_pixbuf (icon); label_widget = gtk_label_new (label); gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), icon_widget, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), icon_widget, sidebar->priv->mode == E_SIDEBAR_MODE_ICON, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), label_widget, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (button_widget), hbox); - sidebar->priv->buttons = g_slist_append (sidebar->priv->buttons, button_new (button_widget, label_widget, hbox, id)); + sidebar->priv->buttons = g_slist_append (sidebar->priv->buttons, button_new (button_widget, label_widget, icon_widget, hbox, id)); gtk_widget_set_parent (button_widget, GTK_WIDGET (sidebar)); if (sidebar->priv->mode == E_SIDEBAR_MODE_ICON) @@ -587,10 +510,16 @@ e_sidebar_set_mode (ESidebar *sidebar, ESidebarMode mode) switch (mode) { case E_SIDEBAR_MODE_TEXT: - gtk_box_pack_start (GTK_BOX (button->hbox), button->label_widget, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (button->hbox), button->label, TRUE, TRUE, 0); + gtk_container_child_set (GTK_CONTAINER (button->hbox), button->icon, + "expand", FALSE, + NULL); break; case E_SIDEBAR_MODE_ICON: - gtk_container_remove (GTK_CONTAINER (button->hbox), button->label_widget); + gtk_container_remove (GTK_CONTAINER (button->hbox), button->label); + gtk_container_child_set (GTK_CONTAINER (button->hbox), button->icon, + "expand", TRUE, + NULL); break; default: g_assert_not_reached (); |