aboutsummaryrefslogblamecommitdiffstats
path: root/calendar/gncal-day-view.c
blob: 85d61292f1eeb6778fc0ffe66272b9ccfdc36a11 (plain) (tree)
1
2
3
4
5
6
7
8
9



                                                  

                                               

   
                  

                           
                       

                      

                       






                                                                   
                                                                    




                                                                         

                                                                   





































                                                                                         

                                                       


                                                                 
                                                                       









                                                      
                         

                                                  

 

                                          


                            






                                                      
                          
                                                            
        


                                                                      





























                                                                                         
                                          





















                                                                           

           
                                                                        

                            
 
                                                      
 


                                                          


                                
 
                                               

































                                                                                                              
                                                                                           





                                                                            
                             






                                                      

                                  




                                                                                          
                                                                                   
 






                                                                                                






                                                                


                                












                                                                 
                                                    


                                          


                                                                      

                                                       
                                                              



                                                    







                                                                     
 


























                                                                                          
 
                           
 





                                                
 












                                                                                                        
                                                      

                                                      




                     
                                                                       
 


                      

                                                     
                                                
 

                                        
 
                                        
                                                     
                                        
 
                          
                                                            


                                                                           
                                                                    

                                                   


    
                                                                           



                                                     


                                                                 
 
                                                       

         












                                                                          
/* Day view widget for gncal
 *
 * Copyright (C) 1998 The Free Software Foundation
 *
 * Authors: Federico Mena   <quartic@gimp.org>
 *          Miguel de Icaza <miguel@kernel.org>
 */

#include <gnome.h>
#include "gncal-day-view.h"
#include "timeutil.h"
#include "view-utils.h"
#include "main.h"
#include "eventedit.h"
#include "popup-menu.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_destroy      (GtkObject         *object);
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 gint gncal_day_view_button_press (GtkWidget         *widget,
                     GdkEventButton    *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 ());

    object_class->destroy = gncal_day_view_destroy;

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

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

    dview->calendar = NULL;

    dview->lower = 0;
    dview->upper = 0;

    dview->shadow_type = GTK_SHADOW_ETCHED_IN;
}

static void
gncal_day_view_destroy (GtkObject *object)
{
    GncalDayView *dview;

    g_return_if_fail (object != NULL);
    g_return_if_fail (GNCAL_IS_DAY_VIEW (object));

    dview = GNCAL_DAY_VIEW (object);

    if (dview->day_str)
        g_free (dview->day_str);
    if (dview->events)
        calendar_destroy_event_list (dview->events);
    
    if (GTK_OBJECT_CLASS (parent_class)->destroy)
        (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}

static int
new_appointment (GtkWidget *widget, gpointer data)
{
    GncalDayView *dayview = GNCAL_DAY_VIEW (data);
    iCalObject *ico;
    GtkWidget *ee;
    struct tm tm;
    
    ico = ical_new ("", user_name, "");
    ico->new = 1;

    tm = *localtime (&dayview->lower);
    tm.tm_hour = day_begin;
    ico->dtstart = mktime (&tm);
    tm.tm_hour++;
    ico->dtend   = mktime (&tm);
    ee = event_editor_new (dayview->calendar, ico);
    gtk_widget_show (ee);
    return 1;
}

static void
context_menu (GncalDayView *dayview, GdkEventButton *event)
{
    static struct menu_item main_items[] = {
        { N_("New appointment..."), (GtkSignalFunc) new_appointment, NULL, TRUE }
    };

    main_items [0].data = dayview;
    popup_menu (main_items, 1, event);
}

static void
switch_to_day (GncalDayView *dayview)
{
}

static gint
gncal_day_view_button_press (GtkWidget *widget, GdkEventButton *event)
{
    GncalDayView *dayview;

    dayview = GNCAL_DAY_VIEW (widget);

    if (event->button == 3)
        context_menu (dayview, event);

    if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
        gnome_calendar_dayjump (dayview->calendar, dayview->lower);

    return TRUE;
}

GtkWidget *
gncal_day_view_new (GnomeCalendar *calendar, time_t lower, time_t upper)
{
    GncalDayView *dview;

    g_return_val_if_fail (calendar != NULL, NULL);

    dview = gtk_type_new (gncal_day_view_get_type ());

    dview->calendar = calendar;
    dview->lower    = lower;
    dview->upper    = upper;
    dview->events   = 0;

    gncal_day_view_update (dview, NULL, 0);

    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);

    gdk_window_set_background (widget->window, &widget->style->bg[GTK_STATE_PRELIGHT]);
}

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

    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);

    /* border and min width */

    str_width = gdk_string_width (widget->style->font, dview->day_str);

    width = MAX (MIN_INFO_WIDTH, str_width);

    requisition->width = 2 * (widget->style->klass->xthickness + TEXT_BORDER) + width;
    requisition->height = 2 * (widget->style->klass->ythickness + TEXT_BORDER);

    /* division line */

    requisition->height += 2 * TEXT_BORDER + widget->style->klass->ythickness;

    /* title and at least one line of text */

    requisition->height += 2 * (widget->style->font->ascent + widget->style->font->descent);
}

