GtkTreeViewRevealer
- From: Detlef Reichl <detlef reichl arcormail de>
- To: GTK-devel <gtk-devel-list gnome org>
- Subject: GtkTreeViewRevealer
- Date: 29 Oct 2001 23:09:04 +0100
hi all
attached are some patches, which will add someting i call a
TreeViewRevealer to the GtkTreeView. it expands a cell where the pointer
in a treeview is in, if this cell is wider then the column.
this implementation works but needs some polish and some additions i.e.
left2rigtht is not considerated.
have a nice day
detlef
--- gtk+/gtk/gtktreeprivate.h Sun Sep 30 12:11:17 2001
+++ gtkdet/gtk/gtktreeprivate.h Mon Oct 29 22:29:08 2001
@@ -78,6 +78,22 @@
GtkTreeViewColumn *right_column;
};
+typedef struct _GtkTreeViewRevealerInfo GtkTreeViewRevealerInfo;
+struct _GtkTreeViewRevealerInfo
+{
+ GtkWidget *revealer_window;
+ GtkWidget *revealer_area;
+ GtkTreeView *tree_view;
+ GtkTreeViewColumn *column;
+ GtkTreeIter iter;
+ GdkRectangle cell_area;
+ GdkRectangle background_area;
+ GdkRectangle old_revealer;
+ gint x;
+ gint y;
+ gint timer;
+};
+
struct _GtkTreeViewPrivate
{
GtkTreeModel *model;
@@ -106,6 +122,15 @@
GtkTreeViewColumn *expander_column;
GtkTreeViewColumn *edited_column;
+
+ /* revealing covered cells */
+ guint enable_revealer :1;
+ gint revealer_x;
+ gint revealer_y;
+ gint revealer_width;
+ gint revealer_height;
+ guint revealer_timeout;
+ GtkTreeViewRevealerInfo *revealer_info;
/* Focus code */
GtkTreeViewColumn *focus_column;
--- gtk+/gtk/gtktreeview.c Tue Oct 23 21:13:20 2001
+++ gtkdet/gtk/gtktreeview.c Mon Oct 29 22:40:05 2001
@@ -23,6 +23,7 @@
#include "gtktreednd.h"
#include "gtktreeprivate.h"
#include "gtkcellrenderer.h"
+#include "gtkcellrenderertext.h"
#include "gtksignal.h"
#include "gtkmain.h"
#include "gtkbutton.h"
@@ -34,6 +35,7 @@
#include "gtkbindings.h"
#include "gtkcontainer.h"
#include "gtkentry.h"
+#include "gtkdrawingarea.h"
#include <string.h>
#include <gdk/gdkkeysyms.h>
@@ -42,6 +44,7 @@
#define SCROLL_EDGE_SIZE 15
#define EXPANDER_EXTRA_PADDING 4
+#define REVEALER_DEFAULT_TIMEOUT 300
/* The "background" areas of all rows/cells add up to cover the entire tree.
* The background includes all inter-row and inter-cell spacing.
@@ -117,6 +120,8 @@
PROP_RULES_HINT,
PROP_ENABLE_SEARCH,
PROP_SEARCH_COLUMN,
+ PROP_ENABLE_REVEALER,
+ PROP_REVEALER_TIMEOUT,
};
static void gtk_tree_view_class_init (GtkTreeViewClass *klass);
@@ -568,6 +573,24 @@
0,
G_PARAM_READWRITE));
+ g_object_class_install_property (o_class,
+ PROP_ENABLE_REVEALER,
+ g_param_spec_boolean ("enable_revealer",
+ _("Enable Revealer"),
+ _("Allows the view to show the revealer window"),
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (o_class,
+ PROP_REVEALER_TIMEOUT,
+ g_param_spec_uint ("revealer_timeout",
+ _("Revealer Timeout"),
+ _("The time when the revealer window will appear"),
+ 1,
+ G_MAXUINT,
+ REVEALER_DEFAULT_TIMEOUT,
+ G_PARAM_READWRITE));
+
/* Style properties */
#define _TREE_VIEW_EXPANDER_SIZE 10
#define _TREE_VIEW_VERTICAL_SEPARATOR 2
@@ -879,6 +902,13 @@
tree_view->priv->search_column = -1;
tree_view->priv->search_dialog_position_func = gtk_tree_view_search_position_func;
tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
+ tree_view->priv->revealer_info = NULL;
+ tree_view->priv->revealer_x = 0;
+ tree_view->priv->revealer_y = 0;
+ tree_view->priv->revealer_width = 0;
+ tree_view->priv->revealer_height = 0;
+ tree_view->priv->enable_revealer = TRUE;
+ tree_view->priv->revealer_timeout = REVEALER_DEFAULT_TIMEOUT;
}
@@ -927,6 +957,12 @@
case PROP_SEARCH_COLUMN:
gtk_tree_view_set_search_column (tree_view, g_value_get_int (value));
break;
+ case PROP_ENABLE_REVEALER:
+ tree_view->priv->enable_revealer = g_value_get_boolean (value);
+ break;
+ case PROP_REVEALER_TIMEOUT:
+ tree_view->priv->revealer_timeout = g_value_get_uint (value);
+ break;
default:
break;
}
@@ -971,6 +1007,11 @@
case PROP_SEARCH_COLUMN:
g_value_set_int (value, tree_view->priv->search_column);
break;
+ case PROP_ENABLE_REVEALER:
+ g_value_set_boolean (value, tree_view->priv->enable_revealer);
+ case PROP_REVEALER_TIMEOUT:
+ g_value_set_uint (value, tree_view->priv->revealer_timeout);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2333,17 +2374,226 @@
return TRUE;
}
+static void
+gtk_tree_view_revealer_hide (GtkTreeView *tree_view)
+{
+ if (!tree_view->priv->revealer_info)
+ return;
+
+ if (tree_view->priv->revealer_info->timer)
+ gtk_timeout_remove (tree_view->priv->revealer_info->timer);
+ if (tree_view->priv->revealer_info->revealer_window
+ && GTK_WIDGET_VISIBLE (tree_view->priv->revealer_info->revealer_window))
+ {
+ /* invalid position, so on reenterence the revealer will be shown in any case */
+ tree_view->priv->revealer_info->old_revealer.x = -1;
+ gtk_widget_hide (tree_view->priv->revealer_info->revealer_window);
+ }
+}
+
+static gboolean
+gtk_tree_view_revealer_timeout (GtkTreeViewRevealerInfo *info)
+{
+ if (!GTK_WIDGET_VISIBLE (info->revealer_window))
+ {
+ gtk_widget_show (info->revealer_window);
+ }
+ return FALSE;
+}
+
+static void
+gtk_tree_view_revealer_move_resize (GtkTreeViewRevealerInfo *info)
+{
+ GList *renderers = NULL;
+
+ gint x_offset = 0;
+ gint y_offset = 0;
+ gint width = 0;
+ gint height = 0;
+ gint column_width;
+ gint horizontal_separator, vertical_separator;
+ GValue value = {0, };
+
+ if (info->timer)
+ gtk_timeout_remove (info->timer);
+ if (GTK_WIDGET_VISIBLE (info->revealer_window))
+ gtk_widget_hide (info->revealer_window);
+
+ if (! (renderers = gtk_tree_view_column_get_cell_renderers (info->column)))
+ return;
+
+ gtk_widget_style_get (GTK_WIDGET (info->tree_view),
+ "horizontal_separator", &horizontal_separator,
+ "vertical_separator", &vertical_separator,
+ NULL);
+ column_width = gtk_tree_view_column_get_width (info->column);
+ info->background_area.x = info->cell_area.x;
+ info->background_area.y = info->cell_area.y;
+ info->background_area.width = info->cell_area.width,
+ info->background_area.height = info->cell_area.height;
+
+ gtk_cell_renderer_get_size (GTK_CELL_RENDERER (renderers->data),
+ GTK_WIDGET (info->tree_view),
+ &info->background_area,
+ &x_offset, &y_offset,
+ &width, &height);
+
+ info->background_area.x = (column_width - horizontal_separator / 2) *-1;
+ info->background_area.y = 1;
+ info->background_area.width = width + horizontal_separator;
+ info->background_area.height = height;
+
+ /* if the column is widther the the content we don't need the revealer */
+ if (column_width >= width)
+ return;
+
+ gtk_window_move (GTK_WINDOW (info->revealer_window),
+ info->x + column_width - 1,
+ info->y + y_offset - 1);
+ gtk_widget_set_usize (info->revealer_window,
+ info->background_area.width - column_width + 1,
+ info->background_area.height + 2);
+
+ g_value_init (&value, G_TYPE_UINT);
+ g_object_get_property (G_OBJECT (info->tree_view),
+ "revealer_timeout",
+ &value);
+ info->timer = gtk_timeout_add (g_value_get_uint (&value),
+ (GtkFunction)gtk_tree_view_revealer_timeout,
+ info);
+}
+
+static gboolean
+gtk_tree_view_revealer_expose (GtkWidget *widget,
+ GdkEventExpose *event,
+ GtkTreeViewRevealerInfo *info)
+{
+ GtkTreeView *tree_view = GTK_TREE_VIEW (info->tree_view);
+ GtkRBTree *tree;
+ GtkRBNode *node;
+
+ gint new_y;
+ const gchar *detail = NULL;
+ guint flags;
+ GtkStateType state;
+ gboolean allow_rules;
+ gboolean parity;
+ GValue rules_hint = {0, };
+
+ gtk_widget_style_get (GTK_WIDGET (info->tree_view),"allow_rules", &allow_rules,NULL);
+
+ new_y = ((gint)info->cell_area.y < TREE_VIEW_HEADER_HEIGHT (tree_view))
+ ? TREE_VIEW_HEADER_HEIGHT (tree_view)
+ : (gint)info->cell_area.y;
+ _gtk_rbtree_find_offset (tree_view->priv->tree,
+ TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
+ &tree,
+ &node);
+
+ parity = _gtk_rbtree_node_find_parity (tree, node);
+
+ g_value_init (&rules_hint, G_TYPE_BOOLEAN);
+ g_object_get_property (G_OBJECT (info->tree_view),
+ "rules_hint",
+ &rules_hint);
+
+ flags = GTK_CELL_RENDERER_PRELIT;
+ if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
+ flags |= GTK_CELL_RENDERER_SELECTED;
+ if (info->column->show_sort_indicator)
+ flags |= GTK_CELL_RENDERER_SORTED;
+ else
+ flags &= ~GTK_CELL_RENDERER_SORTED;
+
+ if (allow_rules && g_value_get_boolean (&rules_hint))
+ {
+ if (flags & GTK_CELL_RENDERER_SORTED)
+ {
+ if (parity)
+ detail = "cell_odd_ruled_sorted";
+ else
+ detail = "cell_even_ruled_sorted";
+ }
+ else
+ {
+ if (parity)
+ detail = "cell_odd_ruled";
+ else
+ detail = "cell_even_ruled";
+ }
+ }
+ else
+ {
+ if (flags & GTK_CELL_RENDERER_SORTED)
+ {
+ if (parity)
+ detail = "cell_odd_sorted";
+ else
+ detail = "cell_even_sorted";
+ }
+ else
+ {
+ if (parity)
+ detail = "cell_odd";
+ else
+ detail = "cell_even";
+ }
+ }
+ g_assert (detail);
+ if (flags & GTK_CELL_RENDERER_SELECTED)
+ state = GTK_STATE_SELECTED;
+ else
+ state = GTK_STATE_NORMAL;
+
+ gdk_draw_rectangle (info->revealer_area->window,
+ widget->style->black_gc,
+ FALSE,
+ info->background_area.x - 1,
+ info->background_area.y - 1,
+ info->background_area.width,
+ info->background_area.height + 1);
+ gtk_paint_flat_box (widget->style,
+ event->window,
+ state,
+ GTK_SHADOW_NONE,
+ &event->area,
+ GTK_WIDGET (info->tree_view),
+ detail,
+ info->background_area.x + 1,
+ info->background_area.y,
+ info->background_area.width - 2,
+ info->background_area.height);
+
+ gtk_tree_view_column_cell_set_cell_data (info->column,
+ tree_view->priv->model,
+ &info->iter,
+ FALSE,
+ FALSE);
+ gtk_tree_view_column_cell_render (info->column,
+ info->revealer_area->window,
+ &info->cell_area,
+ &info->background_area,
+ &info->background_area,
+ flags );
+ return FALSE;
+}
+
static gboolean
gtk_tree_view_motion_bin_window (GtkWidget *widget,
GdkEventMotion *event)
{
GtkTreeView *tree_view;
+ GtkTreeViewRevealerInfo *info;
GtkRBTree *tree;
GtkRBNode *node;
gint new_y;
GtkRBTree *old_prelight_tree;
GtkRBNode *old_prelight_node;
gboolean old_arrow_prelit;
+ gint x, y;
+
+ GtkTreePath *path = NULL;
+ GtkTreeViewColumn *column;
tree_view = (GtkTreeView *) widget;
@@ -2397,6 +2647,77 @@
tree_view->priv->prelight_node,
NULL);
}
+
+ /* there is only one instance of the revealer info, cause we only have one pointer (hope ;)*/
+ if (!tree_view->priv->revealer_info)
+ {
+ tree_view->priv->revealer_info = g_new (GtkTreeViewRevealerInfo, 1);
+ tree_view->priv->revealer_info->revealer_window = NULL;
+ tree_view->priv->revealer_info->old_revealer.x = -1;
+ tree_view->priv->revealer_info->timer = 0;
+ }
+ info = tree_view->priv->revealer_info;
+
+ if (!tree_view->priv->enable_revealer)
+ {
+ gtk_tree_view_revealer_hide (tree_view);
+ return TRUE;
+ }
+
+ if (! (gtk_tree_view_get_path_at_pos (tree_view,
+ event->window,
+ (gint)event->x,
+ (gint)event->y,
+ &path,
+ &column,
+ &x, &y)))
+ return TRUE;
+
+ if (! (gtk_tree_model_get_iter (tree_view->priv->model,
+ &tree_view->priv->revealer_info->iter,
+ path)))
+ return TRUE;
+ gtk_tree_view_get_cell_area( tree_view,
+ path,
+ column,
+ &info->cell_area);
+
+ if (!info->revealer_window)
+ {
+ info->revealer_window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_type_hint ( GTK_WINDOW (info->revealer_window),
+ GDK_WINDOW_TYPE_HINT_MENU);
+ gtk_window_set_resizable (GTK_WINDOW (info->revealer_window), FALSE);
+ info->revealer_area = gtk_drawing_area_new ();
+ gtk_container_add (GTK_CONTAINER (info->revealer_window), info->revealer_area);
+ gtk_signal_connect (GTK_OBJECT (info->revealer_area),
+ "expose-event",
+ GTK_SIGNAL_FUNC (gtk_tree_view_revealer_expose),
+ info);
+ info->tree_view = tree_view;
+ gtk_widget_set_usize (info->revealer_window, 1, 1);
+ gtk_widget_show (info->revealer_area);
+ }
+
+ if (info->cell_area.x != info->old_revealer.x ||
+ info->cell_area.y != info->old_revealer.y)
+ {
+ info->old_revealer.x = info->cell_area.x;
+ info->old_revealer.y = info->cell_area.y;
+ info->old_revealer.width = info->cell_area.width;
+ info->old_revealer.height = info->cell_area.height;
+
+ info->x = event->x_root - event->x + info->cell_area.x;
+ info->y = event->y_root - event->y + info->cell_area.y;
+ info->column = column;
+ gtk_tree_view_column_cell_set_cell_data (info->column,
+ tree_view->priv->model,
+ &info->iter,
+ FALSE,
+ FALSE);
+ gtk_tree_view_revealer_move_resize (info);
+ }
+ gtk_tree_path_free (path);
return TRUE;
}
@@ -2908,6 +3229,8 @@
tree_view = GTK_TREE_VIEW (widget);
+ gtk_tree_view_revealer_hide (tree_view);
+
if (tree_view->priv->prelight_node)
gtk_tree_view_queue_draw_node (tree_view,
tree_view->priv->prelight_tree,
@@ -6282,6 +6605,8 @@
{
if (GTK_WIDGET_REALIZED (tree_view))
{
+ gtk_tree_view_revealer_hide (tree_view);
+
gdk_window_move (tree_view->priv->bin_window,
- tree_view->priv->hadjustment->value,
- tree_view->priv->vadjustment->value);
@@ -8703,12 +9028,11 @@
drawable,
&background_area,
&cell_area,
- NULL,
+ &cell_area,
0);
cell_offset += column->width;
}
-
return drawable;
}
--- gtk+/gtk/gtktreeviewcolumn.c Mon Oct 22 00:04:09 2001
+++ gtkdet/gtk/gtktreeviewcolumn.c Sun Oct 28 18:01:51 2001
@@ -2184,8 +2184,8 @@
if (visible == FALSE)
continue;
- real_cell_area.width = info->requested_width +
- (info->expand?extra_space:0);
+ real_cell_area.width = MIN (info->requested_width +
+ (info->expand?extra_space:0), cell_area->width);
if (render)
{
gtk_cell_renderer_render (info->cell,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]