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



commit 96ae0925648f228d573b71dd6d566ac7e333cca6
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, but with bug fixes.
    
    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]