[gtk+/wip/matthiasc/tab-strip] Improve scrolling
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/matthiasc/tab-strip] Improve scrolling
- Date: Thu, 26 May 2016 04:18:51 +0000 (UTC)
commit 2c944b7928758d5ad60240fa470ea3f848dde608
Author: Matthias Clasen <mclasen redhat com>
Date: Thu May 26 00:18:06 2016 -0400
Improve scrolling
Arrange for autoscroll and keyboard scrolling to end on a
tab boundary.
gtk/gtktabstrip.c | 171 +++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 134 insertions(+), 37 deletions(-)
---
diff --git a/gtk/gtktabstrip.c b/gtk/gtktabstrip.c
index e5da39c..b30d737 100644
--- a/gtk/gtktabstrip.c
+++ b/gtk/gtktabstrip.c
@@ -36,7 +36,6 @@
* TODO:
* - reordering
* - dnd
- * - improve scrolling: scroll by tabs for click/activation
*/
typedef struct
@@ -53,6 +52,8 @@ typedef struct
GtkWidget *end_scroll;
GtkScrollType autoscroll_mode;
guint autoscroll_id;
+ gboolean autoscroll_goal_set;
+ gdouble autoscroll_goal;
} GtkTabStripPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GtkTabStrip, gtk_tab_strip, GTK_TYPE_CONTAINER)
@@ -411,6 +412,17 @@ update_scrolling (GtkTabStrip *self)
hscroll, vscroll);
}
+static GtkAdjustment *
+gtk_tab_strip_get_scroll_adjustment (GtkTabStrip *self)
+{
+ GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+ if (gtk_tab_strip_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
+ return gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
+ else
+ return gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
+}
+
static gboolean
autoscroll_cb (GtkWidget *widget,
GdkFrameClock *frame_clock,
@@ -421,20 +433,41 @@ autoscroll_cb (GtkWidget *widget,
GtkAdjustment *adj;
gdouble value;
- if (gtk_tab_strip_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
- adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
- else
- adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
+ adj = gtk_tab_strip_get_scroll_adjustment (self);
value = gtk_adjustment_get_value (adj);
- if (priv->autoscroll_mode == GTK_SCROLL_STEP_FORWARD)
+
+ if (priv->autoscroll_goal_set && ABS (value - priv->autoscroll_goal) < 5)
+ value = priv->autoscroll_goal;
+ else if (priv->autoscroll_mode == GTK_SCROLL_STEP_FORWARD)
value += 5;
else
value -= 5;
gtk_adjustment_set_value (adj, value);
- return G_SOURCE_CONTINUE;
+ if (priv->autoscroll_goal_set && value == priv->autoscroll_goal)
+ {
+ priv->autoscroll_id = 0;
+ return G_SOURCE_REMOVE;
+ }
+ else
+ {
+ return G_SOURCE_CONTINUE;
+ }
+}
+
+static GtkScrollType
+autoscroll_mode_for_button (GtkTabStrip *self,
+ GtkWidget *button)
+{
+ GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+ if ((button == priv->start_scroll && !priv->reversed) ||
+ (button == priv->end_scroll && priv->reversed))
+ return GTK_SCROLL_STEP_BACKWARD;
+ else
+ return GTK_SCROLL_STEP_FORWARD;
}
static void
@@ -446,12 +479,8 @@ add_autoscroll (GtkTabStrip *self,
if (priv->autoscroll_id != 0)
return;
- if ((button == priv->start_scroll && !priv->reversed) ||
- (button == priv->end_scroll && priv->reversed))
- priv->autoscroll_mode = GTK_SCROLL_STEP_BACKWARD;
- else
- priv->autoscroll_mode = GTK_SCROLL_STEP_FORWARD;
-
+ priv->autoscroll_mode = autoscroll_mode_for_button (self, button);
+ priv->autoscroll_goal_set = FALSE;
priv->autoscroll_id = gtk_widget_add_tick_callback (GTK_WIDGET (self),
autoscroll_cb, self, NULL);
}
@@ -461,11 +490,87 @@ remove_autoscroll (GtkTabStrip *self)
{
GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
- if (priv->autoscroll_id)
+ if (priv->autoscroll_id == 0)
+ return;
+
+ gtk_widget_remove_tick_callback (GTK_WIDGET (self), priv->autoscroll_id);
+ priv->autoscroll_id = 0;
+}
+
+static gdouble
+find_autoscroll_goal (GtkTabStrip *self,
+ gboolean force_step,
+ GtkScrollType mode)
+{
+ GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+ GtkAdjustment *adj;
+ gdouble value;
+ gdouble goal;
+ GList *children, *l;
+
+ adj = gtk_tab_strip_get_scroll_adjustment (self);
+
+ if (mode == GTK_SCROLL_STEP_FORWARD)
+ value = gtk_adjustment_get_value (adj) + gtk_adjustment_get_page_size (adj);
+ else
+ value = gtk_adjustment_get_value (adj);
+
+ if (force_step)
{
- gtk_widget_remove_tick_callback (GTK_WIDGET (self), priv->autoscroll_id);
- priv->autoscroll_id = 0;
+ if (mode == GTK_SCROLL_STEP_FORWARD)
+ value += 5;
+ else
+ value -= 5;
+ value = CLAMP (value, gtk_adjustment_get_lower (adj), gtk_adjustment_get_upper (adj));
+ }
+
+ goal = 0;
+ children = gtk_container_get_children (GTK_CONTAINER (priv->tabs));
+ for (l = children; l; l = l->next)
+ {
+ GtkWidget *child = l->data;
+ GtkAllocation alloc;
+ gint start, end;
+
+ gtk_widget_get_allocation (child, &alloc);
+ if (gtk_tab_strip_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
+ {
+ start = alloc.x;
+ end = alloc.x + alloc.width;
+ }
+ else
+ {
+ start = alloc.y;
+ end = alloc.y + alloc.height;
+ }
+
+ if (start <= value && value <= end)
+ {
+ if (mode == GTK_SCROLL_STEP_FORWARD)
+ goal = end - gtk_adjustment_get_page_size (adj);
+ else
+ goal = start;
+ break;
+ }
}
+ g_list_free (children);
+
+ return goal;
+}
+
+static void
+finish_autoscroll (GtkTabStrip *self)
+{
+ GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+ gdouble goal;
+
+ if (priv->autoscroll_id == 0 || priv->autoscroll_goal_set)
+ return;
+
+ goal = find_autoscroll_goal (self, FALSE, priv->autoscroll_mode);
+
+ priv->autoscroll_goal = goal;
+ priv->autoscroll_goal_set = TRUE;
}
static gboolean
@@ -473,10 +578,13 @@ scroll_button_event (GtkWidget *button,
GdkEventButton *event,
GtkTabStrip *self)
{
- remove_autoscroll (self);
-
if (event->type == GDK_BUTTON_PRESS)
- add_autoscroll (self, button);
+ {
+ remove_autoscroll (self);
+ add_autoscroll (self, button);
+ }
+ else if (event->type == GDK_BUTTON_RELEASE)
+ finish_autoscroll (self);
return FALSE;
}
@@ -485,22 +593,15 @@ static void
scroll_button_activate (GtkWidget *button,
GtkTabStrip *self)
{
- GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
GtkAdjustment *adj;
- gdouble value;
+ gdouble goal;
+ GtkScrollType mode;
- if (gtk_tab_strip_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
- adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
- else
- adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
- value = gtk_adjustment_get_value (adj);
-
- if (priv->start_scroll == button)
- value -= 20;
- else
- value += 20;
+ mode = autoscroll_mode_for_button (self, button);
+ goal = find_autoscroll_goal (self, TRUE, mode);
- gtk_adjustment_animate_to_value (adj, value);
+ adj = gtk_tab_strip_get_scroll_adjustment (self);
+ gtk_adjustment_animate_to_value (adj, goal);
}
static void
@@ -511,11 +612,7 @@ adjustment_changed (GtkTabStrip *self)
gdouble value;
gboolean at_lower, at_upper;
- if (gtk_tab_strip_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
- adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
- else
- adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
-
+ adj = gtk_tab_strip_get_scroll_adjustment (self);
value = gtk_adjustment_get_value (adj);
at_lower = value <= gtk_adjustment_get_lower (adj);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]