diff options
author | Owen Taylor <otaylor@redhat.com> | 2001-09-25 20:40:20 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2001-09-25 20:40:20 +0000 |
commit | 0c3be55498e388015bcba07791177be9d1225bd9 (patch) | |
tree | adcafce7f55404b0b8a6ab1f86967a54fe2cf69c /gtk | |
parent | efae27a3a5d7ed8cb7063e1f0ac5634fc162284f (diff) | |
download | gtk+-0c3be55498e388015bcba07791177be9d1225bd9.tar.gz |
ue Sep 25 12:41:17 2001 Owen Taylor <otaylor@redhat.com>GTK_1_3_9
* configure.in: Version 1.3.9, interface age 0, binary age 0.
* configure.in: Require GLib-1.39, Pango 0.20, Atk 0.5.
* NEWS: Updates.
Mon Sep 24 11:59:09 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkstyle.[ch] (_gtk_draw_insertion_cursor): Shared
function for drawing cursors between gtkentry/gtklabel/gtktextview.
Should this be public? It has a bit of an odd interface, but
custom editing widgets probably should be using it.
Function will draw with wider width for taller cursors, and
draws a little indicator arrow to indicate directoin for split
cursors.
* gtk/gtktextview.c: Add a "cursor_color" property.
* gtk/gtktextdisplay.[ch]: Add a cursor_gc parameter to
gtk_text_layout_draw().
* gtk/gtkentry.c gtk/gtklabel.c gtk/gtktextdisplay.c: Use
_gtk_draw_insertion_cursor().
Tue Sep 25 11:22:23 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkcellrenderertext.c gtk/gtktexttag.c: Restore
the behavior where you could turn family_set (etc) back on
and get back the values you had before.
* demos/gtk-demo/stock_browser.c (id_to_macro): Use
g_string_ascii_up() rather than looping through the
string ourself.
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtkcellrenderertext.c | 72 | ||||
-rw-r--r-- | gtk/gtkentry.c | 24 | ||||
-rw-r--r-- | gtk/gtklabel.c | 30 | ||||
-rw-r--r-- | gtk/gtkstyle.c | 57 | ||||
-rw-r--r-- | gtk/gtkstyle.h | 5 | ||||
-rw-r--r-- | gtk/gtktextdisplay.c | 47 | ||||
-rw-r--r-- | gtk/gtktextdisplay.h | 2 | ||||
-rw-r--r-- | gtk/gtktexttag.c | 76 | ||||
-rw-r--r-- | gtk/gtktextview.c | 41 | ||||
-rw-r--r-- | gtk/gtktextview.h | 1 |
10 files changed, 330 insertions, 25 deletions
diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c index bced2d8c14..5f7e9626c9 100644 --- a/gtk/gtkcellrenderertext.c +++ b/gtk/gtkcellrenderertext.c @@ -668,6 +668,46 @@ set_fg_color (GtkCellRendererText *celltext, } } +static PangoFontMask +set_font_desc_fields (PangoFontDescription *desc, + PangoFontMask to_set) +{ + PangoFontMask changed_mask = 0; + + if (to_set & PANGO_FONT_MASK_FAMILY) + { + const char *family = pango_font_description_get_family (desc); + if (!family) + { + family = "sans"; + changed_mask |= PANGO_FONT_MASK_FAMILY; + } + + pango_font_description_set_family (desc, family); + } + if (to_set & PANGO_FONT_MASK_STYLE) + pango_font_description_set_style (desc, pango_font_description_get_style (desc)); + if (to_set & PANGO_FONT_MASK_VARIANT) + pango_font_description_set_variant (desc, pango_font_description_get_variant (desc)); + if (to_set & PANGO_FONT_MASK_WEIGHT) + pango_font_description_set_weight (desc, pango_font_description_get_weight (desc)); + if (to_set & PANGO_FONT_MASK_STRETCH) + pango_font_description_set_stretch (desc, pango_font_description_get_stretch (desc)); + if (to_set & PANGO_FONT_MASK_SIZE) + { + gint size = pango_font_description_get_size (desc); + if (size <= 0) + { + size = 10 * PANGO_SCALE; + changed_mask |= PANGO_FONT_MASK_SIZE; + } + + pango_font_description_set_size (desc, size); + } + + return changed_mask; +} + static void notify_set_changed (GObject *object, PangoFontMask changed_mask) @@ -687,6 +727,24 @@ notify_set_changed (GObject *object, } static void +notify_fields_changed (GObject *object, + PangoFontMask changed_mask) +{ + if (changed_mask & PANGO_FONT_MASK_FAMILY) + g_object_notify (object, "family"); + if (changed_mask & PANGO_FONT_MASK_STYLE) + g_object_notify (object, "style"); + if (changed_mask & PANGO_FONT_MASK_VARIANT) + g_object_notify (object, "variant"); + if (changed_mask & PANGO_FONT_MASK_WEIGHT) + g_object_notify (object, "weight"); + if (changed_mask & PANGO_FONT_MASK_STRETCH) + g_object_notify (object, "stretch"); + if (changed_mask & PANGO_FONT_MASK_SIZE) + g_object_notify (object, "size"); +} + +static void set_font_description (GtkCellRendererText *celltext, PangoFontDescription *font_desc) { @@ -960,8 +1018,18 @@ gtk_cell_renderer_text_set_property (GObject *object, case PROP_STRETCH_SET: case PROP_SIZE_SET: if (!g_value_get_boolean (value)) - pango_font_description_unset_fields (celltext->font, - get_property_font_set_mask (param_id)); + { + pango_font_description_unset_fields (celltext->font, + get_property_font_set_mask (param_id)); + } + else + { + PangoFontMask changed_mask; + + changed_mask = set_font_desc_fields (celltext->font, + get_property_font_set_mask (param_id)); + notify_fields_changed (G_OBJECT (celltext), changed_mask); + } break; case PROP_SCALE_SET: diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index c8931e4818..0554f001f4 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -2653,6 +2653,7 @@ gtk_entry_draw_cursor (GtkEntry *entry, if (GTK_WIDGET_DRAWABLE (entry)) { GtkWidget *widget = GTK_WIDGET (entry); + GdkRectangle cursor_location; gboolean split_cursor; gint xoffset = INNER_BORDER - entry->scroll_offset; @@ -2660,6 +2661,8 @@ gtk_entry_draw_cursor (GtkEntry *entry, gint text_area_height; GdkGC *gc1 = NULL; GdkGC *gc2 = NULL; + GtkTextDirection dir1 = GTK_TEXT_DIR_NONE; + GtkTextDirection dir2 = GTK_TEXT_DIR_NONE; gint x1 = 0; gint x2 = 0; @@ -2678,6 +2681,9 @@ gtk_entry_draw_cursor (GtkEntry *entry, if (weak_x != strong_x) { + dir1 = widget_direction; + dir2 = (widget_direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR; + gc2 = widget->style->text_gc[GTK_STATE_NORMAL]; x2 = weak_x; } @@ -2691,15 +2697,21 @@ gtk_entry_draw_cursor (GtkEntry *entry, else x1 = weak_x; } + + cursor_location.x = xoffset + x1; + cursor_location.y = INNER_BORDER; + cursor_location.width = 0; + cursor_location.height = text_area_height - 2 * INNER_BORDER ; - gdk_draw_line (entry->text_area, gc1, - xoffset + x1, INNER_BORDER, - xoffset + x1, text_area_height - INNER_BORDER); + _gtk_draw_insertion_cursor (entry->text_area, gc1, + &cursor_location, dir1); if (gc2) - gdk_draw_line (entry->text_area, gc2, - xoffset + x2, INNER_BORDER, - xoffset + x2, text_area_height - INNER_BORDER); + { + cursor_location.x = xoffset + x2; + _gtk_draw_insertion_cursor (entry->text_area, gc2, + &cursor_location, dir2); + } } } diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 89d74efca6..23cfa66069 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -1595,13 +1595,16 @@ gtk_label_draw_cursor (GtkLabel *label, gint xoffset, gint yoffset) if (GTK_WIDGET_DRAWABLE (label)) { GtkWidget *widget = GTK_WIDGET (label); - + GtkTextDirection keymap_direction; GtkTextDirection widget_direction; PangoRectangle strong_pos, weak_pos; gboolean split_cursor; PangoRectangle *cursor1 = NULL; PangoRectangle *cursor2 = NULL; + GdkRectangle cursor_location; + GtkTextDirection dir1 = GTK_TEXT_DIR_NONE; + GtkTextDirection dir2 = GTK_TEXT_DIR_NONE; GdkGC *gc1 = NULL; GdkGC *gc2 = NULL; @@ -1628,6 +1631,9 @@ gtk_label_draw_cursor (GtkLabel *label, gint xoffset, gint yoffset) if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y) { + dir1 = widget_direction; + dir2 = (widget_direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR; + gc2 = widget->style->black_gc; cursor2 = &weak_pos; } @@ -1642,14 +1648,24 @@ gtk_label_draw_cursor (GtkLabel *label, gint xoffset, gint yoffset) cursor1 = &weak_pos; } - gdk_draw_line (widget->window, gc1, - xoffset + PANGO_PIXELS (cursor1->x), yoffset + PANGO_PIXELS (cursor1->y), - xoffset + PANGO_PIXELS (cursor1->x), yoffset + PANGO_PIXELS (cursor1->y + cursor1->height)); + cursor_location.x = xoffset + PANGO_PIXELS (cursor1->x); + cursor_location.y = yoffset + PANGO_PIXELS (cursor1->y); + cursor_location.width = 0; + cursor_location.height = PANGO_PIXELS (cursor1->height); + + _gtk_draw_insertion_cursor (widget->window, gc1, + &cursor_location, dir1); if (gc2) - gdk_draw_line (widget->window, gc2, - xoffset + PANGO_PIXELS (cursor2->x), yoffset + PANGO_PIXELS (cursor2->y), - xoffset + PANGO_PIXELS (cursor2->x), yoffset + PANGO_PIXELS (cursor2->y + cursor2->height)); + { + cursor_location.x = xoffset + PANGO_PIXELS (cursor2->x); + cursor_location.y = yoffset + PANGO_PIXELS (cursor2->y); + cursor_location.width = 0; + cursor_location.height = PANGO_PIXELS (cursor2->height); + + _gtk_draw_insertion_cursor (widget->window, gc2, + &cursor_location, dir2); + } } } diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index d3a7fc7c2e..bc3f092633 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -5043,3 +5043,60 @@ gtk_style_set_font (GtkStyle *style, style->private_font_desc = NULL; } } + +/** + * _gtk_draw_insertion_cursor: + * @drawable: a #GdkDrawable + * @gc: a #GdkGC + * @location: location where to draw the cursor (@location->width is ignored) + * @dir: text direction for the cursor, used to decide whether to draw a + * directional arrow on the cursor and in what direction. Unless both + * strong and weak cursors are displayed, this should be %GTK_TEXT_DIR_NONE. + * + * Draws a text caret on @drawable at @location. This is not a style function + * but merely a convenience function for drawing the standard cursor shape. + **/ +void +_gtk_draw_insertion_cursor (GdkDrawable *drawable, + GdkGC *gc, + GdkRectangle *location, + GtkTextDirection dir) +{ + gint stem_width = location->height / 30 + 1; + gint arrow_width = stem_width + 1; + gint x, y; + gint i; + + for (i = 0; i < stem_width; i++) + gdk_draw_line (drawable, gc, + location->x + i - stem_width / 2, location->y, + location->x + i - stem_width / 2, location->y + location->height); + + if (dir == GTK_TEXT_DIR_RTL) + { + x = location->x - stem_width / 2 - 1; + y = location->y + location->height - arrow_width * 2 - arrow_width + 1; + + for (i = 0; i < arrow_width; i++) + { + gdk_draw_line (drawable, gc, + x, y + i + 1, + x, y + 2 * arrow_width - i - 1); + x --; + } + } + else if (dir == GTK_TEXT_DIR_LTR) + { + x = location->x + stem_width - stem_width / 2; + y = location->y + location->height - arrow_width * 2 - arrow_width + 1; + + for (i = 0; i < arrow_width; i++) + { + gdk_draw_line (drawable, gc, + x, y + i + 1, + x, y + 2 * arrow_width - i - 1); + x++; + } + } +} + diff --git a/gtk/gtkstyle.h b/gtk/gtkstyle.h index a6de90197f..14fcf3d2c6 100644 --- a/gtk/gtkstyle.h +++ b/gtk/gtkstyle.h @@ -868,6 +868,11 @@ void gtk_paint_string (GtkStyle *style, const gchar *string); #endif /* GTK_DISABLE_DEPRECATED */ +void _gtk_draw_insertion_cursor (GdkDrawable *drawable, + GdkGC *gc, + GdkRectangle *location, + GtkTextDirection dir); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gtk/gtktextdisplay.c b/gtk/gtktextdisplay.c index d605a1ba1d..51ef0ae125 100644 --- a/gtk/gtktextdisplay.c +++ b/gtk/gtktextdisplay.c @@ -716,6 +716,7 @@ void gtk_text_layout_draw (GtkTextLayout *layout, GtkWidget *widget, GdkDrawable *drawable, + GdkGC *cursor_gc, /* Location of the drawable in layout coordinates */ gint x_offset, @@ -775,6 +776,8 @@ gtk_text_layout_draw (GtkTextLayout *layout, GtkTextLineDisplay *line_display; gint selection_start_index = -1; gint selection_end_index = -1; + gboolean have_strong; + gboolean have_weak; GtkTextLine *line = tmp_list->data; @@ -823,23 +826,53 @@ gtk_text_layout_draw (GtkTextLayout *layout, /* We paint the cursors last, because they overlap another chunk and need to appear on top. */ + have_strong = FALSE; + have_weak = FALSE; + + cursor_list = line_display->cursors; + while (cursor_list) + { + GtkTextCursorDisplay *cursor = cursor_list->data; + if (cursor->is_strong) + have_strong = TRUE; + else + have_weak = TRUE; + + cursor_list = cursor_list->next; + } + cursor_list = line_display->cursors; while (cursor_list) { GtkTextCursorDisplay *cursor = cursor_list->data; + GtkTextDirection dir; + GdkRectangle cursor_location; + GdkGC *gc; if (cursor->is_strong) - gc = widget->style->base_gc[GTK_STATE_SELECTED]; + gc = cursor_gc; else gc = widget->style->text_gc[GTK_STATE_NORMAL]; - gdk_gc_set_clip_rectangle (gc, &clip); - gdk_draw_line (drawable, gc, - line_display->x_offset + cursor->x - x_offset, - current_y + line_display->top_margin + cursor->y, - line_display->x_offset + cursor->x - x_offset, - current_y + line_display->top_margin + cursor->y + cursor->height - 1); + if (have_strong && have_weak) + { + dir = line_display->direction; + if (!cursor->is_strong) + dir = (dir == GTK_TEXT_DIR_RTL) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL; + } + else + { + dir = GTK_TEXT_DIR_NONE; + } + + cursor_location.x = line_display->x_offset + cursor->x - x_offset; + cursor_location.y = current_y + line_display->top_margin + cursor->y; + cursor_location.width = 0; + cursor_location.height = cursor->height; + + gdk_gc_set_clip_rectangle(gc, &clip); + _gtk_draw_insertion_cursor (drawable, gc, &cursor_location, dir); gdk_gc_set_clip_rectangle (gc, NULL); cursor_list = cursor_list->next; diff --git a/gtk/gtktextdisplay.h b/gtk/gtktextdisplay.h index 03ec505dc5..c44a90f03a 100644 --- a/gtk/gtktextdisplay.h +++ b/gtk/gtktextdisplay.h @@ -90,6 +90,7 @@ extern "C" { /* The drawable should be pre-initialized to your preferred background. * widget - Widget to grab some style info from * drawable - Drawable to render to + * cursor_gc - Graphics context to use for cursor * x_offset/y_offset - Position of the drawable in layout coordinates * x/y/width/height - Region of the layout to render. x,y must be inside * the drawable. @@ -97,6 +98,7 @@ extern "C" { void gtk_text_layout_draw (GtkTextLayout *layout, GtkWidget *widget, GdkDrawable *drawable, + GdkGC *cursor_gc, gint x_offset, gint y_offset, gint x, diff --git a/gtk/gtktexttag.c b/gtk/gtktexttag.c index fbd90eb4ca..f4f1c749ec 100644 --- a/gtk/gtktexttag.c +++ b/gtk/gtktexttag.c @@ -749,6 +749,46 @@ get_property_font_set_mask (guint prop_id) return 0; } +static PangoFontMask +set_font_desc_fields (PangoFontDescription *desc, + PangoFontMask to_set) +{ + PangoFontMask changed_mask = 0; + + if (to_set & PANGO_FONT_MASK_FAMILY) + { + const char *family = pango_font_description_get_family (desc); + if (!family) + { + family = "sans"; + changed_mask |= PANGO_FONT_MASK_FAMILY; + } + + pango_font_description_set_family (desc, family); + } + if (to_set & PANGO_FONT_MASK_STYLE) + pango_font_description_set_style (desc, pango_font_description_get_style (desc)); + if (to_set & PANGO_FONT_MASK_VARIANT) + pango_font_description_set_variant (desc, pango_font_description_get_variant (desc)); + if (to_set & PANGO_FONT_MASK_WEIGHT) + pango_font_description_set_weight (desc, pango_font_description_get_weight (desc)); + if (to_set & PANGO_FONT_MASK_STRETCH) + pango_font_description_set_stretch (desc, pango_font_description_get_stretch (desc)); + if (to_set & PANGO_FONT_MASK_SIZE) + { + gint size = pango_font_description_get_size (desc); + if (size <= 0) + { + size = 10 * PANGO_SCALE; + changed_mask |= PANGO_FONT_MASK_SIZE; + } + + pango_font_description_set_size (desc, size); + } + + return changed_mask; +} + static void notify_set_changed (GObject *object, PangoFontMask changed_mask) @@ -768,6 +808,24 @@ notify_set_changed (GObject *object, } static void +notify_fields_changed (GObject *object, + PangoFontMask changed_mask) +{ + if (changed_mask & PANGO_FONT_MASK_FAMILY) + g_object_notify (object, "family"); + if (changed_mask & PANGO_FONT_MASK_STYLE) + g_object_notify (object, "style"); + if (changed_mask & PANGO_FONT_MASK_VARIANT) + g_object_notify (object, "variant"); + if (changed_mask & PANGO_FONT_MASK_WEIGHT) + g_object_notify (object, "weight"); + if (changed_mask & PANGO_FONT_MASK_STRETCH) + g_object_notify (object, "stretch"); + if (changed_mask & PANGO_FONT_MASK_SIZE) + g_object_notify (object, "size"); +} + +static void set_font_description (GtkTextTag *text_tag, PangoFontDescription *font_desc) { @@ -1174,9 +1232,21 @@ gtk_text_tag_set_property (GObject *object, case PROP_WEIGHT_SET: case PROP_STRETCH_SET: case PROP_SIZE_SET: - if (!g_value_get_boolean (value) && text_tag->values->font) - pango_font_description_unset_fields (text_tag->values->font, - get_property_font_set_mask (prop_id)); + if (!g_value_get_boolean (value)) + { + if (text_tag->values->font) + pango_font_description_unset_fields (text_tag->values->font, + get_property_font_set_mask (prop_id)); + } + else + { + PangoFontMask changed_mask; + + gtk_text_tag_ensure_font (text_tag); + changed_mask = set_font_desc_fields (text_tag->values->font, + get_property_font_set_mask (prop_id)); + notify_fields_changed (G_OBJECT (text_tag), changed_mask); + } break; case PROP_SCALE_SET: diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index 0e864b178a..254ad44c5e 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -620,6 +620,18 @@ gtk_text_view_class_init (GtkTextViewClass *klass) /* + * Style properties + */ + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boxed ("cursor_color", + _("Cursor color"), + _("Color with which to draw insertion cursor"), + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + + + /* * Signals */ @@ -2909,6 +2921,24 @@ changed_handler (GtkTextLayout *layout, } static void +gtk_text_view_realize_cursor_gc (GtkTextView *text_view) +{ + GdkColor *cursor_color; + GdkColor red = { 0, 0xffff, 0x0000, 0x0000 }; + + if (text_view->cursor_gc) + gdk_gc_unref (text_view->cursor_gc); + + gtk_widget_style_get (GTK_WIDGET (text_view), "cursor_color", &cursor_color, NULL); + + if (!cursor_color) + cursor_color = &red; + + text_view->cursor_gc = gdk_gc_new (text_view->text_window->bin_window); + gdk_gc_set_rgb_fg_color (text_view->cursor_gc, cursor_color); +} + +static void gtk_text_view_realize (GtkWidget *widget) { GtkTextView *text_view; @@ -2958,6 +2988,8 @@ gtk_text_view_realize (GtkWidget *widget) text_window_realize (text_view->bottom_window, widget->window); + gtk_text_view_realize_cursor_gc (text_view); + gtk_text_view_ensure_layout (text_view); if (text_view->buffer) @@ -2976,6 +3008,12 @@ gtk_text_view_unrealize (GtkWidget *widget) gtk_text_buffer_remove_selection_clipboard (text_view->buffer, gtk_clipboard_get (GDK_SELECTION_PRIMARY)); + if (text_view->cursor_gc) + { + gdk_gc_unref (text_view->cursor_gc); + text_view->cursor_gc = NULL; + } + if (text_view->first_validate_idle) { g_source_remove (text_view->first_validate_idle); @@ -3041,6 +3079,8 @@ gtk_text_view_style_set (GtkWidget *widget, if (text_view->bottom_window) gdk_window_set_background (text_view->bottom_window->bin_window, &widget->style->bg[GTK_WIDGET_STATE (widget)]); + + gtk_text_view_realize_cursor_gc (text_view); } if (text_view->layout && previous_style) @@ -3575,6 +3615,7 @@ gtk_text_view_paint (GtkWidget *widget, GdkRectangle *area) gtk_text_layout_draw (text_view->layout, widget, text_view->text_window->bin_window, + text_view->cursor_gc, text_view->xoffset, text_view->yoffset, area->x, area->y, diff --git a/gtk/gtktextview.h b/gtk/gtktextview.h index bcb89b24f9..b4c775daa9 100644 --- a/gtk/gtktextview.h +++ b/gtk/gtktextview.h @@ -142,6 +142,7 @@ struct _GtkTextView GSList *children; GtkTextPendingScroll *pending_scroll; + GdkGC *cursor_gc; }; struct _GtkTextViewClass |