]> Pileus Git - ~andy/gtk/commitdiff
Support insensitive cells in tree views and combo boxes.
authorMatthias Clasen <matthiasc@src.gnome.org>
Thu, 27 May 2004 03:31:17 +0000 (03:31 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Thu, 27 May 2004 03:31:17 +0000 (03:31 +0000)
14 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkcellrenderer.c
gtk/gtkcellrenderer.h
gtk/gtkcellrendererpixbuf.c
gtk/gtkcellrenderertext.c
gtk/gtkcellrenderertoggle.c
gtk/gtkcellview.c
gtk/gtkcellview.h
gtk/gtkcombobox.c
gtk/gtktreeselection.c
tests/testcombo.c

index d666a2512718116952d44e1eb8cfbd0895eaa431..c5d872d3b1fc1ae170ca5e1084a41a6b6972e774 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+Wed May 26 23:26:51 2004  Matthias Clasen  <maclas@gmx.de>
+
+       Support insensitive cells in tree views and combo boxes:
+       
+       * gtk/gtkcellrenderer.h: 
+       * gtk/gtkcellrenderer.c: Add a ::sensitive property.
+
+       * gtk/gtkcellrendererpixbuf.c (gtk_cell_renderer_pixbuf_render): 
+       * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_render): 
+       * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): 
+       Support drawing insensitive.
+
+       * gtk/gtkcellview.h: 
+       * gtk/gtkcellview.c (gtk_cell_view_get_cell_renderers): New 
+       function to obtain the cell renderers from a cell view. Also
+       export gtk_cell_view_set_cell_data().
+
+       * gtk/gtktreeselection.c (tree_column_is_sensitive):
+       * gtk/gtktreeselection.c (row_is_selectable): Helper functions
+       to determine whether all visible cells in a row are insensitive
+       and whether a row is selectable. A row is not selectable if the 
+       user function says so or if all visible cells are insensitive.
+       * gtk/gtktreeselection.c (_gtk_tree_selection_internal_select_node): 
+       * gtk/gtktreeselection.c (gtk_tree_selection_real_select_node): 
+       Use row_is_selectable().
+       
+       * gtk/gtkcombobox.c (row_is_sensitive): 
+       * gtk/gtkcombobox.c (tree_column_row_is_sensitive): 
+       * gtk/gtkcombobox.c (menu_row_is_sensitive): Helper functions
+       to determine row sensitivity in menu or list mode.
+
+       * gtk/gtkcombobox.c (update_menu_sensitivity): Helper function
+       to set up sensitivity menu items from the underlying rows.
+
+       * gtk/gtkcombobox.c (gtk_combo_box_popup): 
+       * gtk/gtkcombobox.c (gtk_combo_box_menu_button_press): Use
+       update_menu_sensitivity().
+               
+       * gtk/gtkcombobox.c (gtk_combo_box_list_setup): Setup the cell
+       data funcs.
+
+       * gtk/gtkcombobox.c (gtk_combo_box_key_press): Skip insensitive
+       rows.
+
+       * tests/testcombo.c (main): Make some rows insensitive.
+
 2004-05-26  Robert Ögren  <gtk@roboros.com>
 
        * gdk/win32/gdkinput-win32.c (_gdk_input_other_event): Send key
