Consider details for size-request and expose-event. (#339540)

* gtk/gtkcalendar.c: Add gtk_calendar_get_detail and
is_color_attribute functions. Change gtk_calendar_size_request
and calendar_paint_day to consider and show calender details.

svn path=/trunk/; revision=19261
This commit is contained in:
Mathias Hasselmann 2007-12-28 09:26:20 +00:00
parent fbc0f37062
commit d1e8ca6c4a
2 changed files with 189 additions and 6 deletions

View File

@ -1,3 +1,11 @@
2007-12-28 Mathias Hasselmann <mathias@openismus.com>
Consider details for size-request and expose-event. (#339540)
* gtk/gtkcalendar.c: Add gtk_calendar_get_detail and
is_color_attribute functions. Change gtk_calendar_size_request
and calendar_paint_day to consider and show calender details.
2007-12-28 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkcombobox.c: Introduce local priv variables to

View File

@ -255,6 +255,7 @@ struct _GtkCalendarPrivate
guint arrow_width;
guint max_month_width;
guint max_year_width;
guint max_detail_height;
guint day_width;
guint week_width;
@ -1602,6 +1603,34 @@ gtk_calendar_unrealize (GtkWidget *widget)
(* GTK_WIDGET_CLASS (gtk_calendar_parent_class)->unrealize) (widget);
}
static G_CONST_RETURN gchar*
gtk_calendar_get_detail (GtkCalendar *calendar,
gint row,
gint column)
{
GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
gint year, month;
year = calendar->year;
month = calendar->month + calendar->day_month[row][column] - MONTH_CURRENT;
if (month < 0)
{
month += 12;
year -= 1;
}
else if (month > 11)
{
month -= 12;
year += 1;
}
return priv->detail_func (calendar,
year, month,
calendar->day[row][column],
priv->detail_func_user_data);
}
/****************************************
* Size Request and Allocate *
@ -1617,7 +1646,7 @@ gtk_calendar_size_request (GtkWidget *widget,
PangoRectangle logical_rect;
gint height;
gint i;
gint i, r, c;
gint calendar_margin = CALENDAR_MARGIN;
gint header_width, main_width;
gint max_header_height = 0;
@ -1700,8 +1729,6 @@ gtk_calendar_size_request (GtkWidget *widget,
priv->max_day_char_descent = MAX (priv->max_day_char_descent,
PANGO_DESCENT (logical_rect));
}
/* We add one to max_day_char_width to be able to make the marked day "bold" */
priv->max_day_char_width = priv->min_day_width / 2 + 1;
priv->max_label_char_ascent = 0;
priv->max_label_char_descent = 0;
@ -1730,6 +1757,77 @@ gtk_calendar_size_request (GtkWidget *widget,
logical_rect.width / 2);
}
/* Calculate detail extents. Do this as late as possible since
* pango_layout_set_markup is called which alters font settings. */
priv->max_detail_height = 0;
if (priv->detail_func)
{
gchar *markup, *tail;
if (priv->detail_width_chars || priv->detail_height_rows)
{
gint rows = MAX (1, priv->detail_height_rows) - 1;
gsize len = priv->detail_width_chars + rows + 16;
markup = tail = g_alloca (len);
memcpy (tail, "<small>", 7);
tail += 7;
memset (tail, 'm', priv->detail_width_chars);
tail += priv->detail_width_chars;
memset (tail, '\n', rows);
tail += rows;
memcpy (tail, "</small>", 9);
tail += 9;
g_assert (len == (tail - markup));
pango_layout_set_markup (layout, markup, -1);
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
if (priv->detail_width_chars)
priv->min_day_width = MAX (priv->min_day_width, logical_rect.width);
if (priv->detail_height_rows)
priv->max_detail_height = MAX (priv->max_detail_height, logical_rect.height);
}
if (!priv->detail_width_chars || !priv->detail_height_rows)
for (r = 0; r < 6; r++)
for (c = 0; c < 7; c++)
{
const gchar *detail = gtk_calendar_get_detail (calendar, r, c);
if (detail)
{
markup = g_strconcat ("<small>", detail, "</small>", NULL);
pango_layout_set_markup (layout, markup, -1);
if (priv->detail_width_chars)
{
pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_width (layout, PANGO_SCALE * priv->min_day_width);
}
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
if (!priv->detail_width_chars)
priv->min_day_width = MAX (priv->min_day_width, logical_rect.width);
if (!priv->detail_height_rows)
priv->max_detail_height = MAX (priv->max_detail_height, logical_rect.height);
g_free (markup);
}
}
}
/* We add one to max_day_char_width to be able to make the marked day "bold" */
priv->max_day_char_width = priv->min_day_width / 2 + 1;
main_width = (7 * (priv->min_day_width + (focus_padding + focus_width) * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2
+ (priv->max_week_char_width
? priv->max_week_char_width * 2 + (focus_padding + focus_width) * 2 + CALENDAR_XSEP * 2
@ -1766,6 +1864,7 @@ gtk_calendar_size_request (GtkWidget *widget,
priv->main_h = (CALENDAR_MARGIN + calendar_margin
+ 6 * (priv->max_day_char_ascent
+ priv->max_day_char_descent
+ priv->max_detail_height
+ 2 * (focus_padding + focus_width))
+ DAY_YSEP * 5);
@ -2199,6 +2298,14 @@ calendar_invalidate_day (GtkCalendar *calendar,
}
}
static gboolean
is_color_attribute (PangoAttribute *attribute,
gpointer data)
{
return (attribute->klass->type == PANGO_ATTR_FOREGROUND ||
attribute->klass->type == PANGO_ATTR_BACKGROUND);
}
static void
calendar_paint_day (GtkCalendar *calendar,
gint row,
@ -2208,6 +2315,7 @@ calendar_paint_day (GtkCalendar *calendar,
GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
cairo_t *cr;
GdkColor *text_color;
const gchar *detail;
gchar buffer[32];
gint day;
gint x_loc, y_loc;
@ -2269,12 +2377,20 @@ calendar_paint_day (GtkCalendar *calendar,
* too.
*/
g_snprintf (buffer, sizeof (buffer), Q_("calendar:day:digits|%d"), day);
/* Get extra information to show, if any: */
if (priv->detail_func)
detail = gtk_calendar_get_detail (calendar, row, col);
else
detail = NULL;
layout = gtk_widget_create_pango_layout (widget, buffer);
pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
x_loc = day_rect.x + day_rect.width / 2 + priv->max_day_char_width;
x_loc -= logical_rect.width;
y_loc = day_rect.y + (day_rect.height - logical_rect.height) / 2;
x_loc = day_rect.x + (day_rect.width - logical_rect.width) / 2;
y_loc = day_rect.y;
gdk_cairo_set_source_color (cr, text_color);
cairo_move_to (cr, x_loc, y_loc);
@ -2287,6 +2403,65 @@ calendar_paint_day (GtkCalendar *calendar,
pango_cairo_show_layout (cr, layout);
}
y_loc += priv->max_day_char_descent;
if (priv->detail_func)
{
cairo_set_line_width (cr, 1);
cairo_move_to (cr, day_rect.x + 1, y_loc + 0.5);
cairo_line_to (cr, day_rect.x + day_rect.width - 1, y_loc + 0.5);
cairo_stroke (cr);
y_loc += 2;
}
if (detail)
{
gint i, n_lines;
gchar *markup = g_strconcat ("<small>", detail, "</small>", NULL);
pango_layout_set_markup (layout, markup, -1);
g_free (markup);
if (day == calendar->selected_day)
{
/* Stripping colors as they conflict with selection marking. */
PangoAttrList *attrs = pango_layout_get_attributes (layout);
PangoAttrList *colors = NULL;
if (attrs)
colors = pango_attr_list_filter (attrs, is_color_attribute, NULL);
if (colors)
pango_attr_list_unref (colors);
}
if (priv->detail_width_chars)
{
pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_width (layout, PANGO_SCALE * priv->min_day_width);
}
n_lines = pango_layout_get_line_count (layout);
if (priv->detail_height_rows)
n_lines = MIN (n_lines, priv->detail_height_rows);
for (i = 0; i < n_lines; ++i)
{
PangoLayoutLine *line = pango_layout_get_line_readonly (layout, i);
pango_layout_line_get_pixel_extents (line, NULL, &logical_rect);
x_loc = day_rect.x + (day_rect.width - logical_rect.width) / 2;
y_loc += PANGO_ASCENT (logical_rect);
cairo_move_to (cr, x_loc, y_loc);
pango_cairo_show_layout_line (cr, line);
y_loc += PANGO_DESCENT (logical_rect);
}
}
if (GTK_WIDGET_HAS_FOCUS (calendar)
&& calendar->focus_row == row && calendar->focus_col == col)
{