[gtksourceview/wip/fix-completion-sizing-2] CompletionContainer sizing fixes
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/fix-completion-sizing-2] CompletionContainer sizing fixes
- Date: Mon, 2 Jun 2014 17:48:10 +0000 (UTC)
commit b37c7dbbb00c7c9e710c5a4b0ee7d4a9eb38830d
Author: Sébastien Wilmet <swilmet gnome org>
Date: Mon Jun 2 19:31:23 2014 +0200
CompletionContainer sizing fixes
The previous implementation subclassed GtkBin and added/removed the
scrolled window during the size requisition, which is probably one of
the problem. Now the CompletionContainer is a subclass of
GtkScrolledWindow, so the scrolled window is always there, with an
automatic policy.
Another source of bug is that the code to know whether a
scrollbar is needed was buggy and not consistent between
get_preferred_width() and get_preferred_height(). It should now be
fixed.
https://bugzilla.gnome.org/show_bug.cgi?id=720823
gtksourceview/gtksourcecompletioncontainer.c | 233 +++++++-------------------
gtksourceview/gtksourcecompletioncontainer.h | 7 +-
2 files changed, 65 insertions(+), 175 deletions(-)
---
diff --git a/gtksourceview/gtksourcecompletioncontainer.c b/gtksourceview/gtksourcecompletioncontainer.c
index 2a305f8..8a81442 100644
--- a/gtksourceview/gtksourcecompletioncontainer.c
+++ b/gtksourceview/gtksourcecompletioncontainer.c
@@ -2,7 +2,7 @@
/* gtksourcecompletioncontainer.c
* This file is part of GtkSourceView
*
- * Copyright (C) 2013 - Sébastien Wilmet <swilmet gnome org>
+ * Copyright (C) 2013, 2014 - Sébastien Wilmet <swilmet gnome org>
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,14 +20,11 @@
*/
/*
- * Custom container for the sizing of the GtkTreeView containing the completion
- * proposals. When the GtkTreeView exceeds a certain size, the container adds
- * the GtkTreeView inside a scrolled window. When the GtkTreeView is small
- * enough, no scrolled window is needed, and the container fits the natural size
- * of the GtkTreeView.
- *
- * If the tree view is always in the scrolled window, there are sometimes some
- * sizing issues.
+ * Custom sizing of the scrolled window containing the GtkTreeView containing
+ * the completion proposals. If the GtkTreeView is small enough, the scrolled
+ * window returns the natural size of the GtkTreeView. If it exceeds a certain
+ * size, the scrolled window returns a smaller size, with the height at a row
+ * boundary of the GtkTreeView (plus the size of the scrollbar(s) if needed).
*
* The purpose is to have a compact completion window, with a certain size
* limit.
@@ -38,13 +35,9 @@
#define UNREALIZED_WIDTH 350
#define MAX_HEIGHT 180
-struct _GtkSourceCompletionContainerPrivate
-{
- GtkTreeView *tree_view;
- GtkWidget *scrolled_window;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceCompletionContainer, _gtk_source_completion_container, GTK_TYPE_BIN);
+G_DEFINE_TYPE (GtkSourceCompletionContainer,
+ _gtk_source_completion_container,
+ GTK_TYPE_SCROLLED_WINDOW);
static gint
get_max_width (GtkSourceCompletionContainer *container)
@@ -70,14 +63,6 @@ get_max_width (GtkSourceCompletionContainer *container)
return UNREALIZED_WIDTH;
}
-/* gtk_container_add() is overridden. This function calls the GtkBin's add(). */
-static void
-bin_container_add (GtkContainer *container,
- GtkWidget *widget)
-{
- GTK_CONTAINER_CLASS (_gtk_source_completion_container_parent_class)->add (container, widget);
-}
-
static gint
get_vertical_scrollbar_width (void)
{
@@ -89,7 +74,6 @@ get_vertical_scrollbar_width (void)
gtk_widget_get_preferred_width (scrollbar, NULL, &width);
g_object_unref (scrollbar);
-
return width;
}
@@ -104,95 +88,61 @@ get_horizontal_scrollbar_height (void)
gtk_widget_get_preferred_height (scrollbar, NULL, &height);
g_object_unref (scrollbar);
-
return height;
}
-static void
-remove_scrolled_window (GtkSourceCompletionContainer *container)
+/* 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 child_natural_height)
{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (container->priv->tree_view));
-
- if (parent != GTK_WIDGET (container))
- {
- gtk_container_remove (GTK_CONTAINER (container),
- container->priv->scrolled_window);
-
- gtk_container_remove (GTK_CONTAINER (container->priv->scrolled_window),
- GTK_WIDGET (container->priv->tree_view));
-
- bin_container_add (GTK_CONTAINER (container),
- GTK_WIDGET (container->priv->tree_view));
- }
+ return MAX_HEIGHT < child_natural_height;
}
static void
-add_scrolled_window (GtkSourceCompletionContainer *container)
+get_width (GtkSourceCompletionContainer *container,
+ gint *container_width,
+ gint *child_available_width)
{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (container->priv->tree_view));
+ GtkWidget *child;
+ GtkRequisition nat_size;
+ gint width;
+ gint scrollbar_width = 0;
- if (parent != container->priv->scrolled_window)
- {
- gtk_container_remove (GTK_CONTAINER (container),
- GTK_WIDGET (container->priv->tree_view));
+ child = gtk_bin_get_child (GTK_BIN (container));
+ gtk_widget_get_preferred_size (child, NULL, &nat_size);
- gtk_container_add (GTK_CONTAINER (container->priv->scrolled_window),
- GTK_WIDGET (container->priv->tree_view));
+ width = nat_size.width;
- bin_container_add (GTK_CONTAINER (container),
- container->priv->scrolled_window);
+ if (needs_vertical_scrollbar (nat_size.height))
+ {
+ scrollbar_width = get_vertical_scrollbar_width ();
+ width += scrollbar_width;
}
-}
-static void
-check_scrolled_window (GtkSourceCompletionContainer *container,
- GtkRequisition child_size)
-{
- if (child_size.width <= get_max_width (container) &&
- child_size.height <= MAX_HEIGHT)
+ width = MIN (width, get_max_width (container));
+
+ if (container_width != NULL)
{
- remove_scrolled_window (container);
+ *container_width = width;
}
- else
+
+ if (child_available_width != NULL)
{
- add_scrolled_window (container);
+ *child_available_width = width - scrollbar_width;
}
}
-static GtkSizeRequestMode
-_gtk_source_completion_container_get_request_mode (GtkWidget *widget)
-{
- return GTK_SIZE_REQUEST_CONSTANT_SIZE;
-}
-
static void
_gtk_source_completion_container_get_preferred_width (GtkWidget *widget,
gint *min_width,
gint *nat_width)
{
GtkSourceCompletionContainer *container = GTK_SOURCE_COMPLETION_CONTAINER (widget);
- GtkRequisition nat_size;
gint width;
- /* FIXME sometimes the returned height (nat_size.height) is 0. Maybe a
- * bug in GtkTreeView. If there are sizing problems, or if there are
- * problems with the scrolled window, a workaround would be to compute
- * the height manually, like it is done in get_preferred_height() below.
- */
- gtk_widget_get_preferred_size (GTK_WIDGET (container->priv->tree_view),
- NULL,
- &nat_size);
-
- check_scrolled_window (container, nat_size);
-
- width = nat_size.width;
-
- if (MAX_HEIGHT < nat_size.height)
- {
- width += get_vertical_scrollbar_width ();
- }
-
- width = MIN (width, get_max_width (container));
+ get_width (container, &width, NULL);
if (min_width != NULL)
{
@@ -208,11 +158,15 @@ _gtk_source_completion_container_get_preferred_width (GtkWidget *widget,
static gint
get_row_height (GtkSourceCompletionContainer *container)
{
- GList *columns = gtk_tree_view_get_columns (container->priv->tree_view);
+ GtkWidget *tree_view;
+ GList *columns;
GList *l;
gint max_row_height = 0;
gint vertical_separator = 0;
+ tree_view = gtk_bin_get_child (GTK_BIN (container));
+ columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree_view));
+
for (l = columns; l != NULL; l = l->next)
{
GtkTreeViewColumn *column = l->data;
@@ -226,14 +180,13 @@ get_row_height (GtkSourceCompletionContainer *container)
}
}
- gtk_widget_style_get (GTK_WIDGET (container->priv->tree_view),
+ gtk_widget_style_get (tree_view,
"vertical-separator", &vertical_separator,
NULL);
max_row_height += vertical_separator;
g_list_free (columns);
-
return max_row_height;
}
@@ -244,59 +197,37 @@ _gtk_source_completion_container_get_preferred_height (GtkWidget *widget,
gint *nat_height)
{
GtkSourceCompletionContainer *container = GTK_SOURCE_COMPLETION_CONTAINER (widget);
- GtkTreeModel *model;
+ GtkWidget *child;
GtkRequisition nat_size;
- gint nb_rows = 0;
- gint row_height = 0;
+ gint total_height;
gint scrollbar_height = 0;
- gint total_height = 0;
- gint ret_height = 0;
-
- if (min_height != NULL)
- {
- *min_height = 0;
- }
-
- if (nat_height != NULL)
- {
- *nat_height = 0;
- }
-
- model = gtk_tree_view_get_model (container->priv->tree_view);
-
- if (model == NULL)
- {
- return;
- }
+ gint child_available_width;
+ gint ret_height;
- row_height = get_row_height (container);
+ child = gtk_bin_get_child (GTK_BIN (container));
+ gtk_widget_get_preferred_size (child, NULL, &nat_size);
- nb_rows = gtk_tree_model_iter_n_children (model, NULL);
+ total_height = nat_size.height;
- total_height = nb_rows * row_height;
+ get_width (container, NULL, &child_available_width);
- gtk_widget_get_preferred_size (GTK_WIDGET (container->priv->tree_view),
- NULL,
- &nat_size);
-
- check_scrolled_window (container, nat_size);
-
- if (get_max_width (container) < nat_size.width)
+ /* Needs horizontal scrollbar */
+ if (child_available_width < nat_size.width)
{
scrollbar_height = get_horizontal_scrollbar_height ();
total_height += scrollbar_height;
}
- if (total_height <= MAX_HEIGHT)
+ if (needs_vertical_scrollbar (nat_size.height))
{
- ret_height = total_height;
+ gint row_height = get_row_height (container);
+ gint nb_rows_allowed = MAX_HEIGHT / row_height;
+
+ ret_height = nb_rows_allowed * row_height + scrollbar_height;
}
else
{
- gint height_available_for_rows = MAX_HEIGHT - scrollbar_height;
- gint nb_rows_allowed = height_available_for_rows / row_height;
-
- ret_height = nb_rows_allowed * row_height + scrollbar_height;
+ ret_height = total_height;
}
if (min_height != NULL)
@@ -311,55 +242,17 @@ _gtk_source_completion_container_get_preferred_height (GtkWidget *widget,
}
static void
-_gtk_source_completion_container_add (GtkContainer *gtk_container,
- GtkWidget *widget)
-{
- GtkSourceCompletionContainer *container = GTK_SOURCE_COMPLETION_CONTAINER (gtk_container);
-
- g_return_if_fail (GTK_IS_TREE_VIEW (widget));
-
- g_clear_object (&container->priv->tree_view);
- container->priv->tree_view = GTK_TREE_VIEW (widget);
- g_object_ref (container->priv->tree_view);
-
- bin_container_add (gtk_container, widget);
-}
-
-static void
-_gtk_source_completion_container_init (GtkSourceCompletionContainer *container)
-{
- container->priv = _gtk_source_completion_container_get_instance_private (container);
-
- container->priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- g_object_ref_sink (container->priv->scrolled_window);
- gtk_widget_show (container->priv->scrolled_window);
-}
-
-static void
-_gtk_source_completion_container_finalize (GObject *object)
-{
- GtkSourceCompletionContainer *container = GTK_SOURCE_COMPLETION_CONTAINER (object);
-
- g_clear_object (&container->priv->scrolled_window);
- g_clear_object (&container->priv->tree_view);
-
- G_OBJECT_CLASS (_gtk_source_completion_container_parent_class)->finalize (object);
-}
-
-static void
_gtk_source_completion_container_class_init (GtkSourceCompletionContainerClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
- object_class->finalize = _gtk_source_completion_container_finalize;
-
- widget_class->get_request_mode = _gtk_source_completion_container_get_request_mode;
widget_class->get_preferred_width = _gtk_source_completion_container_get_preferred_width;
widget_class->get_preferred_height = _gtk_source_completion_container_get_preferred_height;
+}
- container_class->add = _gtk_source_completion_container_add;
+static void
+_gtk_source_completion_container_init (GtkSourceCompletionContainer *container)
+{
}
GtkSourceCompletionContainer *
diff --git a/gtksourceview/gtksourcecompletioncontainer.h b/gtksourceview/gtksourcecompletioncontainer.h
index 5e44ae1..2c26fa5 100644
--- a/gtksourceview/gtksourcecompletioncontainer.h
+++ b/gtksourceview/gtksourcecompletioncontainer.h
@@ -34,19 +34,16 @@ G_BEGIN_DECLS
#define GTK_SOURCE_IS_COMPLETION_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GTK_SOURCE_TYPE_COMPLETION_CONTAINER))
#define GTK_SOURCE_COMPLETION_CONTAINER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GTK_SOURCE_TYPE_COMPLETION_CONTAINER, GtkSourceCompletionContainerClass))
-typedef struct _GtkSourceCompletionContainerPrivate GtkSourceCompletionContainerPrivate;
typedef struct _GtkSourceCompletionContainerClass GtkSourceCompletionContainerClass;
struct _GtkSourceCompletionContainer
{
- GtkBin parent;
-
- GtkSourceCompletionContainerPrivate *priv;
+ GtkScrolledWindow parent;
};
struct _GtkSourceCompletionContainerClass
{
- GtkBinClass parent_class;
+ GtkScrolledWindowClass parent_class;
};
G_GNUC_INTERNAL
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]