index d666a2512718116952d44e1eb8cfbd0895eaa431..c5d872d3b1fc1ae170ca5e1084a41a6b6972e774 100644 (file)
@@ -1,3 +1,49 @@
+Wed May 26 23:26:51 2004  Matthias Clasen  <maclas@gmx.de>
+
+       Support insensitive cells in tree views and combo boxes:
+       
+       * gtk/gtkcellrenderer.h: 
+       * gtk/gtkcellrenderer.c: Add a ::sensitive property.
+
+       * gtk/gtkcellrendererpixbuf.c (gtk_cell_renderer_pixbuf_render): 
+       * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_render): 
+       * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): 
+       Support drawing insensitive.
+
+       * gtk/gtkcellview.h: 
+       * gtk/gtkcellview.c (gtk_cell_view_get_cell_renderers): New 
+       function to obtain the cell renderers from a cell view. Also
+       export gtk_cell_view_set_cell_data().
+
+       * gtk/gtktreeselection.c (tree_column_is_sensitive):
+       * gtk/gtktreeselection.c (row_is_selectable): Helper functions
+       to determine whether all visible cells in a row are insensitive
+       and whether a row is selectable. A row is not selectable if the 
+       user function says so or if all visible cells are insensitive.
+       * gtk/gtktreeselection.c (_gtk_tree_selection_internal_select_node): 
+       * gtk/gtktreeselection.c (gtk_tree_selection_real_select_node): 
+       Use row_is_selectable().
+       
+       * gtk/gtkcombobox.c (row_is_sensitive): 
+       * gtk/gtkcombobox.c (tree_column_row_is_sensitive): 
+       * gtk/gtkcombobox.c (menu_row_is_sensitive): Helper functions
+       to determine row sensitivity in menu or list mode.
+
+       * gtk/gtkcombobox.c (update_menu_sensitivity): Helper function
+       to set up sensitivity menu items from the underlying rows.
+
+       * gtk/gtkcombobox.c (gtk_combo_box_popup): 
+       * gtk/gtkcombobox.c (gtk_combo_box_menu_button_press): Use
+       update_menu_sensitivity().
+               
+       * gtk/gtkcombobox.c (gtk_combo_box_list_setup): Setup the cell
+       data funcs.
+
+       * gtk/gtkcombobox.c (gtk_combo_box_key_press): Skip insensitive
+       rows.
+
+       * tests/testcombo.c (main): Make some rows insensitive.
+
 2004-05-26  Robert Ögren  <gtk@roboros.com>
 
        * gdk/win32/gdkinput-win32.c (_gdk_input_other_event): Send key
index d666a2512718116952d44e1eb8cfbd0895eaa431..c5d872d3b1fc1ae170ca5e1084a41a6b6972e774 100644 (file)
@@ -1,3 +1,49 @@
+Wed May 26 23:26:51 2004  Matthias Clasen  <maclas@gmx.de>
+
+       Support insensitive cells in tree views and combo boxes:
+       
+       * gtk/gtkcellrenderer.h: 
+       * gtk/gtkcellrenderer.c: Add a ::sensitive property.
+
+       * gtk/gtkcellrendererpixbuf.c (gtk_cell_renderer_pixbuf_render): 
+       * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_render): 
+       * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): 
+       Support drawing insensitive.
+
+       * gtk/gtkcellview.h: 
+       * gtk/gtkcellview.c (gtk_cell_view_get_cell_renderers): New 
+       function to obtain the cell renderers from a cell view. Also
+       export gtk_cell_view_set_cell_data().
+
+       * gtk/gtktreeselection.c (tree_column_is_sensitive):
+       * gtk/gtktreeselection.c (row_is_selectable): Helper functions
+       to determine whether all visible cells in a row are insensitive
+       and whether a row is selectable. A row is not selectable if the 
+       user function says so or if all visible cells are insensitive.
+       * gtk/gtktreeselection.c (_gtk_tree_selection_internal_select_node): 
+       * gtk/gtktreeselection.c (gtk_tree_selection_real_select_node): 
+       Use row_is_selectable().
+       
+       * gtk/gtkcombobox.c (row_is_sensitive): 
+       * gtk/gtkcombobox.c (tree_column_row_is_sensitive): 
+       * gtk/gtkcombobox.c (menu_row_is_sensitive): Helper functions
+       to determine row sensitivity in menu or list mode.
+
+       * gtk/gtkcombobox.c (update_menu_sensitivity): Helper function
+       to set up sensitivity menu items from the underlying rows.
+
+       * gtk/gtkcombobox.c (gtk_combo_box_popup): 
+       * gtk/gtkcombobox.c (gtk_combo_box_menu_button_press): Use
+       update_menu_sensitivity().
+               
+       * gtk/gtkcombobox.c (gtk_combo_box_list_setup): Setup the cell
+       data funcs.
+
+       * gtk/gtkcombobox.c (gtk_combo_box_key_press): Skip insensitive
+       rows.
+
+       * tests/testcombo.c (main): Make some rows insensitive.
+
 2004-05-26  Robert Ögren  <gtk@roboros.com>
 
        * gdk/win32/gdkinput-win32.c (_gdk_input_other_event): Send key