static gint
gncal_day_view_expose (GtkWidget *widget, GdkEventExpose *event)
{
    GncalDayView *dview;
    int x1, y1, width, height;
    GdkRectangle rect, dest;
    GdkFont *font;
    int str_width;

    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.height - 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, dview->shadow_type,
             0, 0,
             widget->allocation.width,
             widget->allocation.height);

    /* Clear and paint title */

    font = widget->style->font;

    rect.x = x1;
    rect.y = y1;
    rect.width = width;
    rect.height = 2 * TEXT_BORDER + font->ascent + font->descent;

    if (gdk_rectangle_intersect (&rect, &event->area, &dest)) {
        gdk_draw_rectangle (widget->window,
                    widget->style->bg_gc[GTK_STATE_NORMAL],
                    TRUE,
                    dest.x, dest.y,
                    dest.width, dest.height);

        dest = rect;

        dest.x += TEXT_BORDER;
        dest.y += TEXT_BORDER;
        dest.width -= 2 * TEXT_BORDER;
        dest.height -= 2 * TEXT_BORDER;

        gdk_gc_set_clip_rectangle (widget->style->fg_gc[GTK_STATE_NORMAL], &dest);

        str_width = gdk_string_width (font, dview->day_str);
        
        gdk_draw_string (widget->window,
                 font,
                 widget->style->fg_gc[GTK_STATE_NORMAL],
                 dest.x + (dest.width - str_width) / 2,
                 dest.y + font->ascent,
                 dview->day_str);

        gdk_gc_set_clip_rectangle (widget->style->fg_gc[GTK_STATE_NORMAL], NULL);
    }

    /* Division line */

    gtk_draw_hline (widget->style,
            widget->window,
            GTK_STATE_NORMAL,
            rect.x,
            rect.x + rect.width - 1,
            rect.y + rect.height);

    /* Text */

    rect.x = x1 + TEXT_BORDER;
    rect.y = y1 + 3 * TEXT_BORDER + font->ascent + font->descent + widget->style->klass->ythickness;
    rect.width = width - 2 * TEXT_BORDER;
    rect.height = height - (rect.y - y1) - TEXT_BORDER;

    if (gdk_rectangle_intersect (&rect, &event->area, &dest))
        view_utils_draw_events (widget,
                    widget->window,
                    widget->style->fg_gc[GTK_STATE_NORMAL],
                    &rect,
                    VIEW_UTILS_DRAW_END | VIEW_UTILS_DRAW_SPLIT,
                    dview->events,
                    dview->lower,
                    dview->upper);

    return FALSE;
}

void
gncal_day_view_update (GncalDayView *dview, iCalObject *ico, int flags)
{
    struct tm tm;
    char buf[256];

    g_return_if_fail (dview != NULL);
    g_return_if_fail (GNCAL_IS_DAY_VIEW (dview));
    g_return_if_fail (dview->calendar->cal);

    if (dview->day_str)
        g_free (dview->day_str);

    tm = *localtime (&dview->lower);
    strftime (buf, sizeof (buf)-1, "%A %d", &tm);
    dview->day_str = g_strdup (buf);

    if (dview->events)
        calendar_destroy_event_list (dview->events);

    dview->events = calendar_get_events_in_range (dview->calendar->cal,
                              dview->lower,
                              dview->upper);

    gtk_widget_draw (GTK_WIDGET (dview), NULL);
}

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

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

        gncal_day_view_update (dview, NULL, 0);
    }
}

void
gncal_day_view_set_shadow (GncalDayView *dview, GtkShadowType shadow_type)
{
    g_return_if_fail (dview != NULL);
    g_return_if_fail (GNCAL_IS_DAY_VIEW (dview));

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

        gtk_widget_draw (GTK_WIDGET (dview), NULL);
    }
}