/* Miscellaneous utility functions for the calendar view widgets * * Copyright (C) 1998 The Free Software Foundation * * Authors: Federico Mena * Miguel de Icaza */ #include #include "view-utils.h" #include int am_pm_flag = 0; static char * nicetime (struct tm *tm) { static char buf [20]; char *p = buf; if (am_pm_flag){ if (tm->tm_min) strftime (buf, sizeof (buf), "%l:%M%p", tm); else strftime (buf, sizeof (buf), "%l%p", tm); } else { if (tm->tm_min) strftime (buf, sizeof (buf), "%k:%M", tm); else strftime (buf, sizeof (buf), "%k", tm); } while (*p == ' ') p++; return p; } typedef struct { GnomeIconTextInfo *layout; int lines; int assigned_lines; } line_info_t; void view_utils_draw_events (GtkWidget *widget, GdkWindow *window, GdkGC *gc, GdkRectangle *area, int flags, GList *events, time_t start, time_t end) { GdkFont *font = widget->style->font; int font_height; int y, max_y, items, i, need_more, nlines, base, extra; GList *list; line_info_t *lines; if (events == NULL) return; items = g_list_length (events); lines = g_new0 (line_info_t, items); font_height = font->ascent + font->descent; max_y = area->y + area->height - font_height * ((flags & VIEW_UTILS_DRAW_SPLIT) ? 2 : 1); /* * Layout all the lines, measure the space needs */ for (i = 0, list = events; list; list = list->next, i++){ CalendarObject *co = list->data; struct tm tm_start, tm_end; iCalObject *ico = co->ico; char buf [60]; char *full_text; tm_start = *localtime (&co->ev_start); tm_end = *localtime (&co->ev_end); strcpy (buf, nicetime (&tm_start)); if (flags & VIEW_UTILS_DRAW_END){ strcat (buf, "-"); strcat (buf, nicetime (&tm_end)); } full_text = g_strconcat (buf, ": ", ico->summary, NULL); lines [i].layout = gnome_icon_layout_text ( font, full_text, "\n -,.;:=#", area->width, TRUE); lines [i].lines = g_list_length (lines [i].layout->rows); g_free (full_text); } /* * Compute how many lines we will give to each row */ nlines = 1 + max_y / font_height; base = nlines / items; extra = nlines % items; need_more = 0; for (i = 0; i < items; i++){ if (lines [i].lines <= base){ extra += base - lines [i].lines; lines [i].assigned_lines = lines [i].lines; } else { need_more++; lines [i].assigned_lines = base; } } /* * use any extra space */ while (need_more && extra > 0){ need_more = 0; for (i = 0; i < items; i++){ if (lines [i].lines > lines [i].assigned_lines){ lines [i].assigned_lines++; extra--; } if (extra == 0) break; if (lines [i].lines > lines [i].assigned_lines) need_more = 1; } } /* * Draw the information */ gdk_gc_set_clip_rectangle (gc, area); y = area->y; for (i = 0; i < items; i++){ int line; list = lines [i].layout->rows; for (line = 0; line < lines [i].assigned_lines; line++){ GnomeIconTextInfoRow *row = list->data; list = list->next; if (row) gdk_draw_string ( window, font, gc, area->x, y + font->ascent, row->text); y += font_height; } } gdk_gc_set_clip_rectangle (gc, NULL); /* * Free resources. */ for (i = 0; i < items; i++) gnome_icon_text_info_free (lines [i].layout); g_free (lines); } void view_utils_draw_textured_frame (GtkWidget *widget, GdkWindow *window, GdkRectangle *rect, GtkShadowType shadow) { int x, y; int xthick, ythick; GdkGC *light_gc, *dark_gc; gdk_draw_rectangle (window, widget->style->bg_gc[GTK_STATE_NORMAL], TRUE, rect->x, rect->y, rect->width, rect->height); light_gc = widget->style->light_gc[GTK_STATE_NORMAL]; dark_gc = widget->style->dark_gc[GTK_STATE_NORMAL]; xthick = widget->style->klass->xthickness; ythick = widget->style->klass->ythickness; gdk_gc_set_clip_rectangle (light_gc, rect); gdk_gc_set_clip_rectangle (dark_gc, rect); for (y = rect->y + ythick; y < (rect->y + rect->height - ythick); y += 3) for (x = rect->x + xthick; x < (rect->x + rect->width - xthick); x += 6) { gdk_draw_point (window, light_gc, x, y); gdk_draw_point (window, dark_gc, x + 1, y + 1); gdk_draw_point (window, light_gc, x + 3, y + 1); gdk_draw_point (window, dark_gc, x + 4, y + 2); } gdk_gc_set_clip_rectangle (light_gc, NULL); gdk_gc_set_clip_rectangle (dark_gc, NULL); gtk_draw_shadow (widget->style, window, GTK_STATE_NORMAL, shadow, rect->x, rect->y, rect->width, rect->height); }