index d666a2512718116952d44e1eb8cfbd0895eaa431..c5d872d3b1fc1ae170ca5e1084a41a6b6972e774 100644 (file)
@@ -1,3 +1,49 @@
+Wed May 26 23:26:51 2004  Matthias Clasen  <maclas@gmx.de>
+
+       Support insensitive cells in tree views and combo boxes:
+       
+       * gtk/gtkcellrenderer.h: 
+       * gtk/gtkcellrenderer.c: Add a ::sensitive property.
+
+       * gtk/gtkcellrendererpixbuf.c (gtk_cell_renderer_pixbuf_render): 
+       * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_render): 
+       * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): 
+       Support drawing insensitive.
+
+       * gtk/gtkcellview.h: 
+       * gtk/gtkcellview.c (gtk_cell_view_get_cell_renderers): New 
+       function to obtain the cell renderers from a cell view. Also
+       export gtk_cell_view_set_cell_data().
+
+       * gtk/gtktreeselection.c (tree_column_is_sensitive):
+       * gtk/gtktreeselection.c (row_is_selectable): Helper functions
+       to determine whether all visible cells in a row are insensitive
+       and whether a row is selectable. A row is not selectable if the 
+       user function says so or if all visible cells are insensitive.
+       * gtk/gtktreeselection.c (_gtk_tree_selection_internal_select_node): 
+       * gtk/gtktreeselection.c (gtk_tree_selection_real_select_node): 
+       Use row_is_selectable().
+       
+       * gtk/gtkcombobox.c (row_is_sensitive): 
+       * gtk/gtkcombobox.c (tree_column_row_is_sensitive): 
+       * gtk/gtkcombobox.c (menu_row_is_sensitive): Helper functions
+       to determine row sensitivity in menu or list mode.
+
+       * gtk/gtkcombobox.c (update_menu_sensitivity): Helper function
+       to set up sensitivity menu items from the underlying rows.
+
+       * gtk/gtkcombobox.c (gtk_combo_box_popup): 
+       * gtk/gtkcombobox.c (gtk_combo_box_menu_button_press): Use
+       update_menu_sensitivity().
+               
+       * gtk/gtkcombobox.c (gtk_combo_box_list_setup): Setup the cell
+       data funcs.
+
+       * gtk/gtkcombobox.c (gtk_combo_box_key_press): Skip insensitive
+       rows.
+
+       * tests/testcombo.c (main): Make some rows insensitive.
+
 2004-05-26  Robert Ögren  <gtk@roboros.com>
 
        * gdk/win32/gdkinput-win32.c (_gdk_input_other_event): Send key
index 31fffdaea79678c0338da0c0cbd439af3ac63994..345766d5e0a3eaf1a777cdaf2522326402267541 100644 (file)
@@ -50,6 +50,7 @@ enum {
   PROP_ZERO,
   PROP_MODE,
   PROP_VISIBLE,
+  PROP_SENSITIVE,
   PROP_XALIGN,
   PROP_YALIGN,
   PROP_XPAD,
@@ -111,6 +112,7 @@ gtk_cell_renderer_init (GtkCellRenderer *cell)
   cell->yalign = 0.5;
   cell->xpad = 0;
   cell->ypad = 0;
+  cell->sensitive = TRUE;
 }
 
 static void
@@ -162,8 +164,14 @@ gtk_cell_renderer_class_init (GtkCellRendererClass *class)
                                                         P_("visible"),
                                                         P_("Display the cell"),
                                                         TRUE,
