summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'gtk')
-rw-r--r--gtk/Makefile.am1
-rw-r--r--gtk/gtkcellrenderer.h4
-rw-r--r--gtk/gtkcellrenderertext.c1000
-rw-r--r--gtk/gtkcellrenderertext.h31
-rw-r--r--gtk/gtkliststore.c11
-rw-r--r--gtk/gtkrbtree.c279
-rw-r--r--gtk/gtkrbtree.h25
-rw-r--r--gtk/gtkstyle.c88
-rw-r--r--gtk/gtktexttag.c56
-rw-r--r--gtk/gtktextview.c9
-rw-r--r--gtk/gtktreemodelsort.c2
-rw-r--r--gtk/gtktreeprivate.h3
-rw-r--r--gtk/gtktreeselection.c4
-rw-r--r--gtk/gtktreesortable.h27
-rw-r--r--gtk/gtktreestore.c13
-rw-r--r--gtk/gtktreeview.c372
-rw-r--r--gtk/gtktreeview.h3
-rw-r--r--gtk/gtktreeviewcolumn.c327
-rw-r--r--gtk/gtktreeviewcolumn.h42
19 files changed, 1805 insertions, 492 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 230f78445d..92b76f99aa 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -175,6 +175,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
gtktreemodelsimple.h \
gtktreemodelsort.h \
gtktreeselection.h \
+ gtktreesortable.h \
gtktreestore.h \
gtktreeview.h \
gtktreeviewcolumn.h \
diff --git a/gtk/gtkcellrenderer.h b/gtk/gtkcellrenderer.h
index bf18553957..27694571d3 100644
--- a/gtk/gtkcellrenderer.h
+++ b/gtk/gtkcellrenderer.h
@@ -32,7 +32,9 @@ typedef enum
{
GTK_CELL_RENDERER_SELECTED = 1 << 0,
GTK_CELL_RENDERER_PRELIT = 1 << 1,
- GTK_CELL_RENDERER_INSENSITIVE = 1 << 2
+ GTK_CELL_RENDERER_INSENSITIVE = 1 << 2,
+ /* this flag means the cell is in the sort column/row */
+ GTK_CELL_RENDERER_SORTED = 1 << 3
} GtkCellRendererState;
#define GTK_TYPE_CELL_RENDERER (gtk_cell_renderer_get_type ())
diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c
index 751659fc5c..7ad67797cb 100644
--- a/gtk/gtkcellrenderertext.c
+++ b/gtk/gtkcellrenderertext.c
@@ -23,6 +23,7 @@
static void gtk_cell_renderer_text_init (GtkCellRendererText *celltext);
static void gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class);
+static void gtk_cell_renderer_text_finalize (GObject *object);
static void gtk_cell_renderer_text_get_property (GObject *object,
guint param_id,
@@ -47,21 +48,48 @@ static void gtk_cell_renderer_text_render (GtkCellRenderer *cell,
guint flags);
+
enum {
- PROP_ZERO,
+ PROP_0,
+
PROP_TEXT,
- PROP_FONT,
+
+ /* Style args */
PROP_BACKGROUND,
- PROP_BACKGROUND_GDK,
PROP_FOREGROUND,
+ PROP_BACKGROUND_GDK,
PROP_FOREGROUND_GDK,
+ PROP_FONT,
+ PROP_FONT_DESC,
+ PROP_FAMILY,
+ PROP_STYLE,
+ PROP_VARIANT,
+ PROP_WEIGHT,
+ PROP_STRETCH,
+ PROP_SIZE,
+ PROP_SIZE_POINTS,
+ PROP_EDITABLE,
PROP_STRIKETHROUGH,
PROP_UNDERLINE,
- PROP_EDITABLE,
- PROP_ITALIC,
- PROP_BOLD
+ PROP_RISE,
+
+ /* Whether-a-style-arg-is-set args */
+ PROP_BACKGROUND_SET,
+ PROP_FOREGROUND_SET,
+ PROP_FAMILY_SET,
+ PROP_STYLE_SET,
+ PROP_VARIANT_SET,
+ PROP_WEIGHT_SET,
+ PROP_STRETCH_SET,
+ PROP_SIZE_SET,
+ PROP_EDITABLE_SET,
+ PROP_STRIKETHROUGH_SET,
+ PROP_UNDERLINE_SET,
+ PROP_RISE_SET
};
+static gpointer parent_class;
+
GtkType
gtk_cell_renderer_text_get_type (void)
{
@@ -91,12 +119,10 @@ gtk_cell_renderer_text_get_type (void)
static void
gtk_cell_renderer_text_init (GtkCellRendererText *celltext)
{
- celltext->attr_list = pango_attr_list_new ();
GTK_CELL_RENDERER (celltext)->xalign = 0.0;
GTK_CELL_RENDERER (celltext)->yalign = 0.5;
GTK_CELL_RENDERER (celltext)->xpad = 2;
GTK_CELL_RENDERER (celltext)->ypad = 2;
- celltext->underline = FALSE;
}
static void
@@ -105,87 +131,241 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = gtk_cell_renderer_text_finalize;
+
object_class->get_property = gtk_cell_renderer_text_get_property;
object_class->set_property = gtk_cell_renderer_text_set_property;
cell_class->get_size = gtk_cell_renderer_text_get_size;
cell_class->render = gtk_cell_renderer_text_render;
-
+
g_object_class_install_property (object_class,
- PROP_TEXT,
- g_param_spec_string ("text",
- _("Text String"),
- _("The text of the renderer."),
- "",
- G_PARAM_READABLE |
- G_PARAM_WRITABLE));
+ PROP_TEXT,
+ g_param_spec_string ("text",
+ _("Text"),
+ _("Text to render"),
+ NULL,
+ G_PARAM_READWRITE));
g_object_class_install_property (object_class,
- PROP_FONT,
- g_param_spec_string ("font",
- _("Font String"),
- _("The string of the font."),
- "",
- G_PARAM_WRITABLE));
-
+ PROP_BACKGROUND,
+ g_param_spec_string ("background",
+ _("Background color name"),
+ _("Background color as a string"),
+ NULL,
+ G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_BACKGROUND_GDK,
+ g_param_spec_boxed ("background_gdk",
+ _("Background color"),
+ _("Background color as a GdkColor"),
+ GTK_TYPE_GDK_COLOR,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_FOREGROUND,
+ g_param_spec_string ("foreground",
+ _("Foreground color name"),
+ _("Foreground color as a string"),
+ NULL,
+ G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_FOREGROUND_GDK,
+ g_param_spec_boxed ("foreground_gdk",
+ _("Foreground color"),
+ _("Foreground color as a GdkColor"),
+ GTK_TYPE_GDK_COLOR,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+
+ g_object_class_install_property (object_class,
+ PROP_EDITABLE,
+ g_param_spec_boolean ("editable",
+ _("Editable"),
+ _("Whether the text can be modified by the user"),
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_FONT,
+ g_param_spec_string ("font",
+ _("Font"),
+ _("Font description as a string"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
g_object_class_install_property (object_class,
- PROP_BACKGROUND,
- g_param_spec_string ("background",
- _("Background Color string"),
- _("The color for the background of the text."),
- "white",
- G_PARAM_WRITABLE));
+ PROP_FONT_DESC,
+ g_param_spec_boxed ("font_desc",
+ _("Font"),
+ _("Font description as a PangoFontDescription struct"),
+ GTK_TYPE_PANGO_FONT_DESCRIPTION,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
g_object_class_install_property (object_class,
- PROP_FOREGROUND,
- g_param_spec_string ("foreground",
- _("Foreground Color string"),
- _("The color for the background of the text."),
- "black",
- G_PARAM_WRITABLE));
+ PROP_FAMILY,
+ g_param_spec_string ("family",
+ _("Font family"),
+ _("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_STYLE,
+ g_param_spec_enum ("style",
+ _("Font style"),
+ _("Font style"),
+ PANGO_TYPE_STYLE,
+ PANGO_STYLE_NORMAL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_VARIANT,
+ g_param_spec_enum ("variant",
+ _("Font variant"),
+ _("Font variant"),
+ PANGO_TYPE_VARIANT,
+ PANGO_VARIANT_NORMAL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
g_object_class_install_property (object_class,
- PROP_STRIKETHROUGH,
- g_param_spec_boolean ("strikethrough",
- _("Strikethrough"),
- _("Draw a line through the text."),
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_WRITABLE));
+ PROP_WEIGHT,
+ g_param_spec_int ("weight",
+ _("Font weight"),
+ _("Font weight"),
+ 0,
+ G_MAXINT,
+ PANGO_WEIGHT_NORMAL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
g_object_class_install_property (object_class,
- PROP_UNDERLINE,
- g_param_spec_boolean ("underline",
- _("Underline"),
- _("Underline the text."),
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_WRITABLE));
+ PROP_STRETCH,
+ g_param_spec_enum ("stretch",
+ _("Font stretch"),
+ _("Font stretch"),
+ PANGO_TYPE_STRETCH,
+ PANGO_STRETCH_NORMAL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
g_object_class_install_property (object_class,
- PROP_EDITABLE,
- g_param_spec_boolean ("editable",
- _("Editable"),
- _("Make the text editable."),
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_WRITABLE));
+ PROP_SIZE,
+ g_param_spec_int ("size",
+ _("Font size"),
+ _("Font size"),
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_SIZE_POINTS,
+ g_param_spec_double ("size_points",
+ _("Font points"),
+ _("Font size in points"),
+ 0.0,
+ G_MAXDOUBLE,
+ 0.0,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
g_object_class_install_property (object_class,
- PROP_ITALIC,
- g_param_spec_boolean ("italic",
- _("Italic"),
- _("Make the text italic."),
- FALSE,
- G_PARAM_WRITABLE));
+ PROP_RISE,
+ g_param_spec_int ("rise",
+ _("Rise"),
+ _("Offset of text above the baseline (below the baseline if rise is negative)"),
+ -G_MAXINT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+
+ g_object_class_install_property (object_class,
+ PROP_STRIKETHROUGH,
+ g_param_spec_boolean ("strikethrough",
+ _("Strikethrough"),
+ _("Whether to strike through the text"),
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
g_object_class_install_property (object_class,
- PROP_BOLD,
- g_param_spec_boolean ("bold",
- _("Bold"),
- _("Make the text bold."),
- FALSE,
- G_PARAM_WRITABLE));
+ PROP_UNDERLINE,
+ g_param_spec_enum ("underline",
+ _("Underline"),
+ _("Style of underline for this text"),
+ PANGO_TYPE_UNDERLINE,
+ PANGO_UNDERLINE_NONE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ /* Style props are set or not */
+
+#define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE))
+
+ ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET,
+ _("Background set"),
+ _("Whether this tag affects the background color"));
+
+ ADD_SET_PROP ("foreground_set", PROP_FOREGROUND_SET,
+ _("Foreground set"),
+ _("Whether this tag affects the foreground color"));
+
+ ADD_SET_PROP ("editable_set", PROP_EDITABLE_SET,
+ _("Editability set"),
+ _("Whether this tag affects text editability"));
+
+ ADD_SET_PROP ("family_set", PROP_FAMILY_SET,
+ _("Font family set"),
+ _("Whether this tag affects the font family"));
+
+ ADD_SET_PROP ("style_set", PROP_STYLE_SET,
+ _("Font style set"),
+ _("Whether this tag affects the font style"));
+
+ ADD_SET_PROP ("variant_set", PROP_VARIANT_SET,
+ _("Font variant set"),
+ _("Whether this tag affects the font variant"));
+
+ ADD_SET_PROP ("weight_set", PROP_WEIGHT_SET,
+ _("Font weight set"),
+ _("Whether this tag affects the font weight"));
+
+ ADD_SET_PROP ("stretch_set", PROP_STRETCH_SET,
+ _("Font stretch set"),
+ _("Whether this tag affects the font stretch"));
+
+ ADD_SET_PROP ("size_set", PROP_SIZE_SET,
+ _("Font size set"),
+ _("Whether this tag affects the font size"));
+
+ ADD_SET_PROP ("rise_set", PROP_RISE_SET,
+ _("Rise set"),
+ _("Whether this tag affects the rise"));
+
+ ADD_SET_PROP ("strikethrough_set", PROP_STRIKETHROUGH_SET,
+ _("Strikethrough set"),
+ _("Whether this tag affects strikethrough"));
+
+ ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET,
+ _("Underline set"),
+ _("Whether this tag affects underlining"));
+}
+
+static void
+gtk_cell_renderer_text_finalize (GObject *object)
+{
+ GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
+
+ if (celltext->font.family_name)
+ g_free (celltext->font.family_name);
+
+ if (celltext->text)
+ g_free (celltext->text);
+
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
}
static void
@@ -196,26 +376,146 @@ gtk_cell_renderer_text_get_property (GObject *object,
const gchar *trailer)
{
GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
- PangoAttrIterator *attr_iter;
- PangoAttribute *attr;
switch (param_id)
{
case PROP_TEXT:
g_value_set_string (value, celltext->text);
break;
- case PROP_STRIKETHROUGH:
- attr_iter = pango_attr_list_get_iterator (celltext->attr_list);
- attr = pango_attr_iterator_get (attr_iter,
- PANGO_ATTR_STRIKETHROUGH);
- g_value_set_boolean (value, ((PangoAttrInt*) attr)->value);
+
+ case PROP_BACKGROUND_GDK:
+ {
+ GdkColor color;
+
+ color.red = celltext->background.red;
+ color.green = celltext->background.green;
+ color.blue = celltext->background.blue;
+
+ g_value_set_boxed (value, &color);
+ }
break;
- case PROP_UNDERLINE:
- g_value_set_boolean (value, celltext->underline);
+
+ case PROP_FOREGROUND_GDK:
+ {
+ GdkColor color;
+
+ color.red = celltext->foreground.red;
+ color.green = celltext->foreground.green;
+ color.blue = celltext->foreground.blue;
+
+ g_value_set_boxed (value, &color);
+ }
+ break;
+
+ case PROP_FONT:
+ {
+ /* FIXME GValue imposes a totally gratuitous string copy
+ * here, we could just hand off string ownership
+ */
+ gchar *str = pango_font_description_to_string (&celltext->font);
+ g_value_set_string (value, str);
+ g_free (str);
+ }
break;
+
+ case PROP_FONT_DESC:
+ g_value_set_boxed (value, &celltext->font);
+ break;
+
+ case PROP_FAMILY:
+ g_value_set_string (value, celltext->font.family_name);
+ break;
+
+ case PROP_STYLE:
+ g_value_set_enum (value, celltext->font.style);
+ break;
+
+ case PROP_VARIANT:
+ g_value_set_enum (value, celltext->font.variant);
+ break;
+
+ case PROP_WEIGHT:
+ g_value_set_int (value, celltext->font.weight);
+ break;
+
+ case PROP_STRETCH:
+ g_value_set_enum (value, celltext->font.stretch);
+ break;
+
+ case PROP_SIZE:
+ g_value_set_int (value, celltext->font.size);
+ break;
+
+ case PROP_SIZE_POINTS:
+ g_value_set_double (value, ((double)celltext->font.size) / (double)PANGO_SCALE);
+ break;
+
case PROP_EDITABLE:
g_value_set_boolean (value, celltext->editable);
break;
+
+ case PROP_STRIKETHROUGH:
+ g_value_set_boolean (value, celltext->strikethrough);
+ break;
+
+ case PROP_UNDERLINE:
+ g_value_set_enum (value, celltext->underline_style);
+ break;
+
+ case PROP_RISE:
+ g_value_set_int (value, celltext->rise);
+ break;
+
+ case PROP_BACKGROUND_SET:
+ g_value_set_boolean (value, celltext->background_set);
+ break;
+
+ case PROP_FOREGROUND_SET:
+ g_value_set_boolean (value, celltext->foreground_set);
+ break;
+
+ case PROP_FAMILY_SET:
+ g_value_set_boolean (value, celltext->family_set);
+ break;
+
+ case PROP_STYLE_SET:
+ g_value_set_boolean (value, celltext->style_set);
+ break;
+
+ case PROP_VARIANT_SET:
+ g_value_set_boolean (value, celltext->variant_set);
+ break;
+
+ case PROP_WEIGHT_SET:
+ g_value_set_boolean (value, celltext->weight_set);
+ break;
+
+ case PROP_STRETCH_SET:
+ g_value_set_boolean (value, celltext->stretch_set);
+ break;
+
+ case PROP_SIZE_SET:
+ g_value_set_boolean (value, celltext->size_set);
+ break;
+
+ case PROP_EDITABLE_SET:
+ g_value_set_boolean (value, celltext->editable_set);
+ break;
+
+ case PROP_STRIKETHROUGH_SET:
+ g_value_set_boolean (value, celltext->strikethrough_set);
+ break;
+
+ case PROP_UNDERLINE_SET:
+ g_value_set_boolean (value, celltext->underline_set);
+ break;
+
+ case PROP_RISE_SET:
+ g_value_set_boolean (value, celltext->rise_set);
+ break;
+
+ case PROP_BACKGROUND:
+ case PROP_FOREGROUND:
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -224,6 +524,121 @@ gtk_cell_renderer_text_get_property (GObject *object,
static void
+set_bg_color (GtkCellRendererText *celltext,
+ GdkColor *color)
+{
+ if (color)
+ {
+ if (!celltext->background_set)
+ {
+ celltext->background_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "background_set");
+ }
+
+ celltext->background.red = color->red;
+ celltext->background.green = color->green;
+ celltext->background.blue = color->blue;
+ }
+ else
+ {
+ if (celltext->background_set)
+ {
+ celltext->background_set = FALSE;
+ g_object_notify (G_OBJECT (celltext), "background_set");
+ }
+ }
+}
+
+
+static void
+set_fg_color (GtkCellRendererText *celltext,
+ GdkColor *color)
+{
+ if (color)
+ {
+ if (!celltext->foreground_set)
+ {
+ celltext->foreground_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "foreground_set");
+ }
+
+ celltext->foreground.red = color->red;
+ celltext->foreground.green = color->green;
+ celltext->foreground.blue = color->blue;
+ }
+ else
+ {
+ if (celltext->foreground_set)
+ {
+ celltext->foreground_set = FALSE;
+ g_object_notify (G_OBJECT (celltext), "foreground_set");
+ }
+ }
+}
+
+static void
+set_font_description (GtkCellRendererText *celltext,
+ PangoFontDescription *font_desc)
+{
+ if (font_desc != NULL)
+ {
+ /* pango_font_description_from_string() will sometimes return
+ * a NULL family or -1 size, so handle those cases.
+ */
+
+ if (font_desc->family_name)
+ g_object_set (G_OBJECT (celltext),
+ "family", font_desc->family_name,
+ NULL);
+
+ if (font_desc->size >= 0)
+ g_object_set (G_OBJECT (celltext),
+ "size", font_desc->size,
+ NULL);
+
+ g_object_set (G_OBJECT (celltext),
+ "style", font_desc->style,
+ "variant", font_desc->variant,
+ "weight", font_desc->weight,
+ "stretch", font_desc->stretch,
+ NULL);
+ }
+ else
+ {
+ if (celltext->family_set)
+ {
+ celltext->family_set = FALSE;
+ g_object_notify (G_OBJECT (celltext), "family_set");
+ }
+ if (celltext->style_set)
+ {
+ celltext->style_set = FALSE;
+ g_object_notify (G_OBJECT (celltext), "style_set");
+ }
+ if (celltext->variant_set)
+ {
+ celltext->variant_set = FALSE;
+ g_object_notify (G_OBJECT (celltext), "variant_set");
+ }
+ if (celltext->weight_set)
+ {
+ celltext->weight_set = FALSE;
+ g_object_notify (G_OBJECT (celltext), "weight_set");
+ }
+ if (celltext->stretch_set)
+ {
+ celltext->stretch_set = FALSE;
+ g_object_notify (G_OBJECT (celltext), "stretch_set");
+ }
+ if (celltext->size_set)
+ {
+ celltext->size_set = FALSE;
+ g_object_notify (G_OBJECT (celltext), "size_set");
+ }
+ }
+}
+
+static void
gtk_cell_renderer_text_set_property (GObject *object,
guint param_id,
const GValue *value,
@@ -232,99 +647,206 @@ gtk_cell_renderer_text_set_property (GObject *object,
{
GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
- GdkColor color;
- PangoFontDescription *font_desc;
- gchar *string;
- PangoAttribute *attribute;
- gchar *font;
-
switch (param_id)
{
case PROP_TEXT:
- g_free (celltext->text);
- celltext->text = g_value_dup_string (value);
- break;
- case PROP_FONT:
- font = g_value_get_string (value);
-
- if (font)
- {
- font_desc = pango_font_description_from_string (font);
- attribute = pango_attr_font_desc_new (font_desc);
- attribute->start_index = 0;
- attribute->end_index = G_MAXINT;
- pango_font_description_free (font_desc);
- pango_attr_list_change (celltext->attr_list,
- attribute);
- }
+ if (celltext->text)
+ g_free (celltext->text);
+ celltext->text = g_strdup (g_value_get_string (value));
break;
+
case PROP_BACKGROUND:
- string = g_value_get_string (value);
- if (string && gdk_color_parse (string, &color))
- {
- attribute = pango_attr_background_new (color.red,
- color.green,
- color.blue);
- attribute->start_index = 0;
- attribute->end_index = G_MAXINT;
- pango_attr_list_change (celltext->attr_list,
- attribute);
- }
- break;
- case PROP_BACKGROUND_GDK:
+ {
+ GdkColor color;
+
+ if (gdk_color_parse (g_value_get_string (value), &color))
+ set_bg_color (celltext, &color);
+ else
+ g_warning ("Don't know color `%s'", g_value_get_string (value));
+
+ g_object_notify (G_OBJECT (celltext), "background_gdk");
+ }
break;
+
case PROP_FOREGROUND:
- string = g_value_get_string (value);
- if (string && gdk_color_parse (string, &color))
- {
- attribute = pango_attr_foreground_new (color.red,
- color.green,
- color.blue);
- attribute->start_index = 0;
- attribute->end_index = G_MAXINT;
- pango_attr_list_change (celltext->attr_list,
- attribute);
- }
+ {
+ GdkColor color;
+
+ if (gdk_color_parse (g_value_get_string (value), &color))
+ set_bg_color (celltext, &color);
+ else
+ g_warning ("Don't know color `%s'", g_value_get_string (value));
+
+ g_object_notify (G_OBJECT (celltext), "foreground_gdk");
+ }
+ break;
+
+ case PROP_BACKGROUND_GDK:
+ set_bg_color (celltext, g_value_get_boxed (value));
break;
+
case PROP_FOREGROUND_GDK:
+ set_fg_color (celltext, g_value_get_boxed (value));
+ break;
+
+ case PROP_FONT:
+ {
+ PangoFontDescription *font_desc = NULL;
+ const gchar *name;
+
+ name = g_value_get_string (value);
+
+ if (name)
+ font_desc = pango_font_description_from_string (name);
+
+ set_font_description (celltext, font_desc);
+
+ if (font_desc)
+ pango_font_description_free (font_desc);
+ }
+ break;
+
+ case PROP_FONT_DESC:
+ set_font_description (celltext, g_value_get_boxed (value));
+ break;
+
+ case PROP_FAMILY:
+ if (celltext->font.family_name)
+ g_free (celltext->font.family_name);
+ celltext->font.family_name = g_strdup (g_value_get_string (value));
+
+ celltext->family_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "family_set");
+ g_object_notify (G_OBJECT (celltext), "font_desc");
+ g_object_notify (G_OBJECT (celltext), "font");
+ break;
+
+ case PROP_STYLE:
+ celltext->font.style = g_value_get_enum (value);
+
+ celltext->style_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "style_set");
+ g_object_notify (G_OBJECT (celltext), "font_desc");
+ g_object_notify (G_OBJECT (celltext), "font");
+ break;
+
+ case PROP_VARIANT:
+ celltext->font.variant = g_value_get_enum (value);
+
+ celltext->variant_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "variant_set");
+ g_object_notify (G_OBJECT (celltext), "font_desc");
+ g_object_notify (G_OBJECT (celltext), "font");
+ break;
+
+ case PROP_WEIGHT:
+ celltext->font.weight = g_value_get_int (value);
+
+ celltext->weight_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "weight_set");
+ g_object_notify (G_OBJECT (celltext), "font_desc");
+ g_object_notify (G_OBJECT (celltext), "font");
+ break;
+
+ case PROP_STRETCH:
+ celltext->font.stretch = g_value_get_enum (value);
+
+ celltext->stretch_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "stretch_set");
+ g_object_notify (G_OBJECT (celltext), "font_desc");
+ g_object_notify (G_OBJECT (celltext), "font");
+ break;
+
+ case PROP_SIZE:
+ celltext->font.size = g_value_get_int (value);
+
+ celltext->size_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "size_set");
+ g_object_notify (G_OBJECT (celltext), "font_desc");
+ g_object_notify (G_OBJECT (celltext), "font");
break;
+
+ case PROP_SIZE_POINTS:
+ celltext->font.size = g_value_get_double (value) * PANGO_SCALE;
+
+ celltext->size_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "size_set");
+ g_object_notify (G_OBJECT (celltext), "font_desc");
+ g_object_notify (G_OBJECT (celltext), "font");
+ break;
+
+ case PROP_EDITABLE:
+ celltext->editable = g_value_get_boolean (value);
+ celltext->editable_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "editable_set");
+ break;
+
case PROP_STRIKETHROUGH:
- attribute = pango_attr_strikethrough_new (g_value_get_boolean (value));
- attribute->start_index = 0;
- attribute->end_index = G_MAXINT;
- pango_attr_list_change (celltext->attr_list,
- attribute);
+ celltext->strikethrough = g_value_get_boolean (value);
+ celltext->strikethrough_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "strikethrough_set");
break;
+
case PROP_UNDERLINE:
- celltext->underline = g_value_get_boolean (value);
- attribute = pango_attr_underline_new (celltext->underline ?
- PANGO_UNDERLINE_SINGLE :
- PANGO_UNDERLINE_NONE);
- attribute->start_index = 0;
- attribute->end_index = G_MAXINT;
- pango_attr_list_change (celltext->attr_list,
- attribute);
+ celltext->underline_style = g_value_get_enum (value);
+ celltext->underline_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "underline_set");
break;
- case PROP_EDITABLE:
+
+ case PROP_RISE:
+ celltext->rise = g_value_get_int (value);
+ celltext->rise_set = TRUE;
+ g_object_notify (G_OBJECT (celltext), "rise_set");
+ break;
+
+ case PROP_BACKGROUND_SET:
+ celltext->background_set = g_value_get_boolean (value);
+ break;
+
+ case PROP_FOREGROUND_SET:
+ celltext->foreground_set = g_value_get_boolean (value);
+ break;
+
+ case PROP_FAMILY_SET:
+ celltext->family_set = g_value_get_boolean (value);
+ break;
+
+ case PROP_STYLE_SET:
+ celltext->style_set = g_value_get_boolean (value);
break;
- case PROP_ITALIC:
- attribute = pango_attr_style_new (g_value_get_boolean (value) ?
- PANGO_STYLE_ITALIC :
- PANGO_STYLE_NORMAL);
- attribute->start_index = 0;
- attribute->end_index = G_MAXINT;
- pango_attr_list_change (celltext->attr_list,
- attribute);
- break;
- case PROP_BOLD:
- attribute = pango_attr_weight_new (g_value_get_boolean (value) ?
- PANGO_WEIGHT_BOLD :
- PANGO_WEIGHT_NORMAL);
- attribute->start_index = 0;
- attribute->end_index = G_MAXINT;
- pango_attr_list_change (celltext->attr_list,
- attribute);
+
+ case PROP_VARIANT_SET:
+ celltext->variant_set = g_value_get_boolean (value);
+ break;
+
+ case PROP_WEIGHT_SET:
+ celltext->weight_set = g_value_get_boolean (value);
+ break;
+
+ case PROP_STRETCH_SET:
+ celltext->stretch_set = g_value_get_boolean (value);
+ break;
+
+ case PROP_SIZE_SET:
+ celltext->size_set = g_value_get_boolean (value);
+ break;
+
+ case PROP_EDITABLE_SET:
+ celltext->editable_set = g_value_get_boolean (value);
break;
+
+ case PROP_STRIKETHROUGH_SET:
+ celltext->strikethrough_set = g_value_get_boolean (value);
+ break;
+
+ case PROP_UNDERLINE_SET:
+ celltext->underline_set = g_value_get_boolean (value);
+ break;
+
+ case PROP_RISE_SET:
+ celltext->rise_set = g_value_get_boolean (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -347,7 +869,108 @@ gtk_cell_renderer_text_set_property (GObject *object,
GtkCellRenderer *
gtk_cell_renderer_text_new (void)
{
- return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_text_get_type ()));
+ return GTK_CELL_RENDERER (g_object_new (gtk_cell_renderer_text_get_type (), NULL));
+}
+
+static void
+add_attr (PangoAttrList *attr_list,
+ PangoAttribute *attr)
+{
+ attr->start_index = 0;
+ attr->end_index = G_MAXINT;
+
+ pango_attr_list_insert (attr_list, attr);
+}
+
+static PangoLayout*
+get_layout (GtkCellRendererText *celltext,
+ GtkWidget *widget,
+ gboolean will_render,
+ GtkCellRendererState flags)
+{
+ PangoAttrList *attr_list;
+ PangoLayout *layout;
+ PangoUnderline uline;
+
+ layout = gtk_widget_create_pango_layout (widget, celltext->text);
+
+ attr_list = pango_attr_list_new ();
+
+ if (will_render)
+ {
+ /* Add options that affect appearance but not size */
+
+ /* note that background doesn't go here, since it affects
+ * background_area not the PangoLayout area
+ */
+
+ if (celltext->foreground_set)
+ {
+ PangoColor color;
+
+ color = celltext->foreground;
+
+ add_attr (attr_list,
+ pango_attr_foreground_new (color.red, color.green, color.blue));
+ }
+
+ if (celltext->strikethrough_set)
+ add_attr (attr_list,
+ pango_attr_strikethrough_new (celltext->strikethrough));
+ }
+
+ if (celltext->family_set &&
+ celltext->font.family_name)
+ add_attr (attr_list, pango_attr_family_new (celltext->font.family_name));
+
+ if (celltext->style_set)
+ add_attr (attr_list, pango_attr_style_new (celltext->font.style));
+
+ if (celltext->variant_set)
+ add_attr (attr_list, pango_attr_variant_new (celltext->font.variant));
+
+ if (celltext->weight_set)
+ add_attr (attr_list, pango_attr_weight_new (celltext->font.weight));
+
+ if (celltext->stretch_set)
+ add_attr (attr_list, pango_attr_stretch_new (celltext->font.stretch));
+
+ if (celltext->size_set &&
+ celltext->font.size >= 0)
+ add_attr (attr_list, pango_attr_size_new (celltext->font.size));
+
+ if (celltext->underline_set)
+ uline = celltext->underline_style;
+ else
+ uline = PANGO_UNDERLINE_NONE;
+
+ if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT)
+ {
+ switch (uline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ uline = PANGO_UNDERLINE_SINGLE;
+ break;
+
+ case PANGO_UNDERLINE_SINGLE:
+ uline = PANGO_UNDERLINE_DOUBLE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (uline != PANGO_UNDERLINE_NONE)
+ add_attr (attr_list, pango_attr_underline_new (celltext->underline_style));
+
+ if (celltext->rise_set)
+ add_attr (attr_list, pango_attr_rise_new (celltext->rise));
+
+ pango_layout_set_attributes (layout, attr_list);
+ pango_layout_set_width (layout, -1);
+
+ return layout;
}
static void
@@ -359,21 +982,9 @@ gtk_cell_renderer_text_get_size (GtkCellRenderer *cell,
GtkCellRendererText *celltext = (GtkCellRendererText *)cell;
PangoRectangle rect;
PangoLayout *layout;
- PangoAttribute *attr;
- PangoUnderline underline;
- layout = gtk_widget_create_pango_layout (widget, celltext->text);
- underline = celltext->underline ?
- PANGO_UNDERLINE_DOUBLE :
- PANGO_UNDERLINE_NONE;
-
- attr = pango_attr_underline_new (underline);
- attr->start_index = 0;
- attr->end_index = G_MAXINT;
-
- pango_attr_list_change (celltext->attr_list, attr);
- pango_layout_set_attributes (layout, celltext->attr_list);
- pango_layout_set_width (layout, -1);
+ layout = get_layout (celltext, widget, FALSE, 0);
+
pango_layout_get_pixel_extents (layout, NULL, &rect);
if (width)
@@ -398,40 +1009,15 @@ gtk_cell_renderer_text_render (GtkCellRenderer *cell,
GtkCellRendererText *celltext = (GtkCellRendererText *) cell;
PangoRectangle rect;
PangoLayout *layout;
- PangoAttribute *attr;
- PangoUnderline underline;
GtkStateType state;
gint real_xoffset;
gint real_yoffset;
- layout = gtk_widget_create_pango_layout (widget, celltext->text);
+ layout = get_layout (celltext, widget, TRUE, flags);
- if (celltext->underline)
- underline = PANGO_UNDERLINE_SINGLE;
- else
- underline = PANGO_UNDERLINE_NONE;
-
- attr = pango_attr_underline_new (underline);
- attr->start_index = 0;
- attr->end_index = G_MAXINT;
- pango_attr_list_change (celltext->attr_list, attr);
- pango_layout_set_attributes (layout, celltext->attr_list);
-
- pango_layout_set_width (layout, -1);
pango_layout_get_pixel_extents (layout, NULL, &rect);
- if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT)
- underline = (celltext->underline) ? PANGO_UNDERLINE_DOUBLE:PANGO_UNDERLINE_SINGLE;
- else
- underline = (celltext->underline) ? PANGO_UNDERLINE_SINGLE:PANGO_UNDERLINE_NONE;
-
- attr = pango_attr_underline_new (underline);
- attr->start_index = 0;
- attr->end_index = G_MAXINT;
- pango_attr_list_change (celltext->attr_list, attr);
- pango_layout_set_attributes (layout, celltext->attr_list);
-
real_xoffset = cell->xalign * (cell_area->width - rect.width - (2 * cell->xpad));
real_xoffset = MAX (real_xoffset, 0) + cell->xpad;
real_yoffset = cell->yalign * (cell_area->height - rect.height - (2 * cell->ypad));
@@ -441,6 +1027,30 @@ gtk_cell_renderer_text_render (GtkCellRenderer *cell,
state = GTK_STATE_SELECTED;
else
state = GTK_STATE_NORMAL;
+
+ if (celltext->background_set && state != GTK_STATE_SELECTED)
+ {
+ GdkColor color;
+ GdkGC *gc;
+
+ color.red = celltext->background.red;
+ color.green = celltext->background.green;
+ color.blue = celltext->background.blue;
+
+ gc = gdk_gc_new (window);
+
+ gdk_gc_set_rgb_fg_color (gc, &color);
+
+ gdk_draw_rectangle (window,
+ gc,
+ TRUE,
+ background_area->x,
+ background_area->y,
+ background_area->width,
+ background_area->height);
+
+ g_object_unref (G_OBJECT (gc));
+ }
gtk_paint_layout (widget->style,
window,
diff --git a/gtk/gtkcellrenderertext.h b/gtk/gtkcellrenderertext.h
index 762705413c..b2270b3de0 100644
--- a/gtk/gtkcellrenderertext.h
+++ b/gtk/gtkcellrenderertext.h
@@ -43,10 +43,37 @@ struct _GtkCellRendererText
/*< private >*/
gchar *text;
- PangoAttrList *attr_list;
+ PangoFontDescription font;
+ PangoColor foreground;
+ PangoColor background;
+ PangoUnderline underline_style;
+
+ gint rise;
+
+ guint strikethrough : 1;
+
+ /* editable feature doesn't work */
guint editable : 1;
- guint underline : 1;
+
+ /* font elements set */
+ guint family_set : 1;
+ guint style_set : 1;
+ guint variant_set : 1;
+ guint weight_set : 1;
+ guint stretch_set : 1;
+ guint size_set : 1;
+
+ guint foreground_set : 1;
+ guint background_set : 1;
+
+ guint underline_set : 1;
+
+ guint rise_set : 1;
+
+ guint strikethrough_set : 1;
+
+ guint editable_set : 1;
};
struct _GtkCellRendererTextClass
diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c
index 619594894e..e740dd2bde 100644
--- a/gtk/gtkliststore.c
+++ b/gtk/gtkliststore.c
@@ -1250,7 +1250,6 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
&src_iter,
src_path))
{
- g_print ("can't get source path as iter\n");
goto out;
}
@@ -1266,8 +1265,6 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
&dest_iter);
retval = TRUE;
-
- g_print ("prepending to list\n");
}
else
{
@@ -1280,11 +1277,7 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
&dest_iter,
&tmp_iter);
retval = TRUE;
-
- g_print ("inserting into list\n");
}
- else
- g_print ("can't get iter to insert after\n");
}
gtk_tree_path_free (prev);
@@ -1304,9 +1297,6 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
{
copy_iter = _gtk_tree_data_list_node_copy (dl,
list_store->column_headers[col]);
-
- g_print ("copied col %d type %s\n", col,
- g_type_name (list_store->column_headers[col]));
if (copy_head == NULL)
copy_head = copy_iter;
@@ -1332,7 +1322,6 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
/* FIXME maybe add some data targets eventually, or handle text
* targets in the simple case.
*/
- g_print ("not accepting target\n");
}
out:
diff --git a/gtk/gtkrbtree.c b/gtk/gtkrbtree.c
index e8bbf2d9d0..2765599a5d 100644
--- a/gtk/gtkrbtree.c
+++ b/gtk/gtkrbtree.c
@@ -110,6 +110,7 @@ _gtk_rbnode_new (GtkRBTree *tree,
node->right = tree->nil;
node->parent = tree->nil;
node->flags = GTK_RBNODE_RED;
+ node->parity = 1;
node->count = 1;
node->children = NULL;
node->offset = height;
@@ -122,6 +123,17 @@ _gtk_rbnode_free (GtkRBNode *node)
G_LOCK (current_allocator);
node->left = current_allocator->free_nodes;
current_allocator->free_nodes = node;
+ if (gtk_debug_flags & GTK_DEBUG_TREE)
+ {
+ /* unfortunately node->left has to continue to point to
+ * a node...
+ */
+ node->right = (gpointer) 0xdeadbeef;
+ node->parent = (gpointer) 0xdeadbeef;
+ node->offset = 56789;
+ node->count = 56789;
+ node->flags = 0;
+ }
G_UNLOCK (current_allocator);
}
@@ -130,6 +142,7 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree,
GtkRBNode *node)
{
gint node_height, right_height;
+ guint node_parity, right_parity;
GtkRBNode *right = node->right;
g_return_if_fail (node != tree->nil);
@@ -143,6 +156,15 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree,
(right->right?right->right->offset:0) -
(right->children?right->children->root->offset:0);
+ node_parity = node->parity -
+ (node->left?node->left->parity:0) -
+ (node->right?node->right->parity:0) -
+ (node->children?node->children->root->parity:0);
+ right_parity = right->parity -
+ (right->left?right->left->parity:0) -
+ (right->right?right->right->parity:0) -
+ (right->children?right->children->root->parity:0);
+
node->right = right->left;
if (right->left != tree->nil)
right->left->parent = node;
@@ -167,6 +189,7 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree,
(node->right?node->right->count:0);
right->count = 1 + (right->left?right->left->count:0) +
(right->right?right->right->count:0);
+
node->offset = node_height +
(node->left?node->left->offset:0) +
(node->right?node->right->offset:0) +
@@ -175,6 +198,15 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree,
(right->left?right->left->offset:0) +
(right->right?right->right->offset:0) +
(right->children?right->children->root->offset:0);
+
+ node->parity = node_parity +
+ (node->left?node->left->parity:0) +
+ (node->right?node->right->parity:0) +
+ (node->children?node->children->root->parity:0);
+ right->parity = right_parity +
+ (right->left?right->left->parity:0) +
+ (right->right?right->right->parity:0) +
+ (right->children?right->children->root->parity:0);
}
static void
@@ -182,6 +214,7 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree,
GtkRBNode *node)
{
gint node_height, left_height;
+ guint node_parity, left_parity;
GtkRBNode *left = node->left;
g_return_if_fail (node != tree->nil);
@@ -195,6 +228,15 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree,
(left->right?left->right->offset:0) -
(left->children?left->children->root->offset:0);
+ node_parity = node->parity -
+ (node->left?node->left->parity:0) -
+ (node->right?node->right->parity:0) -
+ (node->children?node->children->root->parity:0);
+ left_parity = left->parity -
+ (left->left?left->left->parity:0) -
+ (left->right?left->right->parity:0) -
+ (left->children?left->children->root->parity:0);
+
node->left = left->right;
if (left->right != tree->nil)
left->right->parent = node;
@@ -222,6 +264,7 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree,
(node->right?node->right->count:0);
left->count = 1 + (left->left?left->left->count:0) +
(left->right?left->right->count:0);
+
node->offset = node_height +
(node->left?node->left->offset:0) +
(node->right?node->right->offset:0) +
@@ -230,6 +273,15 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree,
(left->left?left->left->offset:0) +
(left->right?left->right->offset:0) +
(left->children?left->children->root->offset:0);
+
+ node->parity = node_parity +
+ (node->left?node->left->parity:0) +
+ (node->right?node->right->parity:0) +
+ (node->children?node->children->root->parity:0);
+ left->parity = left_parity +
+ (left->left?left->left->parity:0) +
+ (left->right?left->right->parity:0) +
+ (left->children?left->children->root->parity:0);
}
static void
@@ -412,6 +464,7 @@ _gtk_rbtree_new (void)
retval->nil->flags = GTK_RBNODE_BLACK;
retval->nil->count = 0;
retval->nil->offset = 0;
+ retval->nil->parity = 0;
retval->root = retval->nil;
return retval;
@@ -451,12 +504,21 @@ _gtk_rbtree_remove (GtkRBTree *tree)
GtkRBNode *tmp_node;
gint height = tree->root->offset;
+
+ if (gtk_debug_flags & GTK_DEBUG_TREE)
+ _gtk_rbtree_test (G_STRLOC, tree);
+
tmp_tree = tree->parent_tree;
tmp_node = tree->parent_node;
while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
{
tmp_node->offset -= height;
+
+ /* If the removed tree was odd, flip all parents */
+ if (tree->root->parity)
+ tmp_node->parity = !tmp_node->parity;
+
tmp_node = tmp_node->parent;
if (tmp_node == tmp_tree->nil)
{
@@ -464,7 +526,13 @@ _gtk_rbtree_remove (GtkRBTree *tree)
tmp_tree = tmp_tree->parent_tree;
}
}
+
+ tmp_tree = tree->parent_tree;
+
_gtk_rbtree_free (tree);
+
+ if (gtk_debug_flags & GTK_DEBUG_TREE)
+ _gtk_rbtree_test (G_STRLOC, tmp_tree);
}
@@ -476,8 +544,11 @@ _gtk_rbtree_insert_after (GtkRBTree *tree,
GtkRBNode *node;
gboolean right = TRUE;
GtkRBNode *tmp_node;
- GtkRBTree *tmp_tree;
+ GtkRBTree *tmp_tree;
+ if (gtk_debug_flags & GTK_DEBUG_TREE)
+ _gtk_rbtree_test (G_STRLOC, tree);
+
if (current != NULL && current->right != tree->nil)
{
current = current->right;
@@ -513,6 +584,8 @@ _gtk_rbtree_insert_after (GtkRBTree *tree,
* started in. */
if (tmp_tree == tree)
tmp_node->count++;
+
+ tmp_node->parity += 1;
tmp_node->offset += height;
tmp_node = tmp_node->parent;
if (tmp_node == tmp_tree->nil)
@@ -524,7 +597,7 @@ _gtk_rbtree_insert_after (GtkRBTree *tree,
_gtk_rbtree_insert_fixup (tree, node);
if (gtk_debug_flags & GTK_DEBUG_TREE)
- _gtk_rbtree_test (tree);
+ _gtk_rbtree_test (G_STRLOC, tree);
return node;
}
@@ -539,6 +612,9 @@ _gtk_rbtree_insert_before (GtkRBTree *tree,
GtkRBNode *tmp_node;
GtkRBTree *tmp_tree;
+ if (gtk_debug_flags & GTK_DEBUG_TREE)
+ _gtk_rbtree_test (G_STRLOC, tree);
+
if (current != NULL && current->left != tree->nil)
{
current = current->left;
@@ -574,6 +650,8 @@ _gtk_rbtree_insert_before (GtkRBTree *tree,
* started in. */
if (tmp_tree == tree)
tmp_node->count++;
+
+ tmp_node->parity += 1;
tmp_node->offset += height;
tmp_node = tmp_node->parent;
if (tmp_node == tmp_tree->nil)
@@ -585,7 +663,7 @@ _gtk_rbtree_insert_before (GtkRBTree *tree,
_gtk_rbtree_insert_fixup (tree, node);
if (gtk_debug_flags & GTK_DEBUG_TREE)
- _gtk_rbtree_test (tree);
+ _gtk_rbtree_test (G_STRLOC, tree);
return node;
}
@@ -671,6 +749,41 @@ _gtk_rbtree_node_find_offset (GtkRBTree *tree,
}
gint
+_gtk_rbtree_node_find_parity (GtkRBTree *tree,
+ GtkRBNode *node)
+{
+ GtkRBNode *last;
+ gint retval;
+
+ g_assert (node);
+ g_assert (node->left);
+
+ retval = node->left->parity;
+
+ while (tree && node && node != tree->nil)
+ {
+ last = node;
+ node = node->parent;
+
+ /* Add left branch, plus children, iff we came from the right */
+ if (node->right == last)
+ retval += node->parity - node->right->parity;
+
+ if (node == tree->nil)
+ {
+ node = tree->parent_node;
+ tree = tree->parent_tree;
+
+ /* Add the parent node, plus the left branch. */
+ if (node)
+ retval += node->left->parity + 1; /* 1 == GTK_RBNODE_GET_PARITY() */
+ }
+ }
+
+ return retval % 2;
+}
+
+gint
_gtk_rbtree_find_offset (GtkRBTree *tree,
gint height,
GtkRBTree **new_tree,
@@ -734,14 +847,20 @@ _gtk_rbtree_remove_node (GtkRBTree *tree,
GtkRBNode *node)
{
GtkRBNode *x, *y;
-
+ GtkRBTree *tmp_tree;
+ GtkRBNode *tmp_node;
+
g_return_if_fail (tree != NULL);
g_return_if_fail (node != NULL);
+
/* make sure we're deleting a node that's actually in the tree */
for (x = node; x->parent != tree->nil; x = x->parent)
;
g_return_if_fail (x == tree->root);
+ if (gtk_debug_flags & GTK_DEBUG_TREE)
+ _gtk_rbtree_test (G_STRLOC, tree);
+
if (node->left == tree->nil || node->right == tree->nil)
{
y = node;
@@ -753,9 +872,31 @@ _gtk_rbtree_remove_node (GtkRBTree *tree,
while (y->left != tree->nil)
y = y->left;
}
+
+ /* adjust count only beneath tree */
for (x = y; x != tree->nil; x = x->parent)
x->count--;
- y->count = node->count;
+
+ /* y->count = node->count; */
+
+ /* offsets and parity adjust all the way up through parent trees */
+
+ tmp_tree = tree;
+ tmp_node = y;
+
+ while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
+ {
+ /* tmp_node->offset -= y->offset; */
+ tmp_node->parity -= (guint) 1; /* parity of y is always 1 */
+
+ tmp_node = tmp_node->parent;
+ if (tmp_node == tmp_tree->nil)
+ {
+ tmp_node = tmp_tree->parent_node;
+ tmp_tree = tmp_tree->parent_tree;
+ }
+ }
+
/* x is y's only child */
if (y->left != tree->nil)
x = y->left;
@@ -778,13 +919,10 @@ _gtk_rbtree_remove_node (GtkRBTree *tree,
if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_BLACK)
_gtk_rbtree_remove_node_fixup (tree, x);
- G_LOCK (current_allocator);
- y->left = current_allocator->free_nodes;
- current_allocator->free_nodes = y;
- G_UNLOCK (current_allocator);
+ _gtk_rbnode_free (y);
if (gtk_debug_flags & GTK_DEBUG_TREE)
- _gtk_rbtree_test (tree);
+ _gtk_rbtree_test (G_STRLOC, tree);
}
GtkRBNode *
@@ -989,6 +1127,9 @@ _count_nodes (GtkRBTree *tree,
if (node == tree->nil)
return 0;
+ g_assert (node->left);
+ g_assert (node->right);
+
res = (_count_nodes (tree, node->left) +
_count_nodes (tree, node->right) + 1);
@@ -997,41 +1138,113 @@ _count_nodes (GtkRBTree *tree,
return res;
}
-void
-_gtk_rbtree_test (GtkRBTree *tree)
+static guint
+get_parity (GtkRBNode *node)
{
- if ((_count_nodes (tree, tree->root->left) +
- _count_nodes (tree, tree->root->right) + 1) == tree->root->count)
- g_print ("Tree passed\n");
+ guint child_total = 0;
+ guint rem;
+
+ /* The parity of a node is node->parity minus
+ * the parity of left, right, and children.
+ *
+ * This is equivalent to saying that if left, right, children
+ * sum to 0 parity, then node->parity is the parity of node,
+ * and if left, right, children are odd parity, then
+ * node->parity is the reverse of the node's parity.
+ */
+
+ child_total += (guint) node->left->parity;
+ child_total += (guint) node->right->parity;
+
+ if (node->children)
+ child_total += (guint) node->children->root->parity;
+
+ rem = child_total % 2;
+
+ if (rem == 0)
+ return node->parity;
else
- g_print ("Tree failed\n");
+ return !node->parity;
+}
+static guint
+count_parity (GtkRBTree *tree,
+ GtkRBNode *node)
+{
+ guint res;
+
+ if (node == tree->nil)
+ return 0;
+
+ res =
+ count_parity (tree, node->left) +
+ count_parity (tree, node->right) +
+ (guint)1 +
+ (node->children ? count_parity (node->children, node->children->root) : 0);
+
+ res = res % (guint)2;
+
+ if (res != node->parity)
+ g_print ("parity incorrect for node\n");
+
+ if (get_parity (node) != 1)
+ g_error ("Node has incorrect parity %d", get_parity (node));
+
+ return res;
}
static void
-_gtk_rbtree_test_height_helper (GtkRBTree *tree,
- GtkRBNode *node,
- gint height)
+_gtk_rbtree_test_height (GtkRBTree *tree,
+ GtkRBNode *node)
{
- if (node == tree->nil)
- return;
+ gint computed_offset = 0;
- if (node->offset -
- (node->left?node->left->offset:0) -
- (node->right?node->right->offset:0) -
- (node->children?node->children->root->offset:0) != height)
- g_error ("tree failed\n");
+ /* This whole test is sort of a useless truism. */
+
+ if (node->left != tree->nil)
+ computed_offset += node->left->offset;
- _gtk_rbtree_test_height_helper (tree, node->left, height);
- _gtk_rbtree_test_height_helper (tree, node->right, height);
- if (node->children)
- _gtk_rbtree_test_height_helper (node->children, node->children->root, height);
+ if (node->right != tree->nil)
+ computed_offset += node->right->offset;
+
+ if (node->children && node->children->root != node->children->nil)
+ computed_offset += node->children->root->offset;
+
+ if (GTK_RBNODE_GET_HEIGHT (node) + computed_offset != node->offset)
+ g_error ("node has broken offset\n");
+ if (node->left != tree->nil)
+ _gtk_rbtree_test_height (tree, node->left);
+
+ if (node->right != tree->nil)
+ _gtk_rbtree_test_height (tree, node->right);
+
+ if (node->children && node->children->root != node->children->nil)
+ _gtk_rbtree_test_height (node->children, node->children->root);
}
void
-_gtk_rbtree_test_height (GtkRBTree *tree,
- gint height)
+_gtk_rbtree_test (const gchar *where,
+ GtkRBTree *tree)
{
- _gtk_rbtree_test_height_helper (tree, tree->root, height);
+ GtkRBTree *tmp_tree;
+
+ /* Test the entire tree */
+ tmp_tree = tree;
+ while (tmp_tree->parent_tree)
+ tmp_tree = tmp_tree->parent_tree;
+
+ g_print ("%s: whole tree offset is %d\n", where, tmp_tree->root->offset);
+
+ if (tmp_tree->root != tmp_tree->nil)
+ {
+ g_assert ((_count_nodes (tmp_tree, tmp_tree->root->left) +
+ _count_nodes (tmp_tree, tmp_tree->root->right) + 1) == tmp_tree->root->count);
+
+
+ _gtk_rbtree_test_height (tmp_tree, tmp_tree->root);
+
+ g_assert (count_parity (tmp_tree, tmp_tree->root) == tmp_tree->root->parity);
+ }
}
+
diff --git a/gtk/gtkrbtree.h b/gtk/gtkrbtree.h
index 40c779320c..eea9160b62 100644
--- a/gtk/gtkrbtree.h
+++ b/gtk/gtkrbtree.h
@@ -33,6 +33,7 @@ typedef enum
GTK_RBNODE_IS_SELECTED = 1 << 3,
GTK_RBNODE_IS_PRELIT = 1 << 4,
GTK_RBNODE_IS_VIEW = 1 << 5
+
} GtkRBNodeColor;
typedef struct _GtkRBTree GtkRBTree;
@@ -53,7 +54,20 @@ struct _GtkRBTree
struct _GtkRBNode
{
- guint flags;
+ guint flags : 14;
+
+ /* We keep track of whether the aggregate count of children plus 1
+ * for the node itself comes to an even number. The parity flag is
+ * the total count of children mod 2, where the total count of
+ * children gets computed in the same way that the total offset gets
+ * computed. i.e. not the same as the "count" field below which
+ * doesn't include children. We could replace parity with a
+ * full-size int field here, and then take % 2 to get the parity flag,
+ * but that would use extra memory.
+ */
+
+ guint parity : 1;
+
GtkRBNode *left;
GtkRBNode *right;
GtkRBNode *parent;
@@ -62,13 +76,15 @@ struct _GtkRBNode
* i.e. node->left->count + node->right->count + 1
*/
gint count;
-
+
/* this is the total of sizes of
* node->left, node->right, our own height, and the height
* of all trees in ->children, iff children exists because
* the thing is expanded.
*/
gint offset;
+
+ /* Child trees */
GtkRBTree *children;
};
@@ -101,6 +117,8 @@ void _gtk_rbtree_node_set_height (GtkRBTree *tree,
gint height);
gint _gtk_rbtree_node_find_offset (GtkRBTree *tree,
GtkRBNode *node);
+gint _gtk_rbtree_node_find_parity (GtkRBTree *tree,
+ GtkRBNode *node);
gint _gtk_rbtree_find_offset (GtkRBTree *tree,
gint offset,
GtkRBTree **new_tree,
@@ -127,7 +145,8 @@ gint _gtk_rbtree_get_depth (GtkRBTree *tree);
/* This func just checks the integrity of the tree */
/* It will go away later. */
-void _gtk_rbtree_test (GtkRBTree *tree);
+void _gtk_rbtree_test (const gchar *where,
+ GtkRBTree *tree);
#ifdef __cplusplus
diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c
index 30c75cf907..7b6c04e01b 100644
--- a/gtk/gtkstyle.c
+++ b/gtk/gtkstyle.c
@@ -2416,6 +2416,29 @@ gtk_default_draw_box (GtkStyle *style,
x, y, width, height);
}
+static GdkGC*
+get_darkened_gc (GdkWindow *window,
+ GdkColor *color,
+ gint darken_count)
+{
+ GdkColor src = *color;
+ GdkColor shaded;
+ GdkGC *gc;
+
+ gc = gdk_gc_new (window);
+
+ while (darken_count)
+ {
+ gtk_style_shade (&src, &shaded, 1.3);
+ src = shaded;
+ --darken_count;
+ }
+
+ gdk_gc_set_rgb_fg_color (gc, &shaded);
+
+ return gc;
+}
+
static void
gtk_default_draw_flat_box (GtkStyle *style,
GdkWindow *window,
@@ -2430,6 +2453,7 @@ gtk_default_draw_flat_box (GtkStyle *style,
gint height)
{
GdkGC *gc1;
+ GdkGC *freeme = NULL;
g_return_if_fail (GTK_IS_STYLE (style));
g_return_if_fail (window != NULL);
@@ -2443,14 +2467,60 @@ gtk_default_draw_flat_box (GtkStyle *style,
if (detail)
{
- if (!strcmp ("text", detail) && state_type == GTK_STATE_SELECTED)
- gc1 = style->bg_gc[GTK_STATE_SELECTED];
- else if (!strcmp ("viewportbin", detail))
- gc1 = style->bg_gc[GTK_STATE_NORMAL];
- else if (!strcmp ("entry_bg", detail))
- gc1 = style->base_gc[state_type];
+ if (state_type == GTK_STATE_SELECTED)
+ {
+ if (!strcmp ("text", detail))
+ gc1 = style->bg_gc[GTK_STATE_SELECTED];
+ else if (!strcmp ("cell_even_sorted", detail) ||
+ !strcmp ("cell_odd_sorted", detail) ||
+ !strcmp ("cell_even_ruled_sorted", detail) ||
+ !strcmp ("cell_odd_ruled_sorted", detail))
+ {
+ freeme = get_darkened_gc (window, &style->bg[state_type], 1);
+ gc1 = freeme;
+ }
+ else
+ {
+ gc1 = style->bg_gc[state_type];
+ }
+ }
else
- gc1 = style->bg_gc[state_type];
+ {
+ if (!strcmp ("viewportbin", detail))
+ gc1 = style->bg_gc[GTK_STATE_NORMAL];
+ else if (!strcmp ("entry_bg", detail))
+ gc1 = style->base_gc[state_type];
+
+ /* For trees: even rows are base color, odd rows are a shade of
+ * the base color, the sort column is a shade of the original color
+ * for that row.
+ */
+
+ /* FIXME when we have style properties, clean this up.
+ */
+
+ else if (!strcmp ("cell_even", detail) ||
+ !strcmp ("cell_odd", detail) ||
+ !strcmp ("cell_even_ruled", detail))
+ {
+ gc1 = style->base_gc[state_type];
+ }
+ else if (!strcmp ("cell_even_sorted", detail) ||
+ !strcmp ("cell_odd_sorted", detail) ||
+ !strcmp ("cell_odd_ruled", detail) ||
+ !strcmp ("cell_even_ruled_sorted", detail))
+ {
+ freeme = get_darkened_gc (window, &style->base[state_type], 1);
+ gc1 = freeme;
+ }
+ else if (!strcmp ("cell_odd_ruled_sorted", detail))
+ {
+ freeme = get_darkened_gc (window, &style->base[state_type], 2);
+ gc1 = freeme;
+ }
+ else
+ gc1 = style->bg_gc[state_type];
+ }
}
else
gc1 = style->bg_gc[state_type];
@@ -2475,6 +2545,10 @@ gtk_default_draw_flat_box (GtkStyle *style,
gtk_style_apply_default_background (style, window,
widget && !GTK_WIDGET_NO_WINDOW (widget),
state_type, area, x, y, width, height);
+
+
+ if (freeme)
+ g_object_unref (G_OBJECT (freeme));
}
static void
diff --git a/gtk/gtktexttag.c b/gtk/gtktexttag.c
index 153f3417e1..4340000ff9 100644
--- a/gtk/gtktexttag.c
+++ b/gtk/gtktexttag.c
@@ -106,8 +106,6 @@ enum {
/* Whether-a-style-arg-is-set args */
PROP_BACKGROUND_SET,
PROP_FOREGROUND_SET,
- PROP_BACKGROUND_GDK_SET,
- PROP_FOREGROUND_GDK_SET,
PROP_BACKGROUND_STIPPLE_SET,
PROP_FOREGROUND_STIPPLE_SET,
PROP_FAMILY_SET,
@@ -507,10 +505,6 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
_("Background full height set"),
_("Whether this tag affects background height"));
- ADD_SET_PROP ("background_gdk_set", PROP_BACKGROUND_GDK_SET,
- _("Background set"),
- _("Whether this tag affects the background color"));
-
ADD_SET_PROP ("background_stipple_set", PROP_BACKGROUND_STIPPLE_SET,
_("Background stipple set"),
_("Whether this tag affects the background stipple"));
@@ -519,10 +513,6 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
_("Foreground set"),
_("Whether this tag affects the foreground color"));
- ADD_SET_PROP ("foreground_gdk_set", PROP_FOREGROUND_GDK_SET,
- _("Foreground set"),
- _("Whether this tag affects the foreground color"));
-
ADD_SET_PROP ("foreground_stipple_set", PROP_FOREGROUND_STIPPLE_SET,
_("Foreground stipple set"),
_("Whether this tag affects the foreground stipple"));
@@ -814,6 +804,8 @@ gtk_text_tag_set_property (GObject *object,
set_bg_color (text_tag, &color);
else
g_warning ("Don't know color `%s'", g_value_get_string (value));
+
+ g_object_notify (G_OBJECT (text_tag), "background_gdk");
}
break;
@@ -825,6 +817,8 @@ gtk_text_tag_set_property (GObject *object,
set_fg_color (text_tag, &color);
else
g_warning ("Don't know color `%s'", g_value_get_string (value));
+
+ g_object_notify (G_OBJECT (text_tag), "foreground_gdk");
}
break;
@@ -847,7 +841,7 @@ gtk_text_tag_set_property (GObject *object,
GdkBitmap *bitmap = g_value_get_as_pointer (value);
text_tag->bg_stipple_set = TRUE;
- g_object_notify (G_OBJECT (text_tag), "bg_stipple_set");
+ g_object_notify (G_OBJECT (text_tag), "background_stipple_set");
if (text_tag->values->appearance.bg_stipple != bitmap)
{
@@ -867,7 +861,7 @@ gtk_text_tag_set_property (GObject *object,
GdkBitmap *bitmap = g_value_get_as_pointer (value);
text_tag->fg_stipple_set = TRUE;
- g_object_notify (G_OBJECT (text_tag), "fg_stipple_set");
+ g_object_notify (G_OBJECT (text_tag), "foreground_stipple_set");
if (text_tag->values->appearance.fg_stipple != bitmap)
{
@@ -895,8 +889,8 @@ gtk_text_tag_set_property (GObject *object,
set_font_description (text_tag, font_desc);
if (font_desc)
- pango_font_description_free (font_desc);
-
+ pango_font_description_free (font_desc);
+
size_changed = TRUE;
}
break;
@@ -919,6 +913,8 @@ gtk_text_tag_set_property (GObject *object,
text_tag->values->font.family_name = g_strdup (g_value_get_string (value));
text_tag->family_set = TRUE;
g_object_notify (G_OBJECT (text_tag), "family_set");
+ g_object_notify (G_OBJECT (text_tag), "font_desc");
+ g_object_notify (G_OBJECT (text_tag), "font");
size_changed = TRUE;
break;
@@ -926,6 +922,8 @@ gtk_text_tag_set_property (GObject *object,
text_tag->values->font.style = g_value_get_enum (value);
text_tag->style_set = TRUE;
g_object_notify (G_OBJECT (text_tag), "style_set");
+ g_object_notify (G_OBJECT (text_tag), "font_desc");
+ g_object_notify (G_OBJECT (text_tag), "font");
size_changed = TRUE;
break;
@@ -933,6 +931,8 @@ gtk_text_tag_set_property (GObject *object,
text_tag->values->font.variant = g_value_get_enum (value);
text_tag->variant_set = TRUE;
g_object_notify (G_OBJECT (text_tag), "variant_set");
+ g_object_notify (G_OBJECT (text_tag), "font_desc");
+ g_object_notify (G_OBJECT (text_tag), "font");
size_changed = TRUE;
break;
@@ -940,6 +940,8 @@ gtk_text_tag_set_property (GObject *object,
text_tag->values->font.weight = g_value_get_int (value);
text_tag->weight_set = TRUE;
g_object_notify (G_OBJECT (text_tag), "weight_set");
+ g_object_notify (G_OBJECT (text_tag), "font_desc");
+ g_object_notify (G_OBJECT (text_tag), "font");
size_changed = TRUE;
break;
@@ -947,20 +949,28 @@ gtk_text_tag_set_property (GObject *object,
text_tag->values->font.stretch = g_value_get_enum (value);
text_tag->stretch_set = TRUE;
g_object_notify (G_OBJECT (text_tag), "stretch_set");
+ g_object_notify (G_OBJECT (text_tag), "font_desc");
+ g_object_notify (G_OBJECT (text_tag), "font");
size_changed = TRUE;
break;
case PROP_SIZE:
text_tag->values->font.size = g_value_get_int (value);
text_tag->size_set = TRUE;
+ g_object_notify (G_OBJECT (text_tag), "size_points");
g_object_notify (G_OBJECT (text_tag), "size_set");
+ g_object_notify (G_OBJECT (text_tag), "font_desc");
+ g_object_notify (G_OBJECT (text_tag), "font");
size_changed = TRUE;
break;
case PROP_SIZE_POINTS:
text_tag->values->font.size = g_value_get_double (value) * PANGO_SCALE;
text_tag->size_set = TRUE;
+ g_object_notify (G_OBJECT (text_tag), "size");
g_object_notify (G_OBJECT (text_tag), "size_set");
+ g_object_notify (G_OBJECT (text_tag), "font_desc");
+ g_object_notify (G_OBJECT (text_tag), "font");
size_changed = TRUE;
break;
@@ -1086,12 +1096,10 @@ gtk_text_tag_set_property (GObject *object,
/* Whether the value should be used... */
case PROP_BACKGROUND_SET:
- case PROP_BACKGROUND_GDK_SET:
text_tag->bg_color_set = g_value_get_boolean (value);
break;
case PROP_FOREGROUND_SET:
- case PROP_FOREGROUND_GDK_SET:
text_tag->fg_color_set = g_value_get_boolean (value);
break;
@@ -1289,12 +1297,6 @@ gtk_text_tag_get_property (GObject *object,
break;
case PROP_FONT:
- if (tag->family_set &&
- tag->style_set &&
- tag->variant_set &&
- tag->size_set &&
- tag->stretch_set &&
- tag->weight_set)
{
/* FIXME GValue imposes a totally gratuitous string copy
* here, we could just hand off string ownership
@@ -1306,13 +1308,7 @@ gtk_text_tag_get_property (GObject *object,
break;
case PROP_FONT_DESC:
- if (tag->family_set &&
- tag->style_set &&
- tag->variant_set &&
- tag->size_set &&
- tag->stretch_set &&
- tag->weight_set)
- g_value_set_boxed (value, &tag->values->font);
+ g_value_set_boxed (value, &tag->values->font);
break;
case PROP_FAMILY:
@@ -1413,12 +1409,10 @@ gtk_text_tag_get_property (GObject *object,
break;
case PROP_BACKGROUND_SET:
- case PROP_BACKGROUND_GDK_SET:
g_value_set_boolean (value, tag->bg_color_set);
break;
case PROP_FOREGROUND_SET:
- case PROP_FOREGROUND_GDK_SET:
g_value_set_boolean (value, tag->fg_color_set);
break;
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 76859fdd38..df233806b8 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -4176,9 +4176,16 @@ gtk_text_view_destroy_layout (GtkTextView *text_view)
{
if (text_view->layout)
{
- /* Remove layout from all anchored children */
GSList *tmp_list;
+ if (text_view->incremental_validate_idle)
+ {
+ g_source_remove (text_view->incremental_validate_idle);
+ text_view->incremental_validate_idle = 0;
+ }
+
+ /* Remove layout from all anchored children */
+
tmp_list = text_view->children;
while (tmp_list != NULL)
{
diff --git a/gtk/gtktreemodelsort.c b/gtk/gtktreemodelsort.c
index 99a704761b..17735cec5c 100644
--- a/gtk/gtktreemodelsort.c
+++ b/gtk/gtktreemodelsort.c
@@ -419,7 +419,7 @@ gtk_tree_model_sort_changed (GtkTreeModel *s_model,
array,
(GtkTreeIter *) elt,
TRUE);
- g_print ("index is %d\n", index);
+
gtk_signal_emit_by_name (GTK_OBJECT (data), "changed", path, &iter);
gtk_tree_path_free (path);
diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h
index 6b2daa5696..63e81c0760 100644
--- a/gtk/gtktreeprivate.h
+++ b/gtk/gtktreeprivate.h
@@ -110,6 +110,9 @@ struct _GtkTreeViewPrivate
GtkTreeViewColumn *scroll_to_column;
gfloat scroll_to_row_align;
gfloat scroll_to_col_align;
+
+ /* hint to display rows in alternating colors */
+ guint has_rules : 1;
};
#ifdef __GNUC__
diff --git a/gtk/gtktreeselection.c b/gtk/gtktreeselection.c
index 509b270d45..baf424a141 100644
--- a/gtk/gtktreeselection.c
+++ b/gtk/gtktreeselection.c
@@ -707,6 +707,9 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
&node);
gtk_tree_path_free (anchor_path);
+
+ if (tree == NULL)
+ return FALSE;
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
{
@@ -976,6 +979,7 @@ gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
selected = TRUE;
gtk_tree_path_free (path);
}
+
if (selected == TRUE)
{
node->flags ^= GTK_RBNODE_IS_SELECTED;
diff --git a/gtk/gtktreesortable.h b/gtk/gtktreesortable.h
index 403073e5b9..8c7ed59b9e 100644
--- a/gtk/gtktreesortable.h
+++ b/gtk/gtktreesortable.h
@@ -26,6 +26,12 @@
extern "C" {
#endif /* __cplusplus */
+typedef enum
+{
+ GTK_TREE_SORT_ASCENDING,
+ GTK_TREE_SORT_DESCENDING
+} GtkTreeSortOrder;
+
#define GTK_TYPE_TREE_SORTABLE (gtk_tree_sortable_get_type ())
#define GTK_TREE_SORTABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TREE_SORTABLE, GtkTreeSortable))
#define GTK_IS_TREE_SORTABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TREE_SORTABLE))
@@ -38,14 +44,19 @@ struct _GtkTreeSortableIface
{
GTypeInterface g_iface;
- /* FIXME think about sorting reverse when the column is clicked
- * a second time.
- */
- gboolean (* column_sortable) (GtkTreeSortable *sortable,
- gint column);
- gint (* get_sort_column) (GtkTreeSortable *sortable);
- void (* set_sort_column) (GtkTreeSortable *sortable,
- gint column);
+ /* This one is a signal */
+ void (* sort_column_changed) (GtkTreeSortable *sortable);
+
+ /* virtual methods */
+ gboolean (* column_sortable) (GtkTreeSortable *sortable,
+ gint column,
+ GtkTreeSortOrder order);
+ void (* get_sort_column) (GtkTreeSortable *sortable,
+ gint *column,
+ GtkTreeSortOrder *order);
+ void (* set_sort_column) (GtkTreeSortable *sortable,
+ gint column,
+ GtkTreeSortOrder order);
};
diff --git a/gtk/gtktreestore.c b/gtk/gtktreestore.c
index d44c468197..d54bab9d35 100644
--- a/gtk/gtktreestore.c
+++ b/gtk/gtktreestore.c
@@ -1061,14 +1061,12 @@ gtk_tree_store_drag_data_delete (GtkTreeDragSource *drag_source,
&iter,
path))
{
- g_print ("data_delete deleting tree row\n");
gtk_tree_store_remove (GTK_TREE_STORE (drag_source),
&iter);
return TRUE;
}
else
{
- g_print ("data_delete path not in tree\n");
return FALSE;
}
}
@@ -1117,9 +1115,6 @@ copy_node_data (GtkTreeStore *tree_store,
copy_iter = _gtk_tree_data_list_node_copy (dl,
tree_store->column_headers[col]);
- g_print ("copied col %d type %s\n", col,
- g_type_name (tree_store->column_headers[col]));
-
if (copy_head == NULL)
copy_head = copy_iter;
@@ -1205,7 +1200,6 @@ gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
&src_iter,
src_path))
{
- g_print ("can't get source path as iter\n");
goto out;
}
@@ -1240,8 +1234,6 @@ gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
dest_parent_p);
retval = TRUE;
-
- g_print ("prepending to tree\n");
}
else
{
@@ -1256,10 +1248,7 @@ gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
&tmp_iter);
retval = TRUE;
- g_print ("inserting into tree\n");
}
- else
- g_print ("can't get iter to insert after\n");
}
gtk_tree_path_free (prev);
@@ -1280,7 +1269,7 @@ gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
/* FIXME maybe add some data targets eventually, or handle text
* targets in the simple case.
*/
- g_print ("not accepting target\n");
+
}
out:
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index db5de4e46b..b30eeefb13 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -28,6 +28,8 @@
#include "gtkbutton.h"
#include "gtkalignment.h"
#include "gtklabel.h"
+#include "gtkhbox.h"
+#include "gtkarrow.h"
#include <gdk/gdkkeysyms.h>
@@ -437,10 +439,6 @@ gtk_tree_view_realize (GtkWidget *widget)
tree_view = GTK_TREE_VIEW (widget);
- if (!GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP) &&
- tree_view->priv->model)
- gtk_tree_view_setup_model (tree_view);
-
gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget));
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
@@ -768,7 +766,9 @@ gtk_tree_view_size_allocate (GtkWidget *widget,
widget->allocation = *allocation;
tree_view = GTK_TREE_VIEW (widget);
-
+
+ gtk_tree_view_check_dirty (tree_view);
+
tmp_list = tree_view->priv->children;
while (tmp_list)
@@ -788,28 +788,25 @@ gtk_tree_view_size_allocate (GtkWidget *widget,
gtk_widget_size_allocate (child->widget, &allocation);
}
+ gtk_tree_view_size_allocate_buttons (widget);
+
if (GTK_WIDGET_REALIZED (widget))
{
gdk_window_move_resize (widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
+
gdk_window_move_resize (tree_view->priv->header_window,
0, 0,
MAX (tree_view->priv->width, allocation->width),
tree_view->priv->header_height);
}
-
- /* FIXME I don't think the invariant that the model must be setup
- * before touching the buttons is maintained in most of the
- * rest of the code, e.g. in realize, so something is wrong
- */
- if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
- gtk_tree_view_size_allocate_buttons (widget);
tree_view->priv->hadjustment->page_size = allocation->width;
tree_view->priv->hadjustment->page_increment = allocation->width / 2;
tree_view->priv->hadjustment->lower = 0;
tree_view->priv->hadjustment->upper = tree_view->priv->width;
+
if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed");
@@ -818,9 +815,11 @@ gtk_tree_view_size_allocate (GtkWidget *widget,
tree_view->priv->vadjustment->page_increment = (allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
tree_view->priv->vadjustment->lower = 0;
tree_view->priv->vadjustment->upper = tree_view->priv->height;
+
if (tree_view->priv->vadjustment->value + allocation->height > tree_view->priv->height)
gtk_adjustment_set_value (tree_view->priv->vadjustment,
(gfloat) MAX (tree_view->priv->height - allocation->height, 0));
+
gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
}
@@ -879,12 +878,14 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view,
depth = gtk_tree_path_get_depth (path);
- if (_gtk_tree_view_find_node (tree_view,
- path,
- &tree,
- &node))
- return NULL;
+ _gtk_tree_view_find_node (tree_view,
+ path,
+ &tree,
+ &node);
+ if (tree == NULL)
+ return NULL;
+
if (!gtk_tree_model_get_iter (tree_view->priv->model,
&iter,
path))
@@ -970,9 +971,9 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
GtkTreePath *path;
GtkRBTree *tree;
GList *list;
- GtkRBNode *node, *last_node = NULL;
+ GtkRBNode *node;
GtkRBNode *cursor = NULL;
- GtkRBTree *cursor_tree = NULL, *last_tree = NULL;
+ GtkRBTree *cursor_tree = NULL;
GtkRBNode *drag_highlight = NULL;
GtkRBTree *drag_highlight_tree = NULL;
GtkTreeIter iter;
@@ -984,7 +985,6 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
GdkRectangle background_area;
GdkRectangle cell_area;
guint flags;
- gboolean last_selected;
gint highlight_x;
gint bin_window_width;
GtkTreePath *cursor_path;
@@ -1014,10 +1014,6 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
if (node == NULL)
return TRUE;
- /* See if the last node was selected */
- _gtk_rbtree_prev_full (tree, node, &last_tree, &last_node);
- last_selected = (last_node && GTK_RBNODE_FLAG_SET (last_node, GTK_RBNODE_IS_SELECTED));
-
/* find the path for the node */
path = _gtk_tree_view_find_path ((GtkTreeView *)widget,
tree,
@@ -1060,45 +1056,39 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
max_height = MAX (TREE_VIEW_EXPANDER_MIN_HEIGHT, GTK_RBNODE_GET_HEIGHT (node));
else
*/
+ gboolean parity;
+
max_height = BACKGROUND_HEIGHT (node);
x_offset = -event->area.x;
cell_offset = 0;
highlight_x = 0; /* should match x coord of first cell */
- background_area.y = y_offset + event->area.y + TREE_VIEW_VERTICAL_SEPARATOR / 2;
- background_area.height = max_height - TREE_VIEW_VERTICAL_SEPARATOR;
+ background_area.y = y_offset + event->area.y;
+ background_area.height = max_height;
flags = 0;
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PRELIT))
flags |= GTK_CELL_RENDERER_PRELIT;
+ parity = _gtk_rbtree_node_find_parity (tree, node);
+
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
- {
- flags |= GTK_CELL_RENDERER_SELECTED;
-
- /* Draw the selection */
- gdk_draw_rectangle (event->window,
- GTK_WIDGET (tree_view)->style->bg_gc [GTK_STATE_SELECTED],
- TRUE,
- event->area.x,
- background_area.y - (last_selected?TREE_VIEW_VERTICAL_SEPARATOR:0),
- event->area.width,
- background_area.height + (last_selected?TREE_VIEW_VERTICAL_SEPARATOR:0));
- last_selected = TRUE;
- }
- else
- {
- last_selected = FALSE;
- }
-
+ flags |= GTK_CELL_RENDERER_SELECTED;
+
for (i = 0, list = tree_view->priv->columns; i < tree_view->priv->n_columns; i++, list = list->next)
{
GtkTreeViewColumn *column = list->data;
-
+ const gchar *detail = NULL;
+
if (!column->visible)
- continue;
+ continue;
+ if (column->show_sort_indicator)
+ flags |= GTK_CELL_RENDERER_SORTED;
+ else
+ flags &= ~GTK_CELL_RENDERER_SORTED;
+
cell = column->cell;
gtk_tree_view_column_set_cell_data (column,
tree_view->priv->model,
@@ -1106,10 +1096,75 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
background_area.x = cell_offset;
background_area.width = TREE_VIEW_COLUMN_WIDTH (column);
+
+ cell_area = background_area;
+ cell_area.y += TREE_VIEW_VERTICAL_SEPARATOR / 2;
+ cell_area.height -= TREE_VIEW_VERTICAL_SEPARATOR;
+
+ /* Select the detail for drawing the cell. relevant
+ * factors are parity, sortedness, and whether to
+ * display rules.
+ */
+
+ /* FIXME when we have style properties, clean this up.
+ */
+
+#if 1
+ if (tree_view->priv->has_rules)
+ {
+ 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);
+#endif
+
+ /* Draw background */
+ gtk_paint_flat_box (widget->style,
+ event->window,
+ (flags & GTK_CELL_RENDERER_SELECTED) ?
+ GTK_STATE_SELECTED : GTK_STATE_NORMAL,
+ GTK_SHADOW_NONE,
+ &event->area,
+ widget,
+ detail,
+ background_area.x,
+ background_area.y,
+ background_area.width,
+ background_area.height);
+
if (i == tree_view->priv->expander_column &&
TREE_VIEW_DRAW_EXPANDERS(tree_view))
{
- cell_area = background_area;
cell_area.x += depth*tree_view->priv->tab_offset;
cell_area.width -= depth*tree_view->priv->tab_offset;
@@ -1118,7 +1173,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
* level of the tree we're dropping at.
*/
highlight_x = cell_area.x;
-
+
gtk_cell_renderer_render (cell,
event->window,
widget,
@@ -1126,6 +1181,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
&cell_area,
&event->area,
flags);
+
if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
{
gint x, y;
@@ -1137,8 +1193,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
}
}
else
- {
- cell_area = background_area;
+ {
gtk_cell_renderer_render (cell,
event->window,
widget,
@@ -1196,6 +1251,9 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
tree = node->children;
node = tree->root;
+
+ g_assert (node != tree->nil);
+
while (node->left != tree->nil)
node = node->left;
has_child = gtk_tree_model_iter_children (tree_view->priv->model,
@@ -1246,7 +1304,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget,
}
}
while (y_offset < event->area.height);
-
+
if (cursor_path)
gtk_tree_path_free (cursor_path);
@@ -1284,6 +1342,9 @@ coords_are_over_arrow (GtkTreeView *tree_view,
GdkRectangle arrow;
gint x2;
+ if (!GTK_WIDGET_REALIZED (tree_view))
+ return FALSE;
+
if ((node->flags & GTK_RBNODE_IS_PARENT) == 0)
return FALSE;
@@ -1351,6 +1412,12 @@ do_prelight (GtkTreeView *tree_view,
GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT);
}
+static void
+ensure_unprelighted (GtkTreeView *tree_view)
+{
+ do_unprelight (tree_view, -1000, -1000); /* coords not possibly over an arrow */
+}
+
static gboolean
gtk_tree_view_motion (GtkWidget *widget,
GdkEventMotion *event)
@@ -1406,7 +1473,7 @@ gtk_tree_view_motion (GtkWidget *widget,
&tree,
&node);
- if (node == NULL)
+ if (tree == NULL)
return TRUE;
/* If we are currently pressing down a button, we don't want to prelight anything else. */
@@ -1502,7 +1569,7 @@ gtk_tree_view_leave_notify (GtkWidget *widget,
tree_view->priv->prelight_node,
NULL);
- do_unprelight (tree_view, -1000, -1000); /* coords not possibly over an arrow */
+ ensure_unprelighted (tree_view);
return TRUE;
}
@@ -1756,14 +1823,14 @@ gtk_tree_view_button_release (GtkWidget *widget,
tree_view->priv->button_pressed_node->children->parent_tree = tree_view->priv->button_pressed_tree;
tree_view->priv->button_pressed_node->children->parent_node = tree_view->priv->button_pressed_node;
gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
- gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
-
- gtk_tree_view_build_tree (tree_view,
- tree_view->priv->button_pressed_node->children,
- &child,
- gtk_tree_path_get_depth (path) + 1,
- FALSE,
- GTK_WIDGET_REALIZED (widget));
+
+ if (gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter))
+ gtk_tree_view_build_tree (tree_view,
+ tree_view->priv->button_pressed_node->children,
+ &child,
+ gtk_tree_path_get_depth (path) + 1,
+ FALSE,
+ GTK_WIDGET_REALIZED (widget));
}
else
{
@@ -2422,6 +2489,9 @@ gtk_tree_view_changed (GtkTreeModel *model,
/* We aren't actually showing the node */
return;
+ if (tree == NULL)
+ return;
+
dirty_marked = gtk_tree_view_discover_dirty_iter (tree_view,
iter,
gtk_tree_path_get_depth (path),
@@ -2554,6 +2624,9 @@ gtk_tree_view_child_toggled (GtkTreeModel *model,
/* We aren't actually showing the node */
return;
+ if (tree == NULL)
+ return;
+
has_child = gtk_tree_model_iter_has_child (model, &real_iter);
/* Sanity check.
*/
@@ -2596,12 +2669,15 @@ gtk_tree_view_deleted (GtkTreeModel *model,
GtkRBTree *tree;
GtkRBNode *node;
GList *list;
-
+
g_return_if_fail (path != NULL);
if (_gtk_tree_view_find_node (tree_view, path, &tree, &node))
return;
+ if (tree == NULL)
+ return;
+
/* next, update the selection */
if (tree_view->priv->anchor)
{
@@ -2633,11 +2709,20 @@ gtk_tree_view_deleted (GtkTreeModel *model,
((GtkTreeViewColumn *)list->data)->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
((GtkTreeViewColumn *)list->data)->dirty = TRUE;
+ /* Ensure we don't have a dangling pointer to a dead node */
+ ensure_unprelighted (tree_view);
+
+ g_assert (tree_view->priv->prelight_node == NULL);
+
if (tree->root->count == 1)
- _gtk_rbtree_remove (tree);
+ {
+ _gtk_rbtree_remove (tree);
+ }
else
- _gtk_rbtree_remove_node (tree, node);
-
+ {
+ _gtk_rbtree_remove_node (tree, node);
+ }
+
_gtk_tree_view_set_size (GTK_TREE_VIEW (data), -1, -1);
}
@@ -2905,6 +2990,10 @@ gtk_tree_view_check_dirty (GtkTreeView *tree_view)
GtkTreeViewColumn *column;
GtkTreeIter iter;
+ if (!GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP) &&
+ tree_view->priv->model)
+ gtk_tree_view_setup_model (tree_view);
+
for (list = tree_view->priv->columns; list; list = list->next)
{
column = list->data;
@@ -2913,13 +3002,22 @@ gtk_tree_view_check_dirty (GtkTreeView *tree_view)
dirty = TRUE;
if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
{
- gtk_tree_view_column_set_width (column, MAX (column->button->requisition.width, 1));
+ gint w = 1;
+
+ if (column->button)
+ w = MAX (w, column->button->requisition.width);
+
+ gtk_tree_view_column_set_width (column, w);
}
}
}
+
if (dirty == FALSE)
return;
+ if (tree_view->priv->model == NULL)
+ return;
+
path = gtk_tree_path_new_root ();
if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
{
@@ -2948,8 +3046,8 @@ gtk_tree_view_create_button (GtkTreeView *tree_view,
button = column->button = gtk_button_new ();
gtk_widget_pop_composite_child ();
- gtk_widget_set_parent (button, GTK_WIDGET (tree_view));
-
+ gtk_widget_set_parent (button, GTK_WIDGET (tree_view));\
+
gtk_signal_connect (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) gtk_tree_view_button_clicked,
(gpointer) tree_view);
@@ -2965,7 +3063,13 @@ gtk_tree_view_create_buttons (GtkTreeView *tree_view)
GList *list;
GtkTreeViewColumn *column;
gint i;
+ GtkWidget *hbox;
+ GtkWidget *arrow;
+ /* FIXME this has to be merged with update_button_contents() in
+ * gtktreeviewcolumn.c
+ */
+
for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
{
column = list->data;
@@ -2974,23 +3078,14 @@ gtk_tree_view_create_buttons (GtkTreeView *tree_view)
continue;
gtk_tree_view_create_button (tree_view, i);
- switch (column->justification)
- {
- case GTK_JUSTIFY_LEFT:
- alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
- break;
- case GTK_JUSTIFY_RIGHT:
- alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
- break;
- case GTK_JUSTIFY_CENTER:
- alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
- break;
- case GTK_JUSTIFY_FILL:
- default:
- alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
- break;
- }
+ alignment = gtk_alignment_new (column->xalign, 0.5, 0.0, 0.0);
+ hbox = gtk_hbox_new (FALSE, 2);
+ arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
+
+ column->arrow = arrow;
+ column->alignment = alignment;
+
if (column->child)
label = column->child;
else
@@ -2999,10 +3094,19 @@ gtk_tree_view_create_buttons (GtkTreeView *tree_view)
gtk_widget_show (label);
}
- gtk_container_add (GTK_CONTAINER (alignment), label);
- gtk_container_add (GTK_CONTAINER (column->button), alignment);
+ if (column->xalign <= 0.5)
+ gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
+ else
+ gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
+
+ gtk_container_add (GTK_CONTAINER (alignment), label);
+ gtk_container_add (GTK_CONTAINER (column->button), hbox);
+
+ gtk_widget_show (hbox);
gtk_widget_show (alignment);
+ /* don't show the arrow yet */
}
gtk_tree_view_size_request_buttons (tree_view);
@@ -3104,7 +3208,10 @@ _gtk_tree_view_find_path (GtkTreeView *tree_view,
return path;
}
-/* Returns whether or not it's a parent, or not */
+/* Returns TRUE if we ran out of tree before finding the node,
+ * so the returned node is the last node we saw and the returned
+ * tree is NULL
+ */
gboolean
_gtk_tree_view_find_node (GtkTreeView *tree_view,
GtkTreePath *path,
@@ -3129,7 +3236,8 @@ _gtk_tree_view_find_node (GtkTreeView *tree_view,
return TRUE;
}
tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
- if (++i >= depth)
+ ++i;
+ if (i >= depth)
{
*node = tmpnode;
*tree = tmptree;
@@ -3269,6 +3377,7 @@ _gtk_tree_view_set_size (GtkTreeView *tree_view,
width += TREE_VIEW_COLUMN_WIDTH (column);
}
}
+
if (height == -1)
height = tree_view->priv->tree->root->offset + TREE_VIEW_VERTICAL_SEPARATOR;
@@ -3292,6 +3401,7 @@ _gtk_tree_view_set_size (GtkTreeView *tree_view,
gdk_window_resize (tree_view->priv->bin_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), height + TREE_VIEW_HEADER_HEIGHT (tree_view));
gdk_window_resize (tree_view->priv->header_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), tree_view->priv->header_height);
}
+
gtk_widget_queue_resize (GTK_WIDGET (tree_view));
}
@@ -4557,6 +4667,10 @@ gtk_tree_view_collapse_all_helper (GtkRBTree *tree,
node->children,
&iter,
gtk_tree_path_get_depth (path));
+
+ /* Ensure we don't have a dangling pointer to a dead node */
+ ensure_unprelighted (GTK_TREE_VIEW (data));
+
_gtk_rbtree_remove (node->children);
gtk_tree_path_free (path);
}
@@ -4620,7 +4734,7 @@ gtk_tree_view_expand_row (GtkTreeView *tree_view,
&tree,
&node))
return FALSE;
-
+
if (node->children)
return TRUE;
@@ -4682,6 +4796,12 @@ gtk_tree_view_collapse_row (GtkTreeView *tree_view,
node->children,
&iter,
gtk_tree_path_get_depth (path));
+
+ /* Ensure we don't have a dangling pointer to a dead node */
+ ensure_unprelighted (tree_view);
+
+ g_assert (tree_view->priv->prelight_node == NULL);
+
_gtk_rbtree_remove (node->children);
if (GTK_WIDGET_MAPPED (tree_view))
@@ -4785,6 +4905,56 @@ gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
}
}
+/**
+ * gtk_tree_view_set_rules_hint
+ * @tree_view: a #GtkTreeView
+ * @setting: %TRUE if the tree requires reading across rows
+ *
+ * This function tells GTK+ that the user interface for your
+ * application requires users to read across tree rows and associate
+ * cells with one another. By default, GTK+ will then render the tree
+ * with alternating row colors. <emphasis>DO NOT</emphasis> use it
+ * just because you prefer the appearance of the ruled tree; that's a
+ * question for the theme. Some themes will draw tree rows in
+ * alternating colors even when rules are turned off, and users who
+ * prefer that appearance all the time can choose those themes. You
+ * should call this function only as a <emphasis>semantic</emphasis>
+ * hint to the theme engine that your tree makes alternating colors
+ * useful from a functional standpoint (since it has lots of columns,
+ * generally).
+ *
+ **/
+void
+gtk_tree_view_set_rules_hint (GtkTreeView *tree_view,
+ gboolean setting)
+{
+ g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+ setting = setting != FALSE;
+
+ if (tree_view->priv->has_rules != setting)
+ {
+ tree_view->priv->has_rules = setting;
+ gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+ }
+}
+
+/**
+ * gtk_tree_view_get_rules_hint
+ * @tree_view: a #GtkTreeView
+ *
+ * Gets the setting set by gtk_tree_view_set_rules_hint().
+ *
+ * Return value: %TRUE if rules are useful for the user of this tree
+ **/
+gboolean
+gtk_tree_view_get_rules_hint (GtkTreeView *tree_view)
+{
+ g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
+
+ return tree_view->priv->has_rules;
+}
+
/* Drag-and-drop */
static void
@@ -5447,8 +5617,6 @@ gtk_tree_view_drag_data_delete (GtkWidget *widget,
tree_view = GTK_TREE_VIEW (widget);
model = gtk_tree_view_get_model (tree_view);
-
- g_print ("data_delete\n");
if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag_data_delete"))
return;
@@ -5491,7 +5659,6 @@ gtk_tree_view_drag_leave (GtkWidget *widget,
di = get_info (GTK_TREE_VIEW (widget));
/* unset any highlight row */
- g_print ("drag leave\n");
gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
NULL,
GTK_TREE_VIEW_DROP_BEFORE);
@@ -5561,7 +5728,6 @@ set_destination_row (GtkTreeView *tree_view,
* we return FALSE drag_leave isn't called
*/
- g_print ("no longer a drag dest\n");
gtk_tree_view_set_drag_dest_row (tree_view,
NULL,
GTK_TREE_VIEW_DROP_BEFORE);
@@ -5575,7 +5741,6 @@ set_destination_row (GtkTreeView *tree_view,
*target = gtk_drag_dest_find_target (widget, context, di->dest_target_list);
if (*target == GDK_NONE)
{
- g_print ("bad target, not accepting\n");
return FALSE;
}
@@ -5587,7 +5752,6 @@ set_destination_row (GtkTreeView *tree_view,
/* can't drop here */
remove_open_timeout (tree_view);
- g_print ("no drag row here\n");
gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
NULL,
GTK_TREE_VIEW_DROP_BEFORE);
@@ -5631,7 +5795,6 @@ set_destination_row (GtkTreeView *tree_view,
*suggested_action = GDK_ACTION_MOVE;
}
- g_print ("setting drag dest row\n");
gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
path, pos);
}
@@ -5640,7 +5803,6 @@ set_destination_row (GtkTreeView *tree_view,
/* can't drop here */
remove_open_timeout (tree_view);
- g_print ("droppable predicate false\n");
gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
NULL,
GTK_TREE_VIEW_DROP_BEFORE);
@@ -5664,8 +5826,6 @@ gtk_tree_view_drag_motion (GtkWidget *widget,
tree_view = GTK_TREE_VIEW (widget);
- g_print ("motion\n");
-
if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
return FALSE;
@@ -5676,7 +5836,6 @@ gtk_tree_view_drag_motion (GtkWidget *widget,
if (path == NULL)
{
/* Can't drop here. */
- g_print ("not over a dest row\n");
gdk_drag_status (context, 0, time);
}
else
@@ -5695,13 +5854,11 @@ gtk_tree_view_drag_motion (GtkWidget *widget,
* determining whether to accept the drop
*/
set_status_pending (context, suggested_action);
- g_print ("motion requesting the drop data\n");
gtk_drag_get_data (widget, context, target, time);
}
else
{
set_status_pending (context, 0);
- g_print ("motion sending positive status\n");
gdk_drag_status (context, suggested_action, time);
}
}
@@ -5760,8 +5917,6 @@ gtk_tree_view_drag_drop (GtkWidget *widget,
model = gtk_tree_view_get_model (tree_view);
- g_print ("drop\n");
-
remove_scroll_timeout (GTK_TREE_VIEW (widget));
remove_open_timeout (GTK_TREE_VIEW (widget));
@@ -5780,8 +5935,6 @@ gtk_tree_view_drag_drop (GtkWidget *widget,
if (target != GDK_NONE && path != NULL)
{
- g_print ("have target\n");
-
/* in case a motion had requested drag data, change things so we
* treat drag data receives as a drop.
*/
@@ -5800,7 +5953,6 @@ gtk_tree_view_drag_drop (GtkWidget *widget,
if (target != GDK_NONE)
{
- g_print ("getting data\n");
gtk_drag_get_data (widget, context, target, time);
return TRUE;
}
@@ -5831,8 +5983,6 @@ gtk_tree_view_drag_data_received (GtkWidget *widget,
if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_data_received"))
return;
-
- g_print ("drag data received\n");
di = get_info (tree_view);
@@ -5874,8 +6024,6 @@ gtk_tree_view_drag_data_received (GtkWidget *widget,
gtk_tree_path_free (src_path);
}
}
-
- g_print ("suggested action %d in drag_data_received\n", suggested_action);
gdk_drag_status (context, suggested_action, time);
@@ -5903,8 +6051,6 @@ gtk_tree_view_drag_data_received (GtkWidget *widget,
selection_data))
accepted = TRUE;
}
-
- g_print ("accepted: %d\n", accepted);
gtk_drag_finish (context,
accepted,
diff --git a/gtk/gtktreeview.h b/gtk/gtktreeview.h
index fd36f4d0a6..cb23a4e906 100644
--- a/gtk/gtktreeview.h
+++ b/gtk/gtktreeview.h
@@ -155,6 +155,9 @@ void gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
gint *wx,
gint *wy);
+void gtk_tree_view_set_rules_hint (GtkTreeView *tree_view,
+ gboolean setting);
+gboolean gtk_tree_view_get_rules_hint (GtkTreeView *tree_view);
/* Drag-and-Drop support */
diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c
index 1d7dab0eee..7515327c4a 100644
--- a/gtk/gtktreeviewcolumn.c
+++ b/gtk/gtktreeviewcolumn.c
@@ -23,6 +23,8 @@
#include "gtkbutton.h"
#include "gtkalignment.h"
#include "gtklabel.h"
+#include "gtkhbox.h"
+#include "gtkarrow.h"
#include "gtkintl.h"
enum
@@ -38,7 +40,9 @@ enum
PROP_TITLE,
PROP_CLICKABLE,
PROP_WIDGET,
- PROP_JUSTIFICATION
+ PROP_ALIGNMENT,
+ PROP_SORT_INDICATOR,
+ PROP_SORT_ORDER
};
enum
@@ -200,13 +204,32 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
G_PARAM_READABLE | G_PARAM_WRITABLE));
g_object_class_install_property (object_class,
- PROP_JUSTIFICATION,
- g_param_spec_enum ("justification",
- _("Justification"),
- _("Justification of the column"),
- GTK_TYPE_JUSTIFICATION,
- GTK_JUSTIFY_LEFT,
+ PROP_ALIGNMENT,
+ g_param_spec_float ("alignment",
+ _("Alignment"),
+ _("Alignment of the column header text or widget"),
+ 0.0,
+ 1.0,
+ 0.5,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_SORT_INDICATOR,
+ g_param_spec_boolean ("sort_indicator",
+ _("Sort indicator"),
+ _("Whether to show a sort indicator"),
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_SORT_ORDER,
+ g_param_spec_enum ("sort_order",
+ _("Sort order"),
+ _("Sort direction the sort indicator should indicate"),
+ GTK_TYPE_TREE_SORT_ORDER,
+ GTK_TREE_SORT_ASCENDING,
G_PARAM_READABLE | G_PARAM_WRITABLE));
+
}
static void
@@ -217,7 +240,7 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
gtk_object_sink (GTK_OBJECT (tree_column));
tree_column->button = NULL;
- tree_column->justification = GTK_JUSTIFY_LEFT;
+ tree_column->xalign = 0.0;
tree_column->width = 1;
tree_column->min_width = -1;
tree_column->max_width = -1;
@@ -227,6 +250,8 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
tree_column->visible = TRUE;
tree_column->button_active = FALSE;
tree_column->dirty = TRUE;
+ tree_column->sort_order = GTK_TREE_SORT_ASCENDING;
+ tree_column->show_sort_indicator = FALSE;
}
static void
@@ -288,11 +313,21 @@ gtk_tree_view_column_set_property (GObject *object,
(GtkWidget*) g_value_get_object (value));
break;
- case PROP_JUSTIFICATION:
- gtk_tree_view_column_set_justification (tree_column,
- g_value_get_enum (value));
+ case PROP_ALIGNMENT:
+ gtk_tree_view_column_set_alignment (tree_column,
+ g_value_get_float (value));
+ break;
+
+ case PROP_SORT_INDICATOR:
+ gtk_tree_view_column_set_sort_indicator (tree_column,
+ g_value_get_boolean (value));
break;
+ case PROP_SORT_ORDER:
+ gtk_tree_view_column_set_sort_order (tree_column,
+ g_value_get_enum (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -313,50 +348,69 @@ gtk_tree_view_column_get_property (GObject *object,
switch (prop_id)
{
case PROP_CELL_RENDERER:
- g_value_set_object (value, (GObject*) tree_column->cell);
+ g_value_set_object (value,
+ (GObject*) gtk_tree_view_column_get_cell_renderer (tree_column));
break;
case PROP_VISIBLE:
- g_value_set_boolean (value, tree_column->visible);
+ g_value_set_boolean (value,
+ gtk_tree_view_column_get_visible (tree_column));
break;
case PROP_SIZING:
- g_value_set_enum (value, tree_column->column_type);
+ g_value_set_enum (value,
+ gtk_tree_view_column_get_sizing (tree_column));
break;
case PROP_WIDTH:
- g_value_set_int (value, tree_column->width);
+ g_value_set_int (value,
+ gtk_tree_view_column_get_width (tree_column));
break;
case PROP_MIN_WIDTH:
- g_value_set_int (value, tree_column->min_width);
+ g_value_set_int (value,
+ gtk_tree_view_column_get_min_width (tree_column));
break;
case PROP_MAX_WIDTH:
- g_value_set_int (value, tree_column->max_width);
+ g_value_set_int (value,
+ gtk_tree_view_column_get_max_width (tree_column));
break;
case PROP_TITLE:
- g_value_set_string (value, tree_column->title);
+ g_value_set_string (value,
+ gtk_tree_view_column_get_title (tree_column));
break;
case PROP_CLICKABLE:
- g_value_set_boolean (value, tree_column->button_active);
+ g_value_set_boolean (value,
+ gtk_tree_view_column_get_clickable (tree_column));
break;
case PROP_WIDGET:
- g_warning ("FIXME");
+ g_value_set_object (value,
+ (GObject*) gtk_tree_view_column_get_widget (tree_column));
break;
- case PROP_JUSTIFICATION:
- g_value_set_enum (value, tree_column->justification);
+ case PROP_ALIGNMENT:
+ g_value_set_float (value,
+ gtk_tree_view_column_get_alignment (tree_column));
break;
+ case PROP_SORT_INDICATOR:
+ g_value_set_boolean (value,
+ gtk_tree_view_column_get_sort_indicator (tree_column));
+ break;
+
+ case PROP_SORT_ORDER:
+ g_value_set_enum (value,
+ gtk_tree_view_column_get_sort_order (tree_column));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
-
}
/* used to make the buttons 'unclickable' */
@@ -455,8 +509,8 @@ void
gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell)
{
- g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
+
if (cell)
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
@@ -472,6 +526,22 @@ gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column,
}
/**
+ * gtk_tree_view_column_get_cell_renderer:
+ * @tree_column: a #GtkTreeViewColumn
+ *
+ * Gets the value set with gtk_tree_view_column_set_cell_renderer().
+ *
+ * Return value: cell renderer for the column, or %NULL if unset
+ **/
+GtkCellRenderer*
+gtk_tree_view_column_get_cell_renderer (GtkTreeViewColumn *tree_column)
+{
+ g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
+
+ return tree_column->cell;
+}
+
+/**
* gtk_tree_view_column_add_attribute:
* @tree_column: A #GtkTreeViewColumn.
* @attribute: An attribute on the columns cell
@@ -788,6 +858,22 @@ gtk_tree_view_column_set_width (GtkTreeViewColumn *tree_column,
}
/**
+ * gtk_tree_view_column_get_width:
+ * @tree_column: a #GtkTreeViewColumn
+ *
+ * Gets the value set by gtk_tree_view_column_set_width().
+ *
+ * Return value: the width of the column
+ **/
+gint
+gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column)
+{
+ g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
+
+ return tree_column->width;
+}
+
+/**
* gtk_tree_view_column_set_min_width:
* @tree_column: A #GtkTreeViewColumn.
* @min_width: The minimum width of the column in pixels, or -1.
@@ -923,8 +1009,13 @@ update_button_contents (GtkTreeViewColumn *tree_column)
{
if (tree_column->button)
{
- GtkWidget *alignment = GTK_BIN (tree_column->button)->child;
+ GtkWidget *hbox = GTK_BIN (tree_column->button)->child;
+ GtkWidget *alignment = tree_column->alignment;
+ GtkWidget *arrow = tree_column->arrow;
GtkWidget *current_child = GTK_BIN (alignment)->child;
+
+ gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign,
+ 0.5, 0.0, 0.0);
if (tree_column->child)
{
@@ -958,6 +1049,50 @@ update_button_contents (GtkTreeViewColumn *tree_column)
gtk_label_set_text (GTK_LABEL (current_child),
"");
}
+
+ switch (tree_column->sort_order)
+ {
+ case GTK_TREE_SORT_ASCENDING:
+ gtk_arrow_set (GTK_ARROW (arrow),
+ GTK_ARROW_DOWN,
+ GTK_SHADOW_IN);
+ break;
+
+ case GTK_TREE_SORT_DESCENDING:
+ gtk_arrow_set (GTK_ARROW (arrow),
+ GTK_ARROW_UP,
+ GTK_SHADOW_IN);
+ break;
+
+ default:
+ g_warning (G_STRLOC": bad sort order");
+ break;
+ }
+
+ /* Put arrow on the right if the text is left-or-center justified,
+ * and on the left otherwise; do this by packing boxes, so flipping
+ * text direction will reverse things
+ */
+ gtk_widget_ref (arrow);
+ gtk_container_remove (GTK_CONTAINER (hbox), arrow);
+
+ if (tree_column->xalign <= 0.5)
+ {
+ gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
+ }
+ else
+ {
+ gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
+ /* move it to the front */
+ gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0);
+ }
+
+ gtk_widget_unref (arrow);
+
+ if (tree_column->show_sort_indicator)
+ gtk_widget_show (arrow);
+ else
+ gtk_widget_hide (arrow);
}
}
@@ -995,7 +1130,7 @@ gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
*
* Return value: the title of the column.
**/
-gchar *
+G_CONST_RETURN gchar *
gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
{
g_return_val_if_fail (tree_column != NULL, NULL);
@@ -1120,54 +1255,126 @@ gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
}
/**
- * gtk_tree_view_column_set_justification:
+ * gtk_tree_view_column_set_alignment:
* @tree_column: A #GtkTreeViewColumn.
- * @justification: The justification of the title.
+ * @xalign: alignment (0.0 for left, 0.5 for center, 1.0 for right)
*
- * Sets the justification of the title inside the column header. If a custom
- * widget has been set, then this value is discarded.
+ * Sets the alignment of the title or custom widget inside the column header.
**/
void
-gtk_tree_view_column_set_justification (GtkTreeViewColumn *tree_column,
- GtkJustification justification)
+gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
+ gfloat xalign)
{
- GtkWidget *alignment;
-
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
- if (tree_column->justification == justification)
+ if (tree_column->xalign == xalign)
return;
- tree_column->justification = justification;
+ tree_column->xalign = xalign;
+
+ update_button_contents (tree_column);
+
+ g_object_notify (G_OBJECT (tree_column), "alignment");
+}
- alignment = GTK_BIN (tree_column->button)->child;
+gfloat
+gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
+{
+ g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
- if (GTK_IS_ALIGNMENT (alignment))
+ return tree_column->xalign;
+}
+
+/**
+ * gtk_tree_view_column_set_sort_indicator:
+ * @tree_column: a #GtkTreeViewColumn
+ * @setting: %TRUE to display an indicator that the column is sorted
+ *
+ * Call this function with a @setting of %TRUE to display an arrow in
+ * the header button indicating the column is sorted. Call
+ * gtk_tree_view_column_set_sort_order() to change the direction of
+ * the arrow.
+ *
+ **/
+void
+gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column,
+ gboolean setting)
+{
+ g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
+
+ setting = setting != FALSE;
+
+ if (setting != tree_column->show_sort_indicator)
{
- switch (tree_column->justification)
- {
- case GTK_JUSTIFY_LEFT:
- gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
- break;
-
- case GTK_JUSTIFY_RIGHT:
- gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
- break;
-
- case GTK_JUSTIFY_CENTER:
- gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
- break;
-
- case GTK_JUSTIFY_FILL:
- gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
- break;
-
- default:
- break;
- }
+ tree_column->show_sort_indicator = setting;
+
+ update_button_contents (tree_column);
+
+ g_object_notify (G_OBJECT (tree_column), "sort_indicator");
}
+}
+
+/**
+ * gtk_tree_view_column_get_sort_indicator:
+ * @tree_column: a #GtkTreeViewColumn
+ *
+ * Gets the value set by gtk_tree_view_column_set_sort_indicator().
+ *
+ * Return value: whether the sort indicator arrow is displayed
+ **/
+gboolean
+gtk_tree_view_column_get_sort_indicator (GtkTreeViewColumn *tree_column)
+{
+ g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
+
+ return tree_column->show_sort_indicator;
+}
+
+/**
+ * gtk_tree_view_column_set_sort_order:
+ * @tree_column: a #GtkTreeViewColumn
+ * @order: sort order that the sort indicator should indicate
+ *
+ * Changes the appearance of the sort indicator. (This <emphasis>does
+ * not</emphasis> actually sort the model - for the models shipped
+ * with GTK+, use at gtk_tree_sortable_set_sort_column() to do
+ * that. For custom models, the mechanism will vary.) The sort
+ * indicator changes direction to indicate normal sort or reverse
+ * sort. Note that you must have the sort indicator enabled to see
+ * anything when calling this function; see
+ * gtk_tree_view_column_set_sort_indicator().
+ *
+ **/
+void
+gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column,
+ GtkTreeSortOrder order)
+{
+ g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
+
+ if (order != tree_column->sort_order)
+ {
+ tree_column->sort_order = order;
+
+ update_button_contents (tree_column);
+
+ g_object_notify (G_OBJECT (tree_column), "sort_order");
+ }
+}
+
+/**
+ * gtk_tree_view_column_get_sort_order:
+ * @tree_column: a #GtkTreeViewColumn
+ *
+ * Gets the value set by gtk_tree_view_column_set_sort_order().
+ *
+ * Return value: the sort order the sort indicator is indicating
+ **/
+GtkTreeSortOrder
+gtk_tree_view_column_get_sort_order (GtkTreeViewColumn *tree_column)
+{
+ g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
- g_object_notify (G_OBJECT (tree_column), "justification");
+ return tree_column->sort_order;
}
diff --git a/gtk/gtktreeviewcolumn.h b/gtk/gtktreeviewcolumn.h
index ea13946c4b..3dbc471afd 100644
--- a/gtk/gtktreeviewcolumn.h
+++ b/gtk/gtktreeviewcolumn.h
@@ -23,6 +23,7 @@
#include <gtk/gtkobject.h>
#include <gtk/gtkcellrenderer.h>
#include <gtk/gtktreemodel.h>
+#include <gtk/gtktreesortable.h>
#ifdef __cplusplus
extern "C" {
@@ -55,9 +56,11 @@ struct _GtkTreeViewColumn
GtkWidget *tree_view;
GtkWidget *button;
- GtkWidget *child;
+ GtkWidget *child;
+ GtkWidget *arrow;
+ GtkWidget *alignment;
GdkWindow *window;
- GtkJustification justification;
+ gfloat xalign;
gint id;
@@ -71,9 +74,11 @@ struct _GtkTreeViewColumn
GtkCellRenderer *cell;
GSList *attributes;
GtkTreeViewColumnSizing column_type;
+ GtkTreeSortOrder sort_order;
guint visible : 1;
guint button_active : 1;
guint dirty : 1;
+ guint show_sort_indicator : 1;
};
struct _GtkTreeViewColumnClass
@@ -91,6 +96,7 @@ GtkTreeViewColumn *gtk_tree_view_column_new_with_attributes (gchar
...);
void gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell);
+GtkCellRenderer *gtk_tree_view_column_get_cell_renderer (GtkTreeViewColumn *tree_column);
void gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
gchar *attribute,
gint column);
@@ -121,18 +127,26 @@ void gtk_tree_view_column_clicked (GtkTreeViewColumn
/* Options for manipulating the column headers
*/
-void gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
- gchar *title);
-gchar *gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column);
-void gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
- gboolean active);
-gboolean gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column);
-void gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
- GtkWidget *widget);
-GtkWidget *gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column);
-void gtk_tree_view_column_set_justification (GtkTreeViewColumn *tree_column,
- GtkJustification justification);
-GtkJustification gtk_tree_view_column_get_justification (GtkTreeViewColumn *tree_column);
+void gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
+ gchar *title);
+G_CONST_RETURN gchar *gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column);
+void gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
+ gboolean active);
+gboolean gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column);
+void gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
+ GtkWidget *widget);
+GtkWidget * gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column);
+void gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
+ gfloat xalign);
+gfloat gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column);
+void gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column,
+ gboolean setting);
+gboolean gtk_tree_view_column_get_sort_indicator (GtkTreeViewColumn *tree_column);
+void gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column,
+ GtkTreeSortOrder order);
+GtkTreeSortOrder gtk_tree_view_column_get_sort_order (GtkTreeViewColumn *tree_column);
+
+