diff options
Diffstat (limited to 'calendar/gncal-full-day.c')
-rw-r--r-- | calendar/gncal-full-day.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/calendar/gncal-full-day.c b/calendar/gncal-full-day.c new file mode 100644 index 0000000000..4b4820417a --- /dev/null +++ b/calendar/gncal-full-day.c @@ -0,0 +1,320 @@ +/* Full day widget for gncal + * + * Copyright (C) 1998 The Free Software Foundation + * + * Author: Federico Mena <federico@nuclecu.unam.mx> + */ + +#include <gtk/gtkdrawingarea.h> +#include "gncal-full-day.h" + + +#define TEXT_BORDER 2 +#define MIN_WIDTH 200 + + +static void gncal_full_day_class_init (GncalFullDayClass *class); +static void gncal_full_day_init (GncalFullDay *fullday); +static void gncal_full_day_realize (GtkWidget *widget); +static void gncal_full_day_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gncal_full_day_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static gint gncal_full_day_expose (GtkWidget *widget, + GdkEventExpose *event); + + +static GtkContainerClass *parent_class; + + +guint +gncal_full_day_get_type (void) +{ + static guint full_day_type = 0; + + if (!full_day_type) { + GtkTypeInfo full_day_info = { + "GncalFullDay", + sizeof (GncalFullDay), + sizeof (GncalFullDayClass), + (GtkClassInitFunc) gncal_full_day_class_init, + (GtkObjectInitFunc) gncal_full_day_init, + (GtkArgSetFunc) NULL, + (GtkArgGetFunc) NULL + }; + + full_day_type = gtk_type_unique (gtk_container_get_type (), &full_day_info); + } + + return full_day_type; +} + +static void +gncal_full_day_class_init (GncalFullDayClass *class) +{ + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + widget_class = (GtkWidgetClass *) class; + container_class = (GtkContainerClass *) class; + + parent_class = gtk_type_class (gtk_container_get_type ()); + + widget_class->realize = gncal_full_day_realize; + widget_class->size_request = gncal_full_day_size_request; + widget_class->size_allocate = gncal_full_day_size_allocate; + widget_class->expose_event = gncal_full_day_expose; +} + +static void +gncal_full_day_init (GncalFullDay *fullday) +{ + GTK_WIDGET_UNSET_FLAGS (fullday, GTK_NO_WINDOW); + + fullday->calendar = NULL; + + fullday->lower = 0; + fullday->upper = 0; + fullday->interval = 30; /* 30 minutes by default */ +} + +GtkWidget * +gncal_full_day_new (GnomeCalendar *calendar, time_t lower, time_t upper) +{ + GncalFullDay *fullday; + + g_return_val_if_fail (calendar != NULL, NULL); + + fullday = gtk_type_new (gncal_full_day_get_type ()); + + fullday->calendar = calendar; + + gncal_full_day_set_bounds (fullday, lower, upper); + + return GTK_WIDGET (fullday); +} + +static void +gncal_full_day_realize (GtkWidget *widget) +{ + GdkWindowAttr attributes; + gint attributes_mask; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GNCAL_IS_FULL_DAY (widget)); + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = (gtk_widget_get_events (widget) + | GDK_EXPOSURE_MASK); + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, widget); + + widget->style = gtk_style_attach (widget->style, widget->window); + gdk_window_set_background (widget->window, &widget->style->bg[GTK_STATE_PRELIGHT]); +} + +static int +get_tm_bounds (GncalFullDay *fullday, struct tm *lower, struct tm *upper) +{ + struct tm tm_lower, tm_upper; + int lmin, umin; + + /* Lower */ + + tm_lower = *localtime (&fullday->lower); + + if ((tm_lower.tm_min % fullday->interval) != 0) { + tm_lower.tm_min -= tm_lower.tm_min % fullday->interval; /* round down */ + mktime (&tm_lower); + } + + /* Upper */ + + tm_upper = *localtime (&fullday->upper); + + if ((tm_upper.tm_min % fullday->interval) != 0) { + tm_upper.tm_min += fullday->interval - (tm_upper.tm_min % fullday->interval); /* round up */ + mktime (&tm_upper); + } + + if (lower) + *lower = tm_lower; + + if (upper) + *upper = tm_upper; + + lmin = 60 * tm_lower.tm_hour + tm_lower.tm_min; + umin = 60 * tm_upper.tm_hour + tm_upper.tm_min; + + return (umin - lmin) / fullday->interval; /* number of rows in view */ +} + +static int +calc_labels_width (GncalFullDay *fullday) +{ + struct tm cur, upper; + time_t tim, time_upper; + int width, max_w; + char buf[256]; + + get_tm_bounds (fullday, &cur, &upper); + + max_w = 0; + + tim = mktime (&cur); + time_upper = mktime (&upper); + + while (tim < time_upper) { + strftime (buf, 256, "%R%p", &cur); + + width = gdk_string_width (GTK_WIDGET (fullday)->style->font, buf); + + if (width > max_w) + max_w = width; + + cur.tm_min += fullday->interval; + tim = mktime (&cur); + } + + return max_w; +} + +static void +gncal_full_day_size_request (GtkWidget *widget, GtkRequisition *requisition) +{ + GncalFullDay *fullday; + int labels_width; + int rows; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GNCAL_IS_FULL_DAY (widget)); + g_return_if_fail (requisition != NULL); + + fullday = GNCAL_FULL_DAY (widget); + + /* Border and min width */ + + labels_width = calc_labels_width (fullday); + + requisition->width = 2 * widget->style->klass->xthickness + 4 * TEXT_BORDER + labels_width + MIN_WIDTH; + requisition->height = 2 * widget->style->klass->ythickness; + + /* Rows */ + + rows = get_tm_bounds (fullday, NULL, NULL); + + requisition->height += (rows * (2 * TEXT_BORDER + widget->style->font->ascent + widget->style->font->descent) + + (rows - 1)); /* division lines */ +} + +static void +gncal_full_day_size_allocate (GtkWidget *widget, GtkAllocation *allocation) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GNCAL_IS_FULL_DAY (widget)); + g_return_if_fail (allocation != NULL); + + widget->allocation = *allocation; + + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); + + /* FIXME: adjust children */ +} + +static void +paint_back (GncalFullDay *fullday, GdkRectangle *area) +{ + GtkWidget *widget; + GdkRectangle rect; + int x1, y1, width, height; + int labels_width, division_x; + + widget = GTK_WIDGET (fullday); + + x1 = widget->style->klass->xthickness; + y1 = widget->style->klass->ythickness; + width = widget->allocation.width - 2 * x1; + height = widget->allocation.height - 2 * y1; + + /* Clear and paint frame shadow */ + + gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height); + + gtk_draw_shadow (widget->style, widget->window, + GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_IN, + 0, 0, + widget->allocation.width, + widget->allocation.height); + + /* Vertical division */ + + labels_width = calc_labels_width (fullday); + + division_x = x1 + 2 * TEXT_BORDER + labels_width; + + gtk_draw_vline (widget->style, widget->window, + GTK_STATE_NORMAL, + y1, + y1 + height - 1, + division_x); +} + +static gint +gncal_full_day_expose (GtkWidget *widget, GdkEventExpose *event) +{ + GncalFullDay *fullday; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GNCAL_IS_FULL_DAY (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + if (!GTK_WIDGET_DRAWABLE (widget)) + return FALSE; + + fullday = GNCAL_FULL_DAY (widget); + + if (event->window == widget->window) + paint_back (fullday, &event->area); + + /* FIXME: paint handles in windows if event->window == blah blah */ + + return FALSE; +} + +void +gncal_full_day_update (GncalFullDay *fullday) +{ + g_return_if_fail (fullday != NULL); + g_return_if_fail (GNCAL_IS_FULL_DAY (fullday)); + + /* FIXME */ +} + +void +gncal_full_day_set_bounds (GncalFullDay *fullday, time_t lower, time_t upper) +{ + g_return_if_fail (fullday != NULL); + g_return_if_fail (GNCAL_IS_FULL_DAY (fullday)); + + if ((lower != fullday->lower) || (upper != fullday->upper)) { + fullday->lower = lower; + fullday->upper = upper; + + gncal_full_day_update (fullday); + } +} |