-                                                        G_PARAM_READABLE |
-                                                        G_PARAM_WRITABLE));
+                                                        G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+                                  PROP_SENSITIVE,
+                                  g_param_spec_boolean ("sensitive",
+                                                        P_("Sensitive"),
+                                                        P_("Display the cell sensitive"),
+                                                        TRUE,
+                                                        G_PARAM_READWRITE));
 
   g_object_class_install_property (object_class,
                                   PROP_XALIGN,
@@ -293,6 +301,9 @@ gtk_cell_renderer_get_property (GObject     *object,
     case PROP_VISIBLE:
       g_value_set_boolean (value, cell->visible);
       break;
+    case PROP_SENSITIVE:
+      g_value_set_boolean (value, cell->sensitive);
+      break;
     case PROP_XALIGN:
       g_value_set_float (value, cell->xalign);
       break;
@@ -355,6 +366,9 @@ gtk_cell_renderer_set_property (GObject      *object,
     case PROP_VISIBLE:
       cell->visible = g_value_get_boolean (value);
       break;
+    case PROP_SENSITIVE:
+      cell->sensitive = g_value_get_boolean (value);
+      break;
     case PROP_XALIGN:
       cell->xalign = g_value_get_float (value);
       break;
index 5b681aeb979d8048b004b7473f3a3d1cb979963c..d6cab83c4504296e718438db15228d195a41c6cb 100644 (file)
@@ -71,6 +71,7 @@ struct _GtkCellRenderer
   guint is_expander : 1;
   guint is_expanded : 1;
   guint cell_background_set : 1;
+  guint sensitive : 1;
 };
 
 struct _GtkCellRendererClass
index 43772fa9e2a76a72476a46a0f4038493c2a3f7dd..61cc5e83081c0d77d9f9597992ee08587d6b548d 100644 (file)
@@ -20,6 +20,7 @@
 #include <config.h>
 #include <stdlib.h>
 #include "gtkcellrendererpixbuf.h"
+#include "gtkiconfactory.h"
 #include "gtkintl.h"
 
 static void gtk_cell_renderer_pixbuf_get_property  (GObject                    *object,
@@ -72,6 +73,7 @@ struct _GtkCellRendererPixbufPrivate
   gchar *stock_id;
   GtkIconSize stock_size;
   gchar *stock_detail;
+  GdkPixbuf *insensitive;
 };
 
 
@@ -201,6 +203,9 @@ gtk_cell_renderer_pixbuf_finalize (GObject *object)
   if (priv->stock_detail)
     g_free (priv->stock_detail);
 
+  if (priv->insensitive)
+    g_object_unref (priv->insensitive);
+
   (* G_OBJECT_CLASS (parent_class)->finalize) (object);
 }
 
@@ -467,6 +472,36 @@ gtk_cell_renderer_pixbuf_render (GtkCellRenderer      *cell,
   pix_rect.width  -= cell->xpad * 2;
   pix_rect.height -= cell->ypad * 2;
 
+  if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE || !cell->sensitive)
+    {
+      if (!priv->insensitive)
+       {
+         GtkIconSource *source;
+      
+         source = gtk_icon_source_new ();
+         gtk_icon_source_set_pixbuf (source, pixbuf);
+         /* The size here is arbitrary; since size isn't
+          * wildcarded in the souce, it isn't supposed to be
+          * scaled by the engine function
+          */
+         gtk_icon_source_set_size (source, GTK_ICON_SIZE_SMALL_TOOLBAR);
+         gtk_icon_source_set_size_wildcarded (source, FALSE);
+         
+         priv->insensitive = gtk_style_render_icon (widget->style,
+                                                    source,
+                                                    gtk_widget_get_direction (widget),
+                                                    GTK_STATE_INSENSITIVE,
+                                                    /* arbitrary */
+                                                    (GtkIconSize)-1,
+                                                    widget,
+                                                    "gtkcellrendererpixbuf");
+
+         gtk_icon_source_free (source);
+       }
+      
+      pixbuf = priv->insensitive;
+    }
+
   if (gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect) &&
       gdk_rectangle_intersect (expose_area, &draw_rect, &draw_rect))
     gdk_draw_pixbuf (window,
index c3e090005717db726ab21e287794e4fabe37a170..83745154fc57d200ee5f6609162b3115125866cf 100644 (file)
@@ -1374,8 +1374,11 @@ gtk_cell_renderer_text_render (GtkCellRenderer      *cell,
 
   gtk_cell_renderer_text_get_size (cell, widget, cell_area, &x_offset, &y_offset, NULL, NULL);
 
-
-  if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
+  if (!cell->sensitive) 
+    {
+      state = GTK_STATE_INSENSITIVE;
+    }
+  else if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
     {
       if (GTK_WIDGET_HAS_FOCUS (widget))
        state = GTK_STATE_SELECTED;
index 7c4931869379ef43e217987d4ee6af1ba9f8041f..3b2a205ca7899910cd8eca2deaf5ee9da66c12b8 100644 (file)
@@ -348,7 +348,11 @@ gtk_cell_renderer_toggle_render (GtkCellRenderer      *cell,
   else
     shadow = celltoggle->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
 
-  if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
+  if (!cell->sensitive)
+    {
+      state = GTK_STATE_INSENSITIVE;
+    }
+  else if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
     {
       if (GTK_WIDGET_HAS_FOCUS (widget))
        state = GTK_STATE_SELECTED;
index 84dc2e7fdcd8051fb2fc096993cd5aae0450821c..14600a29c10dbbcef2aa7e65337c6a85efbdc964 100644 (file)
@@ -80,7 +80,6 @@ static void        gtk_cell_view_set_valuesv              (GtkCellView      *cel
                                                            va_list           args);
 static GtkCellViewCellInfo *gtk_cell_view_get_cell_info   (GtkCellView      *cellview,
                                                            GtkCellRenderer  *renderer);
-static void        gtk_cell_view_set_cell_data            (GtkCellView      *cellview);
 
 
 static void        gtk_cell_view_cell_layout_pack_start        (GtkCellLayout         *layout,
@@ -527,7 +526,7 @@ gtk_cell_view_get_cell_info (GtkCellView     *cellview,
   return NULL;
 }
 
-static void
+void
 gtk_cell_view_set_cell_data (GtkCellView *cellview)
 {
   GList *i;
@@ -979,3 +978,20 @@ gtk_cell_view_set_background_color (GtkCellView    *view,
         }
     }
 }
+
+GList *
+gtk_cell_view_get_cell_renderers (GtkCellView *cell_view)
+{
+  GList *retval = NULL, *list;
+
+  g_return_val_if_fail (cell_view != NULL, NULL);
+
+  for (list = cell_view->priv->cell_list; list; list = list->next)
+    {
+      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
+
+      retval = g_list_prepend (retval, info->cell);
+    }
+
+  return g_list_reverse (retval);
+}
index 5212b351a5fb9a9512a99b7537924a6fd65faa8e..844d505f8093b7e87d37724a97520d81955e71c3 100644 (file)
@@ -76,6 +76,8 @@ gboolean          gtk_cell_view_get_size_of_row         (GtkCellView     *cell_v
 
 void              gtk_cell_view_set_background_color    (GtkCellView     *cell_view,
                                                          const GdkColor  *color);
+void              gtk_cell_view_set_cell_data           (GtkCellView     *cellview);
+GList            *gtk_cell_view_get_cell_renderers      (GtkCellView     *cellview);
 
 G_END_DECLS
 
index eaca7a968009fe55c532033ea53851b26ff2ca24..1b539226b014ad22edb662e5f8a086710225e001 100644 (file)
@@ -1142,6 +1142,140 @@ gtk_combo_box_list_position (GtkComboBox *combo_box,
     *y -= *height;
 } 
 
+static gboolean
+menu_row_is_sensitive (GtkComboBox *combo_box,
+                      GtkWidget   *item)
+{
+  GtkWidget *cell_view;
+  GList *cells, *list;
+  gboolean sensitive;
+
+  cell_view = gtk_bin_get_child (GTK_BIN (item));
+  
+  gtk_cell_view_set_cell_data (GTK_CELL_VIEW (cell_view));
+  cells = gtk_cell_view_get_cell_renderers (GTK_CELL_VIEW (cell_view));
+
+  sensitive = FALSE;
+  list = cells;
+  while (list)
+    {
+      g_object_get (G_OBJECT (list->data), "sensitive", &sensitive, NULL);
+      
+      if (sensitive)
+       break;
+
+      list = list->next;
+    }
+  g_list_free (cells);
+
+  return sensitive;
+}
+                      
+
+static gboolean
+tree_column_row_is_sensitive (GtkComboBox *combo_box,
+                             GtkTreeIter *iter)
+{
+  GList *cells, *list;
+  gboolean sensitive;
+
+  if (!combo_box->priv->column)
+    return TRUE;
+
+  gtk_tree_view_column_cell_set_cell_data (combo_box->priv->column,
+                                          combo_box->priv->model,
+                                          iter, FALSE, FALSE);
+
+  cells = gtk_tree_view_column_get_cell_renderers (combo_box->priv->column);
+
+  sensitive = FALSE;
+  list = cells;
+  while (list)
+    {
+      g_object_get (G_OBJECT (list->data), "sensitive", &sensitive, NULL);
+      
+      if (sensitive)
+       break;
+
+      list = list->next;
+    }
+  g_list_free (cells);
+
+  return sensitive;
+}
+                      
+static gboolean
+row_is_sensitive (GtkComboBox *combo_box,
+                 gint         index)
+{
+  gboolean sensitive;
+
+  if (!combo_box->priv->model)
+    return TRUE;
+
+  if (GTK_IS_MENU (combo_box->priv->popup_widget))
+    {
+      GtkWidget *item;
+      GList *children, *child;
+
+      children = gtk_container_get_children (GTK_CONTAINER (combo_box->priv->popup_widget));
+      child = children;
+      if (GTK_IS_TEAROFF_MENU_ITEM (child->data))
+       child = child->next;
+      child = g_list_nth (child, index);
+      item = GTK_WIDGET (child->data);
+      g_list_free (children);
+
+      sensitive = menu_row_is_sensitive (combo_box, item);
+    }
+  else
+    {
+      GtkTreePath *path;
+      GtkTreeIter iter;
+
+      path = gtk_tree_path_new_from_indices (index, -1);
+      if (gtk_tree_model_get_iter (combo_box->priv->model, &iter, path))
+       sensitive = tree_column_row_is_sensitive (combo_box, &iter);
+      else
+       sensitive = TRUE;
+
+      gtk_tree_path_free (path);
+
+    }
+
+  return sensitive;
+}
+
+static void
+update_menu_sensitivity (GtkComboBox *combo_box)
+{
+  gint i, items;
+  GtkWidget *menu;
+  GList *children, *child;
+
+  if (!combo_box->priv->model)
+    return;
+
+  items = gtk_tree_model_iter_n_children (combo_box->priv->model, NULL);
+  menu = combo_box->priv->popup_widget;
+
+  children = gtk_container_get_children (GTK_CONTAINER (menu));
+  child = children;
+
+  if (GTK_IS_TEAROFF_MENU_ITEM (child->data))
+    child = child->next;
+
+  for (i = 0; i < items; i++, child = child->next)
+    {
+      GtkWidget *item = GTK_WIDGET (child->data);
+      gboolean sensitive;
+
+      sensitive = menu_row_is_sensitive (combo_box, item);
+      gtk_widget_set_sensitive (item, sensitive);
+    }
+  g_list_free (children);
+}
+
 /**
  * gtk_combo_box_popup:
  * @combo_box: a #GtkComboBox
@@ -1165,6 +1299,7 @@ gtk_combo_box_popup (GtkComboBox *combo_box)
 
   if (GTK_IS_MENU (combo_box->priv->popup_widget))
     {
+      update_menu_sensitivity (combo_box);
       gtk_menu_set_active (GTK_MENU (combo_box->priv->popup_widget),
                           combo_box->priv->active_item);
 
@@ -1957,7 +2092,7 @@ gtk_combo_box_menu_button_press (GtkWidget      *widget,
   if (event->type == GDK_BUTTON_PRESS && event->button == 1)
     {
       combo_box->priv->popup_in_progress = TRUE;
-      
+      update_menu_sensitivity (combo_box);
       gtk_menu_set_active (GTK_MENU (combo_box->priv->popup_widget),
                           combo_box->priv->active_item);
 
@@ -2295,6 +2430,10 @@ gtk_combo_box_list_setup (GtkComboBox *combo_box)
                                               j->data,
                                               GPOINTER_TO_INT (j->next->data));
         }
+
+      gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo_box->priv->column), 
+                                         info->cell, info->func, info->func_data, 
+                                         NULL);
     }
 
   if (combo_box->priv->active_item != -1)
@@ -2484,22 +2623,34 @@ gtk_combo_box_key_press (GtkWidget   *widget,
     case GDK_Down:
     case GDK_KP_Down:
       new_index = index + 1;
+      while (new_index < items && !row_is_sensitive (combo_box, new_index))
+       new_index++;
+      if (new_index == items)
+       new_index = index;
       break;
     case GDK_Up:
     case GDK_KP_Up:
       new_index = index - 1;
+      while (new_index >= 0 && !row_is_sensitive (combo_box, new_index))
+       new_index--;
+      if (new_index < 0)
+       new_index = index;
       break;
     case GDK_Page_Up:
     case GDK_KP_Page_Up:
     case GDK_Home: 
     case GDK_KP_Home:
       new_index = 0;
+      while (new_index < items - 1 && !row_is_sensitive (combo_box, new_index))
+       new_index++;
       break;
     case GDK_Page_Down:
     case GDK_KP_Page_Down:
     case GDK_End: 
     case GDK_KP_End:
       new_index = items - 1;
+      while (new_index > 0 && !row_is_sensitive (combo_box, new_index))
+       new_index--;
       break;
     default:
       return FALSE;
index 3ba806e9cb5846c5b4af99de73a17178c3b06d41..d0f7f0752a4777cf3c75c7c7e64d201ae5038672 100644 (file)
@@ -1279,6 +1279,73 @@ gtk_tree_selection_unselect_range (GtkTreeSelection *selection,
     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
 }
 
+static gboolean
+tree_column_is_sensitive (GtkTreeViewColumn *column,
+                         GtkTreeModel      *model,
+                         GtkTreeIter       *iter)
+{
+  GList *cells, *list;
+  gboolean sensitive;
+  gboolean visible;
+
+  gtk_tree_view_column_cell_set_cell_data (column, model,
+                                          iter, FALSE, FALSE);
+
+  cells = gtk_tree_view_column_get_cell_renderers (column);
+
+  list = cells;
+  while (list)
+    {
+      g_object_get (G_OBJECT (list->data), 
+                   "sensitive", &sensitive, 
+                   "visible", &visible,
+                   NULL);
+      
+      if (visible && sensitive)
+       break;
+
+      list = list->next;
+    }
+  g_list_free (cells);
+
+  return sensitive;
+}
+
+static gboolean
+row_is_selectable (GtkTreeSelection *selection,
+                  GtkRBNode        *node,
+                  GtkTreePath      *path)
+{
+  GList *list;
+  gboolean sensitive;
+  
+  sensitive = FALSE;
+  for (list = selection->tree_view->priv->columns; list && !sensitive; list = list->next)
+    {
+      GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
+      GtkTreeIter iter;
+
+      if (!column->visible)
+       continue;
+
+      if (gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path))
+       sensitive = tree_column_is_sensitive (column, selection->tree_view->priv->model, &iter);
+      else
+       sensitive = TRUE;
+    }
+
+  if (!sensitive)
+    return FALSE;
+
+  if (selection->user_func)
+    return (*selection->user_func) (selection, selection->tree_view->priv->model, path,
+                                   GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
+                                   selection->user_data);
+  else
+    return TRUE;
+}
+
+
 /* Called internally by gtktreeview.c It handles actually selecting the tree.
  */
 
@@ -1328,17 +1395,7 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
            {
              /* We only want to select the new node if we can unselect the old one,
               * and we can select the new one. */
-             if (selection->user_func)
-               {
-                 if ((*selection->user_func) (selection, selection->tree_view->priv->model, path,
-                                              GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
-                                              selection->user_data))
-                   dirty = TRUE;
-               }
-             else
-               {
-                 dirty = TRUE;
-               }
+             dirty = row_is_selectable (selection, node, path);
 
              /* if dirty is FALSE, we weren't able to select the new one, otherwise, we try to
               * unselect the new one
@@ -1455,15 +1512,7 @@ gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
     {
       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
-      if (selection->user_func)
-       {
-         if ((*selection->user_func) (selection, selection->tree_view->priv->model, path,
-                                       GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
-                                       selection->user_data))
-           selected = TRUE;
-       }
-      else
-       selected = TRUE;
+      selected = row_is_selectable (selection, node, path);
       gtk_tree_path_free (path);
     }
 
index 2fc79715db95d31e845019006bb13dc3aefcad20..157963d5836a4ffdc78def4e14d1007e25909b0d 100644 (file)
@@ -183,6 +183,26 @@ setup_combo_entry (GtkWidget *entry_box)
                                   "klaas");
 }
 
+static void
+set_sensitive (GtkCellLayout   *cell_layout,
+              GtkCellRenderer *cell,
+              GtkTreeModel    *tree_model,
+              GtkTreeIter     *iter,
+              gpointer         data)
+{
+  GtkTreePath *path;
+  gint *indices;
+  gboolean sensitive;
+
+  path = gtk_tree_model_get_path (tree_model, iter);
+  indices = gtk_tree_path_get_indices (path);
+
+  sensitive = indices[0] % 2;
+  gtk_tree_path_free (path);
+
+  g_object_set (cell, "sensitive", sensitive, NULL);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -259,6 +279,10 @@ main (int argc, char **argv)
         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer,
                                         "pixbuf", 0,
                                         NULL);
+       gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combobox),
+                                           renderer,
+                                           set_sensitive,
+                                           NULL, NULL);
 
         renderer = gtk_cell_renderer_text_new ();
         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox),
@@ -267,7 +291,10 @@ main (int argc, char **argv)
         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer,
                                         "text", 1,
                                         NULL);
-
+       gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combobox),
+                                           renderer,
+                                           set_sensitive,
+                                           NULL, NULL);
         gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 1);