GtkTreeViewRevealer



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]