aboutsummaryrefslogblamecommitdiffstats
path: root/calendar/gncal-day-view.c
blob: e6a511f7367f726eb7026d326112a8933a71afdf (plain) (tree)





























































































































































































































































                                                                                                                    
/* Day view widget for gncal
 *
 * Copyright (C) 1998 The Free Software Foundation
 *
 * Author: Federico Mena <federico@nuclecu.unam.mx>
 */

#include "gncal-day-view.h"
#include "timeutil.h"


#define TEXT_BORDER 2
#define MIN_INFO_WIDTH 50


static void gncal_day_view_class_init   (GncalDayViewClass *class);
static void gncal_day_view_init         (GncalDayView      *dview);
static void gncal_day_view_realize      (GtkWidget         *widget);
static void gncal_day_view_size_request (GtkWidget         *widget,
                     GtkRequisition    *requisition);
static gint gncal_day_view_expose       (GtkWidget         *widget,
                     GdkEventExpose    *event);


static GtkWidgetClass *parent_class;


guint
gncal_day_view_get_type (void)
{
    static guint day_view_type = 0;

    if (!day_view_type) {
        GtkTypeInfo day_view_info = {
            "GncalDayView",
            sizeof (GncalDayView),
            sizeof (GncalDayViewClass),
            (GtkClassInitFunc) gncal_day_view_class_init,
            (GtkObjectInitFunc) gncal_day_view_init,
            (GtkArgSetFunc) NULL,
            (GtkArgGetFunc) NULL
        };

        day_view_type = gtk_type_unique (gtk_widget_get_type (), &day_view_info);
    }

    return day_view_type;
}

static void
gncal_day_view_class_init (GncalDayViewClass *class)
{
    GtkObjectClass *object_class;
    GtkWidgetClass *widget_class;

    object_class = (GtkObjectClass *) class;
    widget_class = (GtkWidgetClass *) class;

    parent_class = gtk_type_class (gtk_widget_get_type ());

    widget_class->realize = gncal_day_view_realize;
    widget_class->size_request = gncal_day_view_size_request;
    widget_class->expose_event = gncal_day_view_expose;
}

static void
gncal_day_view_init (GncalDayView *dview)
{
    GTK_WIDGET_UNSET_FLAGS (dview, GTK_NO_WINDOW);

    dview->calendar = NULL;

    dview->lower = 0;
    dview->upper = 24;
    dview->use_am_pm = TRUE;
}

GtkWidget *
gncal_day_view_new (Calendar *calendar)
{
    GncalDayView *dview;

#if 0
    g_assert (calendar != NULL);
#endif

    dview = gtk_type_new (gncal_day_view_get_type ());

    dview->calendar = calendar;

    return GTK_WIDGET (dview);
}

static void
gncal_day_view_realize (GtkWidget *widget)
{
    GdkWindowAttr attributes;
    gint attributes_mask;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (GNCAL_IS_DAY_VIEW (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
                 | GDK_BUTTON_PRESS_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);

    gtk_style_set_background (widget->style, widget->window, GTK_STATE_SELECTED);
}

static int
calc_labels_width (GncalDayView *dview)
{
    int width, max_width;
    GdkFont *font;
    char *buf;
    int i;

    font = GTK_WIDGET (dview)->style->font;

    max_width = 0;

    for (i = 0; i < 24; i++) {
        buf = format_simple_hour (i, dview->use_am_pm);
        width = gdk_string_width (font, buf);
        if (width > max_width)
            max_width = width;
    }

    return width;
}

static void
gncal_day_view_size_request (GtkWidget *widget, GtkRequisition *requisition)
{
    GncalDayView *dview;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (GNCAL_IS_DAY_VIEW (widget));
    g_return_if_fail (requisition != NULL);

    dview = GNCAL_DAY_VIEW (widget);

    requisition->width = 2 * widget->style->klass->xthickness + 4 * TEXT_BORDER + MIN_INFO_WIDTH;
    requisition->height = 2 * widget->style->klass->xthickness;

    requisition->width += calc_labels_width (dview);
    requisition->height += ((dview->upper - dview->lower)
                * (widget->style->font->ascent + widget->style->font->descent
                   + 2 * TEXT_BORDER));
}

static gint
gncal_day_view_expose (GtkWidget *widget, GdkEventExpose *event)
{
    GncalDayView *dview;
    int x1, y1, width, height;
    int division_x;
    int row_height;
    int i;

    g_return_val_if_fail (widget != NULL, FALSE);
    g_return_val_if_fail (GNCAL_IS_DAY_VIEW (widget), FALSE);
    g_return_val_if_fail (event != NULL, FALSE);

    if (!GTK_WIDGET_DRAWABLE (widget))
        return FALSE;

    dview = GNCAL_DAY_VIEW (widget);

    x1 = widget->style->klass->xthickness;
    y1 = widget->style->klass->ythickness;
    width = widget->allocation.width - 2 * x1;
    height = widget->allocation.width - 2 * y1;

    /* Clear and paint frame shadow */

    gdk_window_clear_area (widget->window, event->area.x, event->area.y, event->area.width, event->area.height);

    gtk_draw_shadow (widget->style, widget->window,
             GTK_STATE_NORMAL, GTK_SHADOW_IN,
             0, 0,
             widget->allocation.width,
             widget->allocation.height);

    /* Divisions */

    division_x = x1 + 2 * TEXT_BORDER + calc_labels_width (dview);

    gdk_draw_line (widget->window,
               widget->style->black_gc,
               division_x, y1,
               division_x, y1 + height - 1);

    row_height = height / (dview->upper - dview->lower);

    for (i = 0; i < (dview->upper - dview->lower - 1); i++)
        gdk_draw_line (widget->window,
                   widget->style->black_gc,
                   x1,
                   y1 + (i + 1) * row_height,
                   x1 + width - 1,
                   y1 + (i + 1) * row_height);

    return FALSE;
}

void
gncal_day_view_set_bounds (GncalDayView *dview, int lower, int upper)
{
    g_return_if_fail (dview != NULL);
    g_return_if_fail (GNCAL_IS_DAY_VIEW (dview));

    lower = CLAMP (lower, 0, 23);
    upper = CLAMP (upper, lower + 1, 24);

    if ((lower != dview->lower) || (upper != dview->upper)) {
        dview->lower = lower;
        dview->upper = upper;

        gtk_widget_queue_resize (GTK_WIDGET (dview));
    }
}

void
gncal_day_view_set_format (GncalDayView *dview, int use_am_pm)
{
    g_return_if_fail (dview != NULL);
    g_return_if_fail (GNCAL_IS_DAY_VIEW (dview));

    use_am_pm = use_am_pm ? TRUE : FALSE;

    if (use_am_pm != dview->use_am_pm) {
        dview->use_am_pm = use_am_pm;

        gtk_widget_queue_resize (GTK_WIDGET (dview));
    }
}