xed/xed/xed-paned.c

265 lines
6.3 KiB
C

#include <config.h>
#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;
}