aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2012-10-31 21:14:04 +0800
committerMilan Crha <mcrha@redhat.com>2012-10-31 21:15:04 +0800
commit9e64b59c9d838b3d0a55b0eb95fc088ec26f1644 (patch)
tree2206d19bb22928b54628a6d5ef6c05c89b90856c
parent6225b7f61ef8d46d17e6359802f85ee1b8cbce4d (diff)
downloadgsoc2013-evolution-9e64b59c9d838b3d0a55b0eb95fc088ec26f1644.tar.gz
gsoc2013-evolution-9e64b59c9d838b3d0a55b0eb95fc088ec26f1644.tar.zst
gsoc2013-evolution-9e64b59c9d838b3d0a55b0eb95fc088ec26f1644.zip
Bug #422273 - Wrap searchbar widgets for smaller minimum width request
-rw-r--r--shell/e-shell-searchbar.c234
-rw-r--r--shell/e-shell-searchbar.h4
-rw-r--r--shell/e-shell-sidebar.c6
-rw-r--r--shell/e-shell-view.c30
-rw-r--r--shell/e-shell-view.h1
5 files changed, 210 insertions, 65 deletions
diff --git a/shell/e-shell-searchbar.c b/shell/e-shell-searchbar.c
index 9d9ad5a0cb..b80b3e27cd 100644
--- a/shell/e-shell-searchbar.c
+++ b/shell/e-shell-searchbar.c
@@ -43,6 +43,9 @@
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_SHELL_SEARCHBAR, EShellSearchbarPrivate))
+/* spacing between "groups" on the search bar */
+#define COLUMN_SPACING 24
+
#define SEARCH_OPTION_ADVANCED (-1)
/* Default "state key file" group: [Search Bar] */
@@ -65,6 +68,10 @@ struct _EShellSearchbarPrivate {
GtkWidget *search_entry;
GtkWidget *scope_combo_box;
+ /* Child widget containers (referenced) */
+ GSList *child_containers;
+ guint resize_idle_id;
+
/* State Key File */
gchar *state_group;
@@ -95,7 +102,7 @@ enum {
G_DEFINE_TYPE_WITH_CODE (
EShellSearchbar,
e_shell_searchbar,
- GTK_TYPE_BOX,
+ GTK_TYPE_GRID,
G_IMPLEMENT_INTERFACE (
E_TYPE_EXTENSIBLE, NULL))
@@ -461,6 +468,105 @@ shell_searchbar_option_changed_cb (GtkRadioAction *action,
e_shell_searchbar_set_search_text (searchbar, NULL);
}
+static gboolean
+shell_searchbar_resize_idle_cb (gpointer user_data)
+{
+ GtkWidget *widget;
+ EShellSearchbar *searchbar;
+ GSList *iter, *widths = NULL, *witer;
+ gint row, column, roww, maxw, child_left, child_top, allocated_width;
+ gboolean needs_reposition = FALSE;
+
+ widget = user_data;
+ searchbar = E_SHELL_SEARCHBAR (widget);
+ allocated_width = gtk_widget_get_allocated_width (widget);
+
+ row = 0;
+ column = 0;
+ roww = 0;
+ maxw = 0;
+
+ for (iter = searchbar->priv->child_containers; iter != NULL; iter = iter->next) {
+ GtkWidget *child = iter->data;
+ gint minw = -1;
+
+ if (!gtk_widget_get_visible (child))
+ minw = 0;
+ else
+ gtk_widget_get_preferred_width (child, &minw, NULL);
+
+ widths = g_slist_append (widths, GINT_TO_POINTER (minw));
+
+ if (roww && minw) {
+ roww += COLUMN_SPACING;
+ column++;
+ }
+
+ roww += minw;
+
+ if (minw > maxw)
+ maxw = minw;
+
+ if (roww > allocated_width) {
+ row++;
+ roww = minw;
+ column = 0;
+ }
+
+ gtk_container_child_get (GTK_CONTAINER (widget), child,
+ "left-attach", &child_left,
+ "top-attach", &child_top,
+ NULL);
+
+ needs_reposition = needs_reposition || child_left != column || child_top != row;
+
+ if (column == 0 && row > 0 && roww < maxw) {
+ /* columns has same width, thus use the wider widget for calculations*/
+ roww = maxw;
+ }
+ }
+
+ if (needs_reposition) {
+ row = 0;
+ column = 0;
+ roww = 0;
+
+ for (iter = searchbar->priv->child_containers; iter; iter = iter->next) {
+ gtk_container_remove (GTK_CONTAINER (widget), iter->data);
+ }
+
+ for (witer = widths, iter = searchbar->priv->child_containers; witer && iter; witer = witer->next, iter = iter->next) {
+ GtkWidget *child = iter->data;
+ gint w = GPOINTER_TO_INT (witer->data);
+
+ if (roww && w) {
+ roww += COLUMN_SPACING;
+ column++;
+ }
+
+ roww += w;
+
+ if (roww > allocated_width) {
+ row++;
+ roww = w;
+ column = 0;
+ }
+
+ gtk_grid_attach (GTK_GRID (widget), child, column, row, 1, 1);
+
+ if (column == 0 && row > 0 && roww < maxw)
+ roww = maxw;
+ }
+ }
+
+ g_slist_free (widths);
+
+ searchbar->priv->resize_idle_id = 0;
+ g_object_unref (searchbar);
+
+ return FALSE;
+}
+
static void
shell_searchbar_set_shell_view (EShellSearchbar *searchbar,
EShellView *shell_view)
@@ -635,6 +741,16 @@ shell_searchbar_dispose (GObject *object)
priv = E_SHELL_SEARCHBAR_GET_PRIVATE (object);
+ if (priv->resize_idle_id) {
+ g_source_remove (priv->resize_idle_id);
+ priv->resize_idle_id = 0;
+ }
+
+ if (priv->child_containers) {
+ g_slist_free_full (priv->child_containers, g_object_unref);
+ priv->child_containers = NULL;
+ }
+
if (priv->shell_view != NULL) {
g_object_remove_weak_pointer (
G_OBJECT (priv->shell_view), &priv->shell_view);
@@ -664,14 +780,12 @@ shell_searchbar_constructed (GObject *object)
EShellView *shell_view;
EShellWindow *shell_window;
EShellSearchbar *searchbar;
- GtkSizeGroup *size_group;
GtkAction *action;
GtkWidget *widget;
searchbar = E_SHELL_SEARCHBAR (object);
shell_view = e_shell_searchbar_get_shell_view (searchbar);
shell_window = e_shell_view_get_shell_window (shell_view);
- size_group = e_shell_view_get_size_group (shell_view);
g_signal_connect (
shell_view, "clear-search",
@@ -732,9 +846,6 @@ shell_searchbar_constructed (GObject *object)
widget, "primary-icon-tooltip-text",
G_BINDING_SYNC_CREATE);
- widget = GTK_WIDGET (searchbar);
- gtk_size_group_add_widget (size_group, widget);
-
e_extensible_load_extensions (E_EXTENSIBLE (object));
/* Chain up to parent's constructed() method. */
@@ -754,6 +865,46 @@ shell_searchbar_map (GtkWidget *widget)
}
static void
+shell_searchbar_size_allocate (GtkWidget *widget,
+ GdkRectangle *allocation)
+{
+ EShellSearchbar *searchbar;
+
+ GTK_WIDGET_CLASS (e_shell_searchbar_parent_class)->size_allocate (widget, allocation);
+
+ searchbar = E_SHELL_SEARCHBAR (widget);
+
+ if (!searchbar->priv->resize_idle_id)
+ searchbar->priv->resize_idle_id = g_idle_add (shell_searchbar_resize_idle_cb, g_object_ref (searchbar));
+}
+
+static void
+shell_searchbar_get_preferred_width (GtkWidget *widget,
+ gint *minimum_width,
+ gint *natural_width)
+{
+ GList *children, *iter;
+ gint max_minimum = 0, max_natural = 0;
+
+ children = gtk_container_get_children (GTK_CONTAINER (widget));
+ for (iter = children; iter != NULL; iter = iter->next) {
+ GtkWidget *child = iter->data;
+ gint minimum = 0, natural = 0;
+
+ if (gtk_widget_get_visible (child)) {
+ gtk_widget_get_preferred_width (child, &minimum, &natural);
+ if (minimum > max_minimum)
+ max_minimum = minimum;
+ if (natural > max_natural)
+ max_natural = natural;
+ }
+ }
+
+ *minimum_width = max_minimum + COLUMN_SPACING;
+ *natural_width = max_natural + COLUMN_SPACING;
+}
+
+static void
e_shell_searchbar_class_init (EShellSearchbarClass *class)
{
GObjectClass *object_class;
@@ -769,6 +920,8 @@ e_shell_searchbar_class_init (EShellSearchbarClass *class)
widget_class = GTK_WIDGET_CLASS (class);
widget_class->map = shell_searchbar_map;
+ widget_class->size_allocate = shell_searchbar_size_allocate;
+ widget_class->get_preferred_width = shell_searchbar_get_preferred_width;
g_object_class_install_property (
object_class,
@@ -911,34 +1064,43 @@ e_shell_searchbar_class_init (EShellSearchbarClass *class)
static void
e_shell_searchbar_init (EShellSearchbar *searchbar)
{
- GtkBox *box;
+ GtkGrid *grid;
GtkLabel *label;
GtkWidget *widget;
searchbar->priv = E_SHELL_SEARCHBAR_GET_PRIVATE (searchbar);
+ searchbar->priv->child_containers = NULL;
- gtk_box_set_spacing (GTK_BOX (searchbar), 24);
+ gtk_grid_set_column_spacing (GTK_GRID (searchbar), COLUMN_SPACING);
+ gtk_grid_set_row_spacing (GTK_GRID (searchbar), 4);
/* Filter Combo Widgets */
- box = GTK_BOX (searchbar);
+ grid = GTK_GRID (searchbar);
- widget = gtk_hbox_new (FALSE, 3);
- gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
+ widget = gtk_grid_new ();
+ g_object_set (G_OBJECT (widget),
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ "column-spacing", 3,
+ "valign", GTK_ALIGN_CENTER,
+ NULL);
+ gtk_grid_attach (grid, widget, 0, 0, 1, 1);
+ searchbar->priv->child_containers = g_slist_append (
+ searchbar->priv->child_containers, g_object_ref (widget));
g_object_bind_property (
searchbar, "filter-visible",
widget, "visible",
G_BINDING_SYNC_CREATE);
- box = GTK_BOX (widget);
+ grid = GTK_GRID (widget);
/* Translators: The "Show:" label precedes a combo box that
* allows the user to filter the current view. Examples of
* items that appear in the combo box are "Unread Messages",
* "Important Messages", or "Active Appointments". */
widget = gtk_label_new_with_mnemonic (_("Sho_w:"));
- gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
+ gtk_grid_attach (grid, widget, 0, 0, 1, 1);
gtk_widget_show (widget);
g_object_bind_property (
@@ -950,28 +1112,37 @@ e_shell_searchbar_init (EShellSearchbar *searchbar)
widget = e_action_combo_box_new ();
gtk_label_set_mnemonic_widget (label, widget);
- gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
+ gtk_grid_attach (grid, widget, 1, 0, 1, 1);
searchbar->priv->filter_combo_box = widget;
gtk_widget_show (widget);
/* Search Entry Widgets */
- box = GTK_BOX (searchbar);
+ grid = GTK_GRID (searchbar);
- widget = gtk_hbox_new (FALSE, 3);
- gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
+ widget = gtk_grid_new ();
+ g_object_set (G_OBJECT (widget),
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ "column-spacing", 3,
+ "valign", GTK_ALIGN_CENTER,
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ NULL);
+ gtk_grid_attach (grid, widget, 1, 0, 1, 1);
+ searchbar->priv->child_containers = g_slist_append (
+ searchbar->priv->child_containers, g_object_ref (widget));
g_object_bind_property (
searchbar, "search-visible",
widget, "visible",
G_BINDING_SYNC_CREATE);
- box = GTK_BOX (widget);
+ grid = GTK_GRID (widget);
/* Translators: This is part of the quick search interface.
* example: Search: [_______________] in [ Current Folder ] */
widget = gtk_label_new_with_mnemonic (_("Sear_ch:"));
- gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
+ gtk_grid_attach (grid, widget, 0, 0, 1, 1);
gtk_widget_show (widget);
g_object_bind_property (
@@ -983,7 +1154,11 @@ e_shell_searchbar_init (EShellSearchbar *searchbar)
widget = gtk_entry_new ();
gtk_label_set_mnemonic_widget (label, widget);
- gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
+ g_object_set (G_OBJECT (widget),
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ NULL);
+ gtk_grid_attach (grid, widget, 1, 0, 1, 1);
searchbar->priv->search_entry = widget;
gtk_widget_show (widget);
@@ -1019,29 +1194,36 @@ e_shell_searchbar_init (EShellSearchbar *searchbar)
/* Scope Combo Widgets */
- box = GTK_BOX (searchbar);
+ grid = GTK_GRID (searchbar);
- widget = gtk_hbox_new (FALSE, 3);
- gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
+ widget = gtk_grid_new ();
+ g_object_set (G_OBJECT (widget),
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ "column-spacing", 3,
+ "valign", GTK_ALIGN_CENTER,
+ NULL);
+ gtk_grid_attach (grid, widget, 2, 0, 1, 1);
+ searchbar->priv->child_containers = g_slist_append (
+ searchbar->priv->child_containers, g_object_ref (widget));
g_object_bind_property (
searchbar, "scope-visible",
widget, "visible",
G_BINDING_SYNC_CREATE);
- box = GTK_BOX (widget);
+ grid = GTK_GRID (widget);
/* Translators: This is part of the quick search interface.
* example: Search: [_______________] in [ Current Folder ] */
widget = gtk_label_new_with_mnemonic (_("i_n"));
- gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
+ gtk_grid_attach (grid, widget, 0, 0, 1, 1);
gtk_widget_show (widget);
label = GTK_LABEL (widget);
widget = e_action_combo_box_new ();
gtk_label_set_mnemonic_widget (label, widget);
- gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
+ gtk_grid_attach (grid, widget, 1, 0, 1, 1);
searchbar->priv->scope_combo_box = widget;
gtk_widget_show (widget);
diff --git a/shell/e-shell-searchbar.h b/shell/e-shell-searchbar.h
index a9e73c9f02..6c68e72d80 100644
--- a/shell/e-shell-searchbar.h
+++ b/shell/e-shell-searchbar.h
@@ -58,12 +58,12 @@ typedef struct _EShellSearchbarPrivate EShellSearchbarPrivate;
* functions below.
**/
struct _EShellSearchbar {
- GtkBox parent;
+ GtkGrid parent;
EShellSearchbarPrivate *priv;
};
struct _EShellSearchbarClass {
- GtkBoxClass parent_class;
+ GtkGridClass parent_class;
};
GType e_shell_searchbar_get_type (void);
diff --git a/shell/e-shell-sidebar.c b/shell/e-shell-sidebar.c
index 362321069a..95afe576b4 100644
--- a/shell/e-shell-sidebar.c
+++ b/shell/e-shell-sidebar.c
@@ -203,20 +203,14 @@ shell_sidebar_constructed (GObject *object)
{
EShellView *shell_view;
EShellSidebar *shell_sidebar;
- GtkSizeGroup *size_group;
GtkAction *action;
- GtkWidget *widget;
gchar *label;
gchar *icon_name;
shell_sidebar = E_SHELL_SIDEBAR (object);
shell_view = e_shell_sidebar_get_shell_view (shell_sidebar);
- size_group = e_shell_view_get_size_group (shell_view);
action = e_shell_view_get_action (shell_view);
- widget = shell_sidebar->priv->event_box;
- gtk_size_group_add_widget (size_group, widget);
-
g_object_get (action, "icon-name", &icon_name, NULL);
e_shell_sidebar_set_icon_name (shell_sidebar, icon_name);
g_free (icon_name);
diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c
index 1e7e27b87b..90fdbc852e 100644
--- a/shell/e-shell-view.c
+++ b/shell/e-shell-view.c
@@ -67,7 +67,6 @@ struct _EShellViewPrivate {
guint merge_id;
GtkAction *action;
- GtkSizeGroup *size_group;
GtkWidget *shell_content;
GtkWidget *shell_sidebar;
GtkWidget *shell_taskbar;
@@ -622,10 +621,6 @@ shell_view_constructed (GObject *object)
shell_view->priv->searchbar = g_object_ref_sink (widget);
}
- /* Size group should be safe to unreference now. */
- g_object_unref (shell_view->priv->size_group);
- shell_view->priv->size_group = NULL;
-
/* Update actions whenever the Preferences window is closed. */
widget = e_shell_get_preferences_window (shell);
shell_view->priv->preferences_window = g_object_ref (widget);
@@ -1102,8 +1097,6 @@ static void
e_shell_view_init (EShellView *shell_view,
EShellViewClass *class)
{
- GtkSizeGroup *size_group;
-
/* XXX Our use of GInstanceInitFunc's 'class' parameter
* prevents us from using G_DEFINE_ABSTRACT_TYPE. */
@@ -1113,11 +1106,8 @@ e_shell_view_init (EShellView *shell_view,
if (class->view_collection == NULL)
shell_view_init_view_collection (class);
- size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
-
shell_view->priv = E_SHELL_VIEW_GET_PRIVATE (shell_view);
shell_view->priv->state_key_file = g_key_file_new ();
- shell_view->priv->size_group = size_group;
}
GType
@@ -1488,26 +1478,6 @@ e_shell_view_get_search_query (EShellView *shell_view)
}
/**
- * e_shell_view_get_size_group:
- * @shell_view: an #EShellView
- *
- * Returns a #GtkSizeGroup that #EShellContent and #EShellSidebar use
- * to keep the search bar and sidebar banner vertically aligned. The
- * rest of the application should have no need for this.
- *
- * Note, this is only available during #EShellView construction.
- *
- * Returns: a #GtkSizeGroup for internal use
- **/
-GtkSizeGroup *
-e_shell_view_get_size_group (EShellView *shell_view)
-{
- g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
-
- return shell_view->priv->size_group;
-}
-
-/**
* e_shell_view_get_shell_backend:
* @shell_view: an #EShellView
*
diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h
index 84b3c69314..736af40b6a 100644
--- a/shell/e-shell-view.h
+++ b/shell/e-shell-view.h
@@ -201,7 +201,6 @@ EFilterRule * e_shell_view_get_search_rule (EShellView *shell_view);
void e_shell_view_set_search_rule (EShellView *shell_view,
EFilterRule *search_rule);
gchar * e_shell_view_get_search_query (EShellView *shell_view);
-GtkSizeGroup * e_shell_view_get_size_group (EShellView *shell_view);
EShellBackend * e_shell_view_get_shell_backend (EShellView *shell_view);
EShellContent * e_shell_view_get_shell_content (EShellView *shell_view);
EShellSidebar * e_shell_view_get_shell_sidebar (EShellView *shell_view);