summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorMatthias Clasen <matthiasc@src.gnome.org>2004-05-27 03:31:17 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2004-05-27 03:31:17 +0000
commit310fd268e7498582755fd21bcf5428794a832bc0 (patch)
tree9323eafee5beacd4743fd73599b1a82a11658958 /gtk
parent7c200f8a9c9985c483f6293d79d8b4192e2e6a4a (diff)
downloadgtk+-310fd268e7498582755fd21bcf5428794a832bc0.tar.gz
Support insensitive cells in tree views and combo boxes.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtkcellrenderer.c18
-rw-r--r--gtk/gtkcellrenderer.h1
-rw-r--r--gtk/gtkcellrendererpixbuf.c35
-rw-r--r--gtk/gtkcellrenderertext.c7
-rw-r--r--gtk/gtkcellrenderertoggle.c6
-rw-r--r--gtk/gtkcellview.c20
-rw-r--r--gtk/gtkcellview.h2
-rw-r--r--gtk/gtkcombobox.c153
-rw-r--r--gtk/gtktreeselection.c89
9 files changed, 303 insertions, 28 deletions
diff --git a/gtk/gtkcellrenderer.c b/gtk/gtkcellrenderer.c
index 31fffdaea7..345766d5e0 100644
--- a/gtk/gtkcellrenderer.c
+++ b/gtk/gtkcellrenderer.c
@@ -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;
diff --git a/gtk/gtkcellrenderer.h b/gtk/gtkcellrenderer.h
index 5b681aeb97..d6cab83c45 100644
--- a/gtk/gtkcellrenderer.h
+++ b/gtk/gtkcellrenderer.h
@@ -71,6 +71,7 @@ struct _GtkCellRenderer
guint is_expander : 1;
guint is_expanded : 1;
guint cell_background_set : 1;
+ guint sensitive : 1;
};
struct _GtkCellRendererClass
diff --git a/gtk/gtkcellrendererpixbuf.c b/gtk/gtkcellrendererpixbuf.c
index 43772fa9e2..61cc5e8308 100644
--- a/gtk/gtkcellrendererpixbuf.c
+++ b/gtk/gtkcellrendererpixbuf.c
@@ -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,
diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c
index c3e0900057..83745154fc 100644
--- a/gtk/gtkcellrenderertext.c
+++ b/gtk/gtkcellrenderertext.c
@@ -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;
diff --git a/gtk/gtkcellrenderertoggle.c b/gtk/gtkcellrenderertoggle.c
index 7c49318693..3b2a205ca7 100644
--- a/gtk/gtkcellrenderertoggle.c
+++ b/gtk/gtkcellrenderertoggle.c
@@ -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;
diff --git a/gtk/gtkcellview.c b/gtk/gtkcellview.c
index 84dc2e7fdc..14600a29c1 100644
--- a/gtk/gtkcellview.c
+++ b/gtk/gtkcellview.c
@@ -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);
+}
diff --git a/gtk/gtkcellview.h b/gtk/gtkcellview.h
index 5212b351a5..844d505f80 100644
--- a/gtk/gtkcellview.h
+++ b/gtk/gtkcellview.h
@@ -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
diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c
index eaca7a9680..1b539226b0 100644
--- a/gtk/gtkcombobox.c
+++ b/gtk/gtkcombobox.c
@@ -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;
diff --git a/gtk/gtktreeselection.c b/gtk/gtktreeselection.c
index 3ba806e9cb..d0f7f0752a 100644
--- a/gtk/gtktreeselection.c
+++ b/gtk/gtktreeselection.c
@@ -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);
}