[gtksourceview/wip/fix-completion-sizing: 2/2] completion sizing: better implementation



commit e2e68932b34b70a0e8b5a68e608128977e13429a
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Sun Jun 1 01:26:08 2014 +0200

    completion sizing: better implementation
    
    On each "size-allocate" signal on the GtkTreeView, resize the scrolled
    window. The functions to calculate the size is more or less the same as
    the previous implementation in the custom container, with a bug fix.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=720823

 gtksourceview/gtksourcecompletion.c |  178 ++++++++++++++++++++++++++++++++++-
 1 files changed, 177 insertions(+), 1 deletions(-)
---
diff --git a/gtksourceview/gtksourcecompletion.c b/gtksourceview/gtksourcecompletion.c
index 17d80bc..1f645b1 100644
--- a/gtksourceview/gtksourcecompletion.c
+++ b/gtksourceview/gtksourcecompletion.c
@@ -91,6 +91,9 @@
 #include "gtksourceview-marshal.h"
 #include "gtksourceview-i18n.h"
 
+#define MAX_WIDTH  350
+#define MAX_HEIGHT 180
+
 /* Signals */
 enum
 {
@@ -141,8 +144,8 @@ struct _GtkSourceCompletionPrivate
        GtkToggleButton *info_button;
 
        /* List of proposals */
+       GtkScrolledWindow *scrolled_window;
        GtkTreeView *tree_view_proposals;
-
        GtkCellRenderer *cell_renderer_proposal;
 
        /* Completion management */
@@ -591,6 +594,176 @@ gtk_source_completion_hide_default (GtkSourceCompletion *completion)
        gtk_widget_hide (GTK_WIDGET (completion->priv->main_window));
 }
 
+static gint
+get_max_width (GtkSourceCompletion *completion)
+{
+       if (gtk_widget_get_realized (GTK_WIDGET (completion->priv->main_window)))
+       {
+               GdkWindow *window;
+               GdkScreen *screen;
+               gint max_width;
+               gint xorigin;
+
+               window = gtk_widget_get_window (GTK_WIDGET (completion->priv->main_window));
+               screen = gdk_window_get_screen (window);
+
+               gdk_window_get_origin (window, &xorigin, NULL);
+               max_width = gdk_screen_get_width (screen) - xorigin;
+
+               return MAX (max_width, MAX_WIDTH);
+       }
+
+       return MAX_WIDTH;
+}
+
+static gint
+get_vertical_scrollbar_width (void)
+{
+       gint width;
+       GtkWidget *scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, NULL);
+       g_object_ref_sink (scrollbar);
+       gtk_widget_show (scrollbar);
+
+       gtk_widget_get_preferred_width (scrollbar, NULL, &width);
+
+       g_object_unref (scrollbar);
+       return width;
+}
+
+static gint
+get_horizontal_scrollbar_height (void)
+{
+       gint height;
+       GtkWidget *scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, NULL);
+       g_object_ref_sink (scrollbar);
+       gtk_widget_show (scrollbar);
+
+       gtk_widget_get_preferred_height (scrollbar, NULL, &height);
+
+       g_object_unref (scrollbar);
+       return height;
+}
+
+/* This condition is used at several places, and it is important that it is the
+ * same condition. So a function is better.
+ */
+static gboolean
+needs_vertical_scrollbar (gint tree_view_height)
+{
+       return MAX_HEIGHT < tree_view_height;
+}
+
+static void
+get_scrolled_window_width (GtkSourceCompletion *completion,
+                          gint                 tree_view_width,
+                          gint                 tree_view_height,
+                          gint                *scrolled_window_width,
+                          gint                *tree_view_available_width)
+{
+       gint width = tree_view_width;
+       gint scrollbar_width = 0;
+
+       g_assert (scrolled_window_width != NULL);
+       g_assert (tree_view_available_width != NULL);
+
+       if (needs_vertical_scrollbar (tree_view_height))
+       {
+               scrollbar_width = get_vertical_scrollbar_width ();
+               width += scrollbar_width;
+       }
+
+       width = MIN (width, get_max_width (completion));
+
+       *scrolled_window_width = width;
+       *tree_view_available_width = width - scrollbar_width;
+}
+
+static gint
+get_row_height (GtkSourceCompletion *completion)
+{
+       GList *columns = gtk_tree_view_get_columns (completion->priv->tree_view_proposals);
+       GList *l;
+       gint max_row_height = 0;
+       gint vertical_separator = 0;
+
+       for (l = columns; l != NULL; l = l->next)
+       {
+               GtkTreeViewColumn *column = l->data;
+               gint row_height;
+
+               gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, NULL, &row_height);
+
+               if (row_height > max_row_height)
+               {
+                       max_row_height = row_height;
+               }
+       }
+
+       gtk_widget_style_get (GTK_WIDGET (completion->priv->tree_view_proposals),
+                             "vertical-separator", &vertical_separator,
+                             NULL);
+
+       max_row_height += vertical_separator;
+
+       g_list_free (columns);
+       return max_row_height;
+}
+
+/* Returns a height at a row boundary of the GtkTreeView. */
+static gint
+get_scrolled_window_height (GtkSourceCompletion *completion,
+                           gint                 tree_view_width,
+                           gint                 tree_view_height,
+                           gint                 tree_view_available_width)
+{
+       gint total_height = tree_view_height;
+       gint scrollbar_height = 0;
+
+       if (tree_view_available_width < tree_view_width)
+       {
+               scrollbar_height = get_horizontal_scrollbar_height ();
+               total_height += scrollbar_height;
+       }
+
+       if (needs_vertical_scrollbar (tree_view_height))
+       {
+               gint row_height = get_row_height (completion);
+               gint nb_rows_allowed = MAX_HEIGHT / row_height;
+
+               return nb_rows_allowed * row_height + scrollbar_height;
+       }
+
+       return total_height;
+}
+
+static void
+resize_scrolled_window (GtkSourceCompletion *completion)
+{
+       GtkRequisition nat_size;
+       gint scrolled_window_width = 0;
+       gint scrolled_window_height = 0;
+       gint tree_view_available_width = 0;
+
+       gtk_widget_get_preferred_size (GTK_WIDGET (completion->priv->tree_view_proposals),
+                                      NULL,
+                                      &nat_size);
+
+       get_scrolled_window_width (completion,
+                                  nat_size.width,
+                                  nat_size.height,
+                                  &scrolled_window_width,
+                                  &tree_view_available_width);
+
+       scrolled_window_height = get_scrolled_window_height (completion,
+                                                            nat_size.width,
+                                                            nat_size.height,
+                                                            tree_view_available_width);
+
+       gtk_widget_set_size_request (GTK_WIDGET (completion->priv->scrolled_window),
+                                    scrolled_window_width,
+                                    scrolled_window_height);
+}
+
 static void
 gtk_source_completion_proposals_size_allocate (GtkSourceCompletion *completion,
                                               GtkAllocation       *allocation,
@@ -635,6 +808,8 @@ gtk_source_completion_proposals_size_allocate (GtkSourceCompletion *completion,
                                          NULL);
 
        _gtk_source_completion_info_set_xoffset (completion->priv->main_window, -x_offset);
+
+       resize_scrolled_window (completion);
 }
 
 static void
@@ -1911,6 +2086,7 @@ init_tree_view (GtkSourceCompletion *completion,
        GdkRGBA background_color;
        GdkRGBA foreground_color;
 
+       completion->priv->scrolled_window = GTK_SCROLLED_WINDOW (gtk_builder_get_object (builder, 
"scrolled_window"));
        completion->priv->tree_view_proposals = GTK_TREE_VIEW (gtk_builder_get_object (builder, 
"tree_view_proposals"));
 
        g_signal_connect_swapped (completion->priv->tree_view_proposals,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]