From c16232ee2061842b985fcb860c457349891bb3c6 Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Fri, 17 Mar 2017 00:09:00 -0700 Subject: [PATCH] Add a new animated xed-paned This replaces the GtkPaned we currently use and opens and closes the panes using an animation. --- xed/Makefile.am | 2 + xed/xed-commands-view.c | 20 ++- xed/xed-paned.c | 266 ++++++++++++++++++++++++++++++++++++++++ xed/xed-paned.h | 46 +++++++ xed/xed-panel.c | 7 -- xed/xed-window.c | 44 +++++-- xed/xed-window.h | 6 + 7 files changed, 374 insertions(+), 17 deletions(-) create mode 100644 xed/xed-paned.c create mode 100644 xed/xed-paned.h diff --git a/xed/Makefile.am b/xed/Makefile.am index d5610d7..bbaec9c 100644 --- a/xed/Makefile.am +++ b/xed/Makefile.am @@ -44,6 +44,7 @@ NOINST_H_FILES = \ xed-encodings-dialog.h \ xed-history-entry.h \ xed-io-error-info-bar.h \ + xed-paned.h \ xed-plugins-engine.h \ xed-preferences-dialog.h \ xed-print-job.h \ @@ -119,6 +120,7 @@ libxed_c_files = \ xed-message-type.c \ xed-message.c \ xed-notebook.c \ + xed-paned.c \ xed-panel.c \ xed-plugins-engine.c \ xed-preferences-dialog.c \ diff --git a/xed/xed-commands-view.c b/xed/xed-commands-view.c index 9df6fe2..607ee6c 100644 --- a/xed/xed-commands-view.c +++ b/xed/xed-commands-view.c @@ -40,6 +40,7 @@ #include "xed-debug.h" #include "xed-window.h" #include "xed-window-private.h" +#include "xed-paned.h" void @@ -80,21 +81,24 @@ _xed_cmd_view_show_side_pane (GtkAction *action, { gboolean visible; XedPanel *panel; + XedPaned *paned; xed_debug (DEBUG_COMMANDS); visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); panel = xed_window_get_side_panel (window); + paned = _xed_window_get_hpaned (window); if (visible) { - gtk_widget_show (GTK_WIDGET (panel)); + gtk_widget_show (GTK_WIDGET (panel)); + xed_paned_open (paned, 1, _xed_window_get_side_panel_size (window)); gtk_widget_grab_focus (GTK_WIDGET (panel)); } else { - gtk_widget_hide (GTK_WIDGET (panel)); + xed_paned_close (paned, 1); } } @@ -104,21 +108,31 @@ _xed_cmd_view_show_bottom_pane (GtkAction *action, { gboolean visible; XedPanel *panel; + XedPaned *paned; xed_debug (DEBUG_COMMANDS); visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); panel = xed_window_get_bottom_panel (window); + paned = _xed_window_get_vpaned (window); if (visible) { + gint position; + gint panel_size; + gint paned_size; + + panel_size = _xed_window_get_bottom_panel_size (window); + g_object_get (G_OBJECT (paned), "max-position", &paned_size, NULL); + position = paned_size - panel_size; gtk_widget_show (GTK_WIDGET (panel)); + xed_paned_open (paned, 2, position); gtk_widget_grab_focus (GTK_WIDGET (panel)); } else { - gtk_widget_hide (GTK_WIDGET (panel)); + xed_paned_close (paned, 2); } } diff --git a/xed/xed-paned.c b/xed/xed-paned.c new file mode 100644 index 0000000..7076f8a --- /dev/null +++ b/xed/xed-paned.c @@ -0,0 +1,266 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "xed-paned.h" + +#define ANIMATION_TIME 125 + +struct _XedPanedPrivate +{ + gint start_pos; + gint current_pos; + gint target_pos; + + gint64 start_time; + gint64 end_time; + + guint tick_id; + + gboolean animating; + gboolean show_child; + gboolean is_vertical; + gint pane_number; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (XedPaned, xed_paned, GTK_TYPE_PANED) + +static void +xed_paned_dispose (GObject *object) +{ + XedPaned *paned = XED_PANED (object); + + if (paned->priv->tick_id != 0) + { + gtk_widget_remove_tick_callback (GTK_WIDGET (paned), paned->priv->tick_id); + } + paned->priv->tick_id = 0; + + G_OBJECT_CLASS (xed_paned_parent_class)->dispose (object); +} + +static void +xed_paned_class_init (XedPanedClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = xed_paned_dispose; +} + +static void +xed_paned_init (XedPaned *paned) +{ + paned->priv = xed_paned_get_instance_private (paned); + + paned->priv->animating = FALSE; +} + +GtkWidget * +xed_paned_new (GtkOrientation orientation) +{ + return GTK_WIDGET (g_object_new (XED_TYPE_PANED, + "orientation", orientation, + NULL)); +} + +static void +animate_step (XedPaned *paned, + gint64 now) +{ + + gdouble t; + gint difference; + + if ((paned->priv->show_child && paned->priv->pane_number == 1) || + (!paned->priv->show_child && paned->priv->pane_number == 2)) + { + difference = paned->priv->target_pos - paned->priv->start_pos; + if (now < paned->priv->end_time) + { + t = ((gdouble) (now - paned->priv->start_time) / (gdouble) (paned->priv->end_time - paned->priv->start_time)); + } + else + { + t = 1.0; + } + + paned->priv->current_pos = paned->priv->start_pos + (difference * t); + } + else + { + difference = paned->priv->start_pos - paned->priv->target_pos; + if (now < paned->priv->end_time) + { + t = ((gdouble) (now - paned->priv->start_time) / (gdouble) (paned->priv->end_time - paned->priv->start_time)); + } + else + { + t = 1.0; + } + + paned->priv->current_pos = paned->priv->start_pos - (difference * t); + } + + gtk_paned_set_position (GTK_PANED (paned), paned->priv->current_pos); + gtk_widget_queue_draw (GTK_WIDGET (paned)); +} + +static gboolean +animate_cb (GtkWidget *widget, + GdkFrameClock *frame_clock, + gpointer user_data) +{ + XedPaned *paned = XED_PANED (widget); + gint64 now; + + now = gdk_frame_clock_get_frame_time (frame_clock); + + animate_step (paned, now); + + if (paned->priv->current_pos == paned->priv->target_pos) + { + paned->priv->tick_id = 0; + + if (!paned->priv->show_child) + { + if (paned->priv->pane_number == 1) + { + gtk_widget_hide (gtk_paned_get_child1 (GTK_PANED (paned))); + } + else + { + gtk_widget_hide (gtk_paned_get_child2 (GTK_PANED (paned))); + } + } + + paned->priv->animating = FALSE; + return G_SOURCE_REMOVE; + } + + return G_SOURCE_CONTINUE; +} + +static void +calculate_target_postion (XedPaned *paned, + gint target_position) +{ + if (paned->priv->show_child) + { + if (target_position < 0) + { + paned->priv->target_pos = 0; + } + else + { + paned->priv->target_pos = target_position; + } + } + else + { + if (paned->priv->pane_number == 1) + { + paned->priv->target_pos = 0; + } + else + { + gint max_pos; + + g_object_get (G_OBJECT (paned), "max-position", &max_pos, NULL); + paned->priv->target_pos = max_pos; + } + } +} + +static void +calculate_start_position (XedPaned *paned) +{ + if (paned->priv->show_child && paned->priv->pane_number == 1) + { + paned->priv->start_pos = 0; + } + else if (paned->priv->show_child && paned->priv->pane_number == 2) + { + gint max_pos; + + g_object_get (G_OBJECT (paned), "max-position", &max_pos, NULL); + paned->priv->start_pos = max_pos; + } + else if (paned->priv->pane_number == 1 || paned->priv->pane_number == 2) + { + paned->priv->start_pos = gtk_paned_get_position (GTK_PANED (paned)); + } + + paned->priv->current_pos = paned->priv->start_pos; +} + +static void +setup_animation (XedPaned *paned, + gint target_position) +{ + if (!gtk_widget_get_mapped (GTK_WIDGET (paned))) + { + return; + } + + if (gtk_orientable_get_orientation (GTK_ORIENTABLE (paned)) == GTK_ORIENTATION_HORIZONTAL) + { + paned->priv->is_vertical = FALSE; + } + else + { + paned->priv->is_vertical = TRUE; + } + + calculate_start_position (paned); + calculate_target_postion (paned, target_position); + + paned->priv->start_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (GTK_WIDGET (paned))); + paned->priv->end_time = paned->priv->start_time + (ANIMATION_TIME * 1000); + + if (paned->priv->tick_id == 0) + { + paned->priv->animating = TRUE; + paned->priv->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (paned), + animate_cb, + NULL, + NULL); + } + + if (paned->priv->show_child) + { + gtk_widget_show (gtk_paned_get_child1 (GTK_PANED (paned))); + } + + animate_step (paned, paned->priv->start_time); +} + +void +xed_paned_close (XedPaned *paned, + gint pane_number) +{ + g_return_if_fail (XED_IS_PANED (paned)); + g_return_if_fail (pane_number == 1 || pane_number == 2); + + paned->priv->show_child = FALSE; + paned->priv->pane_number = pane_number; + setup_animation (paned, -1); +} + +void +xed_paned_open (XedPaned *paned, + gint pane_number, + gint target_position) +{ + g_return_if_fail (XED_IS_PANED (paned)); + g_return_if_fail (pane_number == 1 || pane_number == 2); + + paned->priv->show_child = TRUE; + paned->priv->pane_number = pane_number; + setup_animation (paned, target_position); +} + +gboolean +xed_paned_get_is_animating (XedPaned *paned) +{ + return paned->priv->animating; +} diff --git a/xed/xed-paned.h b/xed/xed-paned.h new file mode 100644 index 0000000..f11d774 --- /dev/null +++ b/xed/xed-paned.h @@ -0,0 +1,46 @@ +#ifndef __XED_PANED_H__ +#define __XED_PANED_H__ + +#include + +G_BEGIN_DECLS + +#define XED_TYPE_PANED (xed_paned_get_type ()) +#define XED_PANED(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XED_TYPE_PANED, XedPaned)) +#define XED_PANED_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), XED_TYPE_PANED, XedPanedClass)) +#define XED_IS_PANED(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XED_TYPE_PANED)) +#define XED_IS_PANED_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), XED_TYPE_PANED)) +#define XED_PANED_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), XED_TYPE_PANED, XedPanedClass)) + +typedef struct _XedPaned XedPaned; +typedef struct _XedPanedPrivate XedPanedPrivate; +typedef struct _XedPanedClass XedPanedClass; + +struct _XedPaned +{ + GtkPaned parent; + + /* */ + XedPanedPrivate *priv; +}; + +struct _XedPanedClass +{ + GtkPanedClass parent_class; +}; + +GType xed_paned_get_type (void) G_GNUC_CONST; + +GtkWidget *xed_paned_new (GtkOrientation orientation); + +void xed_paned_close (XedPaned *paned, + gint pane_number); +void xed_paned_open (XedPaned *paned, + gint pane_number, + gint pos); + +gboolean xed_paned_get_is_animating (XedPaned *paned); + +G_END_DECLS + +#endif /* __XED_PANED_H__ */ diff --git a/xed/xed-panel.c b/xed/xed-panel.c index 51addb8..38a4aac 100644 --- a/xed/xed-panel.c +++ b/xed/xed-panel.c @@ -132,12 +132,6 @@ xed_panel_set_property (GObject *object, } } -static void -xed_panel_close (XedPanel *panel) -{ - gtk_widget_hide (GTK_WIDGET (panel)); -} - static void xed_panel_focus_document (XedPanel *panel) { @@ -257,7 +251,6 @@ xed_panel_class_init (XedPanelClass *klass) widget_class->size_allocate = xed_panel_size_allocate; widget_class->grab_focus = xed_panel_grab_focus; - klass->close = xed_panel_close; klass->focus_document = xed_panel_focus_document; g_object_class_install_property (object_class, diff --git a/xed/xed-window.c b/xed/xed-window.c index 77207cb..64e34f4 100644 --- a/xed/xed-window.c +++ b/xed/xed-window.c @@ -3173,7 +3173,10 @@ side_panel_size_allocate (GtkWidget *widget, GtkAllocation *allocation, XedWindow *window) { - window->priv->side_panel_size = allocation->width; + if (!xed_paned_get_is_animating (window->priv->hpaned)) + { + window->priv->side_panel_size = allocation->width; + } } static void @@ -3181,7 +3184,10 @@ bottom_panel_size_allocate (GtkWidget *widget, GtkAllocation *allocation, XedWindow *window) { - window->priv->bottom_panel_size = allocation->height; + if (!xed_paned_get_is_animating (window->priv->vpaned)) + { + window->priv->bottom_panel_size = allocation->height; + } } static void @@ -3256,7 +3262,7 @@ create_side_panel (XedWindow *window) window->priv->side_panel = xed_panel_new (GTK_ORIENTATION_VERTICAL); - gtk_paned_pack1 (GTK_PANED (window->priv->hpaned), window->priv->side_panel, FALSE, FALSE); + gtk_paned_pack1 (GTK_PANED (window->priv->hpaned), window->priv->side_panel, FALSE, TRUE); g_signal_connect_after (window->priv->side_panel, "show", G_CALLBACK (side_panel_visibility_changed), window); g_signal_connect_after (window->priv->side_panel, "hide", G_CALLBACK (side_panel_visibility_changed), window); @@ -3299,7 +3305,7 @@ bottom_panel_item_removed (XedPanel *panel, { GtkAction *action; - gtk_widget_hide (GTK_WIDGET (panel)); + xed_paned_close (window->priv->vpaned, 2); gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), FALSE); action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane"); gtk_action_set_sensitive (action, FALSE); @@ -3335,7 +3341,7 @@ create_bottom_panel (XedWindow *window) { xed_debug (DEBUG_WINDOW); window->priv->bottom_panel = xed_panel_new (GTK_ORIENTATION_HORIZONTAL); - gtk_paned_pack2 (GTK_PANED (window->priv->vpaned), window->priv->bottom_panel, FALSE, FALSE); + gtk_paned_pack2 (GTK_PANED (window->priv->vpaned), window->priv->bottom_panel, FALSE, TRUE); g_signal_connect_after(window->priv->bottom_panel, "show", G_CALLBACK (bottom_panel_visibility_changed), window); g_signal_connect_after(window->priv->bottom_panel, "hide", G_CALLBACK (bottom_panel_visibility_changed), window); } @@ -3539,10 +3545,10 @@ xed_window_init (XedWindow *window) /* Add the main area */ xed_debug_message (DEBUG_WINDOW, "Add main area"); - window->priv->hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL); + window->priv->hpaned = xed_paned_new (GTK_ORIENTATION_HORIZONTAL); gtk_box_pack_start (GTK_BOX (main_box), window->priv->hpaned, TRUE, TRUE, 0); - window->priv->vpaned = gtk_paned_new (GTK_ORIENTATION_VERTICAL); + window->priv->vpaned = xed_paned_new (GTK_ORIENTATION_VERTICAL); gtk_paned_pack2 (GTK_PANED (window->priv->hpaned), window->priv->vpaned, TRUE, FALSE); xed_debug_message (DEBUG_WINDOW, "Create xed notebook"); @@ -4339,3 +4345,27 @@ _xed_window_get_default_size (gint *width, *width = XED_WINDOW_DEFAULT_WIDTH; *height = XED_WINDOW_DEFAULT_HEIGHT; } + +XedPaned * +_xed_window_get_hpaned (XedWindow *window) +{ + return XED_PANED (window->priv->hpaned); +} + +XedPaned * +_xed_window_get_vpaned (XedWindow *window) +{ + return XED_PANED (window->priv->vpaned); +} + +gint +_xed_window_get_side_panel_size (XedWindow *window) +{ + return window->priv->side_panel_size; +} + +gint +_xed_window_get_bottom_panel_size (XedWindow *window) +{ + return window->priv->bottom_panel_size; +} diff --git a/xed/xed-window.h b/xed/xed-window.h index ae7ad72..beb6723 100644 --- a/xed/xed-window.h +++ b/xed/xed-window.h @@ -6,6 +6,7 @@ #include #include #include +#include G_BEGIN_DECLS @@ -106,6 +107,11 @@ void _xed_recent_add (XedWindow *window, GFile *location, const gchar *mime); void _xed_recent_remove (XedWindow *window, GFile *location); void _xed_window_get_default_size (gint *width, gint *height); +gint _xed_window_get_side_panel_size (XedWindow *window); +gint _xed_window_get_bottom_panel_size (XedWindow *window); + +XedPaned *_xed_window_get_hpaned (XedWindow *window); +XedPaned *_xed_window_get_vpaned (XedWindow *window); G_END_DECLS