/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2006-2007 Imendio AB
+ * Copyright (C) 2007-2011 Collabora Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* Authors: Kristian Rietveld <kris@imendio.com>
*/
-/* To do:
- * - should probably cancel animation if model changes
- * - need to handle case where node-in-animation is removed
- * - it only handles a single animation at a time; but I guess users
- * aren't fast enough to trigger two or more animations at once anyway :P
- * (could guard for this by just cancelling the "old" animation, and
- * start the new one).
- */
-
-#include <gtk/gtk.h>
-
-#include <libempathy/empathy-utils.h>
+#include "config.h"
#include "empathy-cell-renderer-expander.h"
+#include "empathy-utils.h"
+
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCellRendererExpander)
typedef struct {
GtkExpanderStyle expander_style;
gint expander_size;
- GtkTreeView *animation_view;
- GtkTreeRowReference *animation_node;
- GtkExpanderStyle animation_style;
- guint animation_timeout;
- GdkRectangle animation_area;
-
guint activatable : 1;
- guint animation_expanding : 1;
} EmpathyCellRendererExpanderPriv;
enum {
static void empathy_cell_renderer_expander_finalize (GObject *object);
static void empathy_cell_renderer_expander_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
- GdkRectangle *cell_area,
+ const GdkRectangle *cell_area,
gint *x_offset,
gint *y_offset,
gint *width,
gint *height);
static void empathy_cell_renderer_expander_render (GtkCellRenderer *cell,
- GdkWindow *window,
+ cairo_t *cr,
GtkWidget *widget,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GdkRectangle *expose_area,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
GtkCellRendererState flags);
static gboolean empathy_cell_renderer_expander_activate (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
const gchar *path,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
GtkCellRendererState flags);
G_DEFINE_TYPE (EmpathyCellRendererExpander, empathy_cell_renderer_expander, GTK_TYPE_CELL_RENDERER)
priv->expander_style = GTK_EXPANDER_COLLAPSED;
priv->expander_size = 12;
priv->activatable = TRUE;
- priv->animation_node = NULL;
g_object_set (expander,
"xpad", 2,
static void
empathy_cell_renderer_expander_finalize (GObject *object)
{
- EmpathyCellRendererExpanderPriv *priv;
-
- priv = GET_PRIV (object);
-
- if (priv->animation_timeout) {
- g_source_remove (priv->animation_timeout);
- priv->animation_timeout = 0;
- }
-
- if (priv->animation_node) {
- gtk_tree_row_reference_free (priv->animation_node);
- }
-
(* G_OBJECT_CLASS (empathy_cell_renderer_expander_parent_class)->finalize) (object);
}
}
static void
-empathy_cell_renderer_expander_get_size (GtkCellRenderer *cell,
- GtkWidget *widget,
- GdkRectangle *cell_area,
- gint *x_offset,
- gint *y_offset,
- gint *width,
- gint *height)
+empathy_cell_renderer_expander_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget,
+ const GdkRectangle *cell_area,
+ gint *x_offset,
+ gint *y_offset,
+ gint *width,
+ gint *height)
{
EmpathyCellRendererExpander *expander;
EmpathyCellRendererExpanderPriv *priv;
static void
empathy_cell_renderer_expander_render (GtkCellRenderer *cell,
- GdkWindow *window,
+ cairo_t *cr,
GtkWidget *widget,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GdkRectangle *expose_area,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
GtkCellRendererState flags)
{
EmpathyCellRendererExpander *expander;
EmpathyCellRendererExpanderPriv *priv;
- GtkExpanderStyle expander_style;
gint x_offset, y_offset;
guint xpad, ypad;
-
+ GtkStyleContext *style;
+ GtkStateFlags state;
expander = (EmpathyCellRendererExpander *) cell;
priv = GET_PRIV (expander);
- if (priv->animation_node) {
- GtkTreePath *path;
- GdkRectangle rect;
-
- /* Not sure if I like this ... */
- path = gtk_tree_row_reference_get_path (priv->animation_node);
- gtk_tree_view_get_background_area (priv->animation_view, path,
- NULL, &rect);
- gtk_tree_path_free (path);
-
- if (background_area->y == rect.y)
- expander_style = priv->animation_style;
- else
- expander_style = priv->expander_style;
- } else
- expander_style = priv->expander_style;
-
- empathy_cell_renderer_expander_get_size (cell, widget, cell_area,
+ empathy_cell_renderer_expander_get_size (cell, widget,
+ (GdkRectangle *) cell_area,
&x_offset, &y_offset,
NULL, NULL);
"ypad", &ypad,
NULL);
- gtk_paint_expander (gtk_widget_get_style (widget),
- window,
- GTK_STATE_NORMAL,
- expose_area,
- widget,
- "treeview",
- cell_area->x + x_offset + xpad + priv->expander_size / 2,
- cell_area->y + y_offset + ypad + priv->expander_size / 2,
- expander_style);
-}
-
-static void
-invalidate_node (GtkTreeView *tree_view,
- GtkTreePath *path)
-{
- GdkWindow *bin_window;
- GdkRectangle rect;
-
- bin_window = gtk_tree_view_get_bin_window (tree_view);
-
- gtk_tree_view_get_background_area (tree_view, path, NULL, &rect);
-
- rect.x = 0;
- rect.width = GTK_WIDGET (tree_view)->allocation.width;
-
- gdk_window_invalidate_rect (bin_window, &rect, TRUE);
-}
-
-static gboolean
-do_animation (EmpathyCellRendererExpander *expander)
-{
- EmpathyCellRendererExpanderPriv *priv;
- GtkTreePath *path;
- gboolean done = FALSE;
-
- priv = GET_PRIV (expander);
-
- if (priv->animation_expanding) {
- if (priv->animation_style == GTK_EXPANDER_SEMI_COLLAPSED)
- priv->animation_style = GTK_EXPANDER_SEMI_EXPANDED;
- else if (priv->animation_style == GTK_EXPANDER_SEMI_EXPANDED) {
- priv->animation_style = GTK_EXPANDER_EXPANDED;
- done = TRUE;
- }
- } else {
- if (priv->animation_style == GTK_EXPANDER_SEMI_EXPANDED)
- priv->animation_style = GTK_EXPANDER_SEMI_COLLAPSED;
- else if (priv->animation_style == GTK_EXPANDER_SEMI_COLLAPSED) {
- priv->animation_style = GTK_EXPANDER_COLLAPSED;
- done = TRUE;
- }
- }
-
- path = gtk_tree_row_reference_get_path (priv->animation_node);
- invalidate_node (priv->animation_view, path);
- gtk_tree_path_free (path);
-
- if (done) {
- gtk_tree_row_reference_free (priv->animation_node);
- priv->animation_node = NULL;
- priv->animation_timeout = 0;
- }
+ style = gtk_widget_get_style_context (widget);
- return !done;
-}
+ gtk_style_context_save (style);
+ gtk_style_context_add_class (style, GTK_STYLE_CLASS_EXPANDER);
-static gboolean
-animation_timeout (gpointer data)
-{
- gboolean retval;
+ state = gtk_cell_renderer_get_state (cell, widget, flags);
- GDK_THREADS_ENTER ();
+ if (priv->expander_style == GTK_EXPANDER_COLLAPSED)
+ state |= GTK_STATE_FLAG_NORMAL;
+ else
+ state |= GTK_STATE_FLAG_ACTIVE;
- retval = do_animation (data);
+ gtk_style_context_set_state (style, state);
- GDK_THREADS_LEAVE ();
+ gtk_render_expander (style,
+ cr,
+ cell_area->x + x_offset + xpad,
+ cell_area->y + y_offset + ypad,
+ priv->expander_size,
+ priv->expander_size);
- return retval;
-}
-
-static void
-empathy_cell_renderer_expander_start_animation (EmpathyCellRendererExpander *expander,
- GtkTreeView *tree_view,
- GtkTreePath *path,
- gboolean expanding,
- GdkRectangle *background_area)
-{
- EmpathyCellRendererExpanderPriv *priv;
-
- priv = GET_PRIV (expander);
-
- if (expanding) {
- priv->animation_style = GTK_EXPANDER_SEMI_COLLAPSED;
- } else {
- priv->animation_style = GTK_EXPANDER_SEMI_EXPANDED;
- }
-
- invalidate_node (tree_view, path);
-
- priv->animation_expanding = expanding;
- priv->animation_view = tree_view;
- priv->animation_node = gtk_tree_row_reference_new (gtk_tree_view_get_model (tree_view), path);
- priv->animation_timeout = g_timeout_add (50, animation_timeout, expander);
+ gtk_style_context_restore (style);
}
static gboolean
GdkEvent *event,
GtkWidget *widget,
const gchar *path_string,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
GtkCellRendererState flags)
{
- EmpathyCellRendererExpander *expander;
EmpathyCellRendererExpanderPriv *priv;
GtkTreePath *path;
- gboolean animate;
- gboolean expanding;
- expander = EMPATHY_CELL_RENDERER_EXPANDER (cell);
priv = GET_PRIV (cell);
if (!GTK_IS_TREE_VIEW (widget) || !priv->activatable)
return TRUE;
}
- g_object_get (gtk_widget_get_settings (GTK_WIDGET (widget)),
- "gtk-enable-animations", &animate,
- NULL);
-
if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (widget), path)) {
gtk_tree_view_collapse_row (GTK_TREE_VIEW (widget), path);
- expanding = FALSE;
} else {
gtk_tree_view_expand_row (GTK_TREE_VIEW (widget), path, FALSE);
- expanding = TRUE;
- }
-
- if (animate) {
- empathy_cell_renderer_expander_start_animation (expander,
- GTK_TREE_VIEW (widget),
- path,
- expanding,
- background_area);
}
gtk_tree_path_free (path);