aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui')
-rw-r--r--calendar/gui/calendar.c1
-rw-r--r--calendar/gui/calendar.h1
-rw-r--r--calendar/gui/eventedit.c9
-rw-r--r--calendar/gui/eventedit.h2
-rw-r--r--calendar/gui/gncal-day-view.c11
-rw-r--r--calendar/gui/gncal-full-day.c902
-rw-r--r--calendar/gui/gncal-full-day.h6
-rw-r--r--calendar/gui/gncal-week-view.c2
-rw-r--r--calendar/gui/gnome-cal.c20
-rw-r--r--calendar/gui/gnome-cal.h1
-rw-r--r--calendar/gui/main.c5
-rw-r--r--calendar/gui/test.vcf9
12 files changed, 881 insertions, 88 deletions
diff --git a/calendar/gui/calendar.c b/calendar/gui/calendar.c
index 581a75ee2f..c06414a571 100644
--- a/calendar/gui/calendar.c
+++ b/calendar/gui/calendar.c
@@ -15,6 +15,7 @@
#include <config.h>
#include "calendar.h"
+#include "timeutil.h"
#include "versit/vcc.h"
Calendar *
diff --git a/calendar/gui/calendar.h b/calendar/gui/calendar.h
index f990caabd6..8f4e4c1497 100644
--- a/calendar/gui/calendar.h
+++ b/calendar/gui/calendar.h
@@ -18,6 +18,7 @@ typedef struct {
} Calendar;
Calendar *calendar_new (char *title);
+void calendar_load (Calendar *cal, char *fname);
void calendar_add_object (Calendar *cal, iCalObject *obj);
void calendar_remove_object (Calendar *cal, iCalObject *obj);
void calendar_destroy (Calendar *cal);
diff --git a/calendar/gui/eventedit.c b/calendar/gui/eventedit.c
index 1a63bd60f5..7846eab86e 100644
--- a/calendar/gui/eventedit.c
+++ b/calendar/gui/eventedit.c
@@ -6,10 +6,11 @@
*/
#include <gnome.h>
+#include <string.h>
#include "calendar.h"
-#include "gnome-cal.h"
#include "eventedit.h"
#include "main.h"
+#include "timeutil.h"
static void event_editor_init (EventEditor *ee);
GtkWindow *parent_class;
@@ -202,10 +203,9 @@ alarm_toggle (GtkToggleButton *toggle, CalendarAlarm *alarm)
#define FX GTK_FILL | GTK_EXPAND
#define XCOL 6
-static GtkWidget *
+static void
ee_create_ae (GtkTable *table, char *str, CalendarAlarm *alarm, enum AlarmType type, int y)
{
- GtkWidget *timesel;
char buffer [40];
alarm->w_enabled = gtk_check_button_new_with_label (str);
@@ -253,7 +253,7 @@ ee_create_ae (GtkTable *table, char *str, CalendarAlarm *alarm, enum AlarmType t
static GtkWidget *
ee_alarm_widgets (EventEditor *ee)
{
- GtkWidget *table, *aalarm, *dalarm, *palarm, *malarm, *mailto, *mailte, *l;
+ GtkWidget *table, *mailto, *mailte, *l;
l = gtk_frame_new (_("Alarms"));
@@ -304,6 +304,7 @@ ee_classification_widgets (EventEditor *ee)
* Retrieves the information from the CalendarAlarm widgets and stores them
* on the CalendarAlarm generic values
*/
+void
ee_store_alarm (CalendarAlarm *alarm, enum AlarmType type)
{
GtkWidget *item;
diff --git a/calendar/gui/eventedit.h b/calendar/gui/eventedit.h
index e726270877..2396d302f6 100644
--- a/calendar/gui/eventedit.h
+++ b/calendar/gui/eventedit.h
@@ -8,6 +8,8 @@
#ifndef EVENT_EDITOR_H
#define EVENT_EDITOR_H
+#include "gnome-cal.h"
+
BEGIN_GNOME_DECLS
#define EVENT_EDITOR(obj) GTK_CHECK_CAST(obj, event_editor_get_type(), EventEditor)
diff --git a/calendar/gui/gncal-day-view.c b/calendar/gui/gncal-day-view.c
index 209b6be40a..951b0eb5ae 100644
--- a/calendar/gui/gncal-day-view.c
+++ b/calendar/gui/gncal-day-view.c
@@ -156,6 +156,7 @@ 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));
@@ -165,7 +166,11 @@ gncal_day_view_size_request (GtkWidget *widget, GtkRequisition *requisition)
/* border and min width */
- requisition->width = 2 * (widget->style->klass->xthickness + TEXT_BORDER) + MIN_INFO_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 */
@@ -297,8 +302,6 @@ gncal_day_view_update (GncalDayView *dview)
strftime (buf, sizeof (buf)-1, "%A %d", &tm);
dview->day_str = g_strdup (buf);
- gtk_widget_draw (GTK_WIDGET (dview), NULL);
-
if (dview->events)
g_list_free (dview->events);
@@ -306,6 +309,8 @@ gncal_day_view_update (GncalDayView *dview)
dview->lower,
dview->upper,
calendar_compare_by_dtstart);
+
+ gtk_widget_draw (GTK_WIDGET (dview), NULL);
}
void
diff --git a/calendar/gui/gncal-full-day.c b/calendar/gui/gncal-full-day.c
index ba646d5a2e..b6a61a3a9d 100644
--- a/calendar/gui/gncal-full-day.c
+++ b/calendar/gui/gncal-full-day.c
@@ -6,26 +6,453 @@
*/
#include <gtk/gtkdrawingarea.h>
+#include <gtk/gtktext.h>
#include "gncal-full-day.h"
+#include "view-utils.h"
#define TEXT_BORDER 2
+#define HANDLE_SIZE 3
#define MIN_WIDTH 200
+#define XOR_RECT_WIDTH 2
+
+
+typedef struct {
+ iCalObject *ico;
+ GtkWidget *widget;
+ GdkWindow *window;
+ int lower_row; /* zero is first displayed row */
+ int rows_used;
+ int x; /* coords of child's window */
+ int y;
+ int width;
+ int height;
+} Child;
+
+struct layout_row {
+ int intersections;
+ int *slots;
+};
+
+struct drag_info {
+ Child *child;
+ enum {
+ DRAG_MOVE,
+ DRAG_SIZE
+ } drag_mode;
+ int new_y;
+ int new_height;
+};
+
+
+static void gncal_full_day_class_init (GncalFullDayClass *class);
+static void gncal_full_day_init (GncalFullDay *fullday);
+static void gncal_full_day_destroy (GtkObject *object);
+static void gncal_full_day_map (GtkWidget *widget);
+static void gncal_full_day_unmap (GtkWidget *widget);
+static void gncal_full_day_realize (GtkWidget *widget);
+static void gncal_full_day_unrealize (GtkWidget *widget);
+static void gncal_full_day_draw (GtkWidget *widget,
+ GdkRectangle *area);
+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_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gncal_full_day_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gncal_full_day_motion (GtkWidget *widget,
+ GdkEventMotion *event);
+static gint gncal_full_day_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gncal_full_day_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
-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;
-static GtkContainerClass *parent_class;
+static void
+get_tm_range (GncalFullDay *fullday,
+ time_t time_lower, time_t time_upper,
+ struct tm *lower, struct tm *upper,
+ int *lower_row, int *rows_used)
+{
+ struct tm tm_lower, tm_upper;
+ int lmin, umin;
+ int lrow;
+
+ /* Lower */
+
+ tm_lower = *localtime (&time_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 (&time_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;
+
+ if (umin == 0) /* midnight of next day? */
+ umin = 60 * 24;
+
+ lrow = lmin / fullday->interval;
+
+ if (lower_row)
+ *lower_row = lrow;
+
+ if (rows_used)
+ *rows_used = (umin - lmin) / fullday->interval;
+}
+
+static void
+child_map (GncalFullDay *fullday, Child *child)
+{
+ gdk_window_show (child->window);
+
+ if (GTK_WIDGET_VISIBLE (child->widget) && !GTK_WIDGET_MAPPED (child->widget))
+ gtk_widget_map (child->widget);
+}
+
+static void
+child_unmap (GncalFullDay *fullday, Child *child)
+{
+ gdk_window_hide (child->window);
+
+ if (GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_MAPPED (child->widget))
+ gtk_widget_unmap (child->widget);
+}
+
+static void
+child_move_text (Child *child)
+{
+ GtkAllocation allocation;
+
+ allocation.x = 0;
+ allocation.y = HANDLE_SIZE;
+ allocation.width = child->width;
+ allocation.height = child->height - 2 * HANDLE_SIZE;
+
+ gtk_widget_size_request (child->widget, &child->widget->requisition); /* FIXME: is this needed? */
+ gtk_widget_size_allocate (child->widget, &allocation);
+}
+
+static void
+child_realize (GncalFullDay *fullday, Child *child)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (fullday);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = child->x;
+ attributes.y = child->y;
+ attributes.width = child->width;
+ attributes.height = child->height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.cursor = fullday->up_down_cursor;
+ attributes.event_mask = (GDK_EXPOSURE_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_BUTTON_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR;
+
+ child->window = gdk_window_new (widget->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (child->window, widget);
+
+ gtk_style_set_background (widget->style, child->window, GTK_STATE_NORMAL);
+
+ gtk_widget_set_parent_window (child->widget, child->window);
+
+ child_move_text (child);
+}
+
+static void
+child_unrealize (GncalFullDay *fullday, Child *child)
+{
+ gdk_window_set_user_data (child->window, NULL);
+ gdk_window_destroy (child->window);
+ child->window = NULL;
+}
+
+static void
+child_draw (GncalFullDay *fullday, Child *child, GdkRectangle *area, int draw_child)
+{
+ GdkRectangle arect, rect, dest;
+ gint w, h;
+
+ gdk_window_get_size (child->window, &w, &h);
+
+ if (!area) {
+ arect.x = 0;
+ arect.y = 0;
+
+ arect.width = w;
+ arect.height = h;
+
+ area = &arect;
+ }
+
+ /* Top handle */
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = w;
+ rect.height = HANDLE_SIZE;
+
+ if (gdk_rectangle_intersect (&rect, area, &dest))
+ view_utils_draw_textured_frame (GTK_WIDGET (fullday), child->window, &rect, GTK_SHADOW_OUT);
+
+ /* Bottom handle */
+
+ rect.y = h - HANDLE_SIZE;
+
+ if (gdk_rectangle_intersect (&rect, area, &dest))
+ view_utils_draw_textured_frame (GTK_WIDGET (fullday), child->window, &rect, GTK_SHADOW_OUT);
+
+ if (draw_child) {
+ area->y -= HANDLE_SIZE;
+ gtk_widget_draw (child->widget, area);
+ }
+}
+
+static void
+child_set_beam_cursor (GtkWidget *widget, gpointer data)
+{
+ GncalFullDay *fullday = data;
+
+ gdk_window_set_cursor (widget->window, fullday->beam_cursor);
+}
+
+static Child *
+child_new (GncalFullDay *fullday, iCalObject *ico)
+{
+ Child *child;
+ struct tm start, end;
+ int lower_row, rows_used;
+ int f_lower_row;
+
+ child = g_new (Child, 1);
+
+ child->ico = ico;
+ child->widget = gtk_text_new (NULL, NULL);
+ child->window = NULL;
+ child->x = 0;
+ child->y = 0;
+ child->width = 0;
+ child->height = 0;
+
+ /* Calc display range for event */
+
+ get_tm_range (fullday, child->ico->dtstart, child->ico->dtend, &start, &end, &lower_row, &rows_used);
+ get_tm_range (fullday, fullday->lower, fullday->upper, NULL, NULL, &f_lower_row, NULL);
+
+ child->lower_row = lower_row - f_lower_row;
+ child->rows_used = rows_used;
+
+ /* Finish setup */
+
+ gtk_signal_connect (GTK_OBJECT (child->widget), "realize",
+ (GtkSignalFunc) child_set_beam_cursor,
+ fullday);
+
+ gtk_text_set_editable (GTK_TEXT (child->widget), TRUE);
+ gtk_text_set_word_wrap (GTK_TEXT (child->widget), TRUE);
+ gtk_widget_set_parent (child->widget, GTK_WIDGET (fullday));
+ gtk_widget_show (child->widget);
+
+ return child;
+}
+
+static void
+child_destroy (GncalFullDay *fullday, Child *child)
+{
+ /* FIXME */
+}
+
+static void
+child_set_pos (GncalFullDay *fullday, Child *child, int x, int y, int width, int height)
+{
+ child->x = x;
+ child->y = y;
+ child->width = width;
+ child->height = height;
+
+ if (!GTK_WIDGET_REALIZED (fullday))
+ return;
+
+ child_move_text (child);
+ gdk_window_move_resize (child->window, x, y, width, height);
+}
+
+static struct layout_row *
+layout_get_rows (GncalFullDay *fullday)
+{
+ struct layout_row *rows;
+ int max_i;
+ int f_rows;
+ GList *children;
+ Child *child;
+ int i, n;
+
+ get_tm_range (fullday, fullday->lower, fullday->upper, NULL, NULL, NULL, &f_rows);
+
+ rows = g_new0 (struct layout_row, f_rows);
+ max_i = 0;
+
+ for (children = fullday->children; children; children = children->next) {
+ child = children->data;
+
+ for (i = 0; i < child->rows_used; i++) {
+ n = child->lower_row + i;
+
+ rows[n].intersections++;
+
+ if (rows[n].intersections > max_i)
+ max_i = rows[n].intersections;
+ }
+ }
+
+ for (i = 0; i < f_rows; i++)
+ rows[i].slots = g_new0 (int, max_i);
+
+ return rows;
+}
+
+static void
+layout_get_child_intersections (Child *child, struct layout_row *rows, int *min, int *max)
+{
+ int i, n;
+ int imin, imax;
+
+ imax = 0;
+
+ for (i = 0; i < child->rows_used; i++) {
+ n = child->lower_row + i;
+
+ if (rows[n].intersections > imax)
+ imax = rows[n].intersections;
+ }
+
+ imin = imax;
+
+ for (i = 0; i < child->rows_used; i++) {
+ n = child->lower_row + i;
+
+ if (rows[n].intersections < imin)
+ imin = rows[n].intersections;
+ }
+
+ if (min)
+ *min = imin;
+
+ if (max)
+ *max = imax;
+}
+
+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_range (fullday, fullday->lower, fullday->upper, &cur, &upper, NULL, NULL);
+
+ max_w = 0;
+
+ tim = mktime (&cur);
+ time_upper = mktime (&upper);
+
+ while (tim < time_upper) {
+ strftime (buf, 256, "%X", &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
+layout_child (GncalFullDay *fullday, Child *child, struct layout_row *rows)
+{
+ int c_x, c_y, c_width, c_height;
+ GtkWidget *widget;
+ int labels_width;
+ int height, f_rows;
+ int row_height;
+
+ /* Calculate child position */
+
+ widget = GTK_WIDGET (fullday);
+
+ labels_width = calc_labels_width (fullday); /* FIXME: this is expensive to do for each child */
+
+ get_tm_range (fullday, fullday->lower, fullday->upper, NULL, NULL, NULL, &f_rows);
+
+ height = widget->allocation.height - 2 * widget->style->klass->ythickness;
+ row_height = height / f_rows;
+
+ c_x = 2 * (widget->style->klass->xthickness + TEXT_BORDER) + labels_width;
+ c_y = widget->style->klass->ythickness;
+
+ /* FIXME: for now, the children overlap. Make it layout them nicely. */
+
+ c_width = widget->allocation.width - (widget->style->klass->xthickness + c_x);
+
+ c_y += child->lower_row * row_height;
+ c_height = child->rows_used * row_height;
+
+ /* Position child */
+
+ child_set_pos (fullday, child, c_x, c_y, c_width, c_height);
+}
+
+static void
+layout_children (GncalFullDay *fullday)
+{
+ struct layout_row *rows;
+ GList *children;
+
+ rows = layout_get_rows (fullday);
+
+ for (children = fullday->children; children; children = children->next)
+ layout_child (fullday, children->data, rows);
+
+ g_free (rows);
+}
guint
gncal_full_day_get_type (void)
@@ -52,18 +479,31 @@ gncal_full_day_get_type (void)
static void
gncal_full_day_class_init (GncalFullDayClass *class)
{
+ GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkContainerClass *container_class;
+ object_class = (GtkObjectClass *) class;
widget_class = (GtkWidgetClass *) class;
container_class = (GtkContainerClass *) class;
parent_class = gtk_type_class (gtk_container_get_type ());
+ object_class->destroy = gncal_full_day_destroy;
+
+ widget_class->map = gncal_full_day_map;
+ widget_class->unmap = gncal_full_day_unmap;
widget_class->realize = gncal_full_day_realize;
+ widget_class->unrealize = gncal_full_day_unrealize;
+ widget_class->draw = gncal_full_day_draw;
widget_class->size_request = gncal_full_day_size_request;
widget_class->size_allocate = gncal_full_day_size_allocate;
+ widget_class->button_press_event = gncal_full_day_button_press;
+ widget_class->button_release_event = gncal_full_day_button_release;
+ widget_class->motion_notify_event = gncal_full_day_motion;
widget_class->expose_event = gncal_full_day_expose;
+
+ container_class->foreach = gncal_full_day_foreach;
}
static void
@@ -76,6 +516,29 @@ gncal_full_day_init (GncalFullDay *fullday)
fullday->lower = 0;
fullday->upper = 0;
fullday->interval = 30; /* 30 minutes by default */
+
+ fullday->children = NULL;
+ fullday->drag_info = g_new (struct drag_info, 1);
+
+ fullday->up_down_cursor = NULL;
+ fullday->beam_cursor = NULL;
+}
+
+static void
+gncal_full_day_destroy (GtkObject *object)
+{
+ GncalFullDay *fullday;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNCAL_IS_FULL_DAY (object));
+
+ fullday = GNCAL_FULL_DAY (object);
+
+ g_list_free (fullday->children);
+ g_free (fullday->drag_info);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
GtkWidget *
@@ -95,16 +558,58 @@ gncal_full_day_new (GnomeCalendar *calendar, time_t lower, time_t upper)
}
static void
+gncal_full_day_map (GtkWidget *widget)
+{
+ GncalFullDay *fullday;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GNCAL_IS_FULL_DAY (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+ fullday = GNCAL_FULL_DAY (widget);
+
+ gdk_window_show (widget->window);
+
+ for (children = fullday->children; children; children = children->next)
+ child_map (fullday, children->data);
+}
+
+static void
+gncal_full_day_unmap (GtkWidget *widget)
+{
+ GncalFullDay *fullday;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GNCAL_IS_FULL_DAY (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+ fullday = GNCAL_FULL_DAY (widget);
+
+ gdk_window_hide (widget->window);
+
+ for (children = fullday->children; children; children = children->next)
+ child_unmap (fullday, children->data);
+}
+
+static void
gncal_full_day_realize (GtkWidget *widget)
{
+ GncalFullDay *fullday;
GdkWindowAttr attributes;
gint attributes_mask;
+ GList *children;
g_return_if_fail (widget != NULL);
g_return_if_fail (GNCAL_IS_FULL_DAY (widget));
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ fullday = GNCAL_FULL_DAY (widget);
+
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.y;
@@ -123,75 +628,53 @@ gncal_full_day_realize (GtkWidget *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);
- }
+ fullday->up_down_cursor = gdk_cursor_new (GDK_DOUBLE_ARROW);
+ fullday->beam_cursor = gdk_cursor_new (GDK_XTERM);
- /* Upper */
+ for (children = fullday->children; children; children = children->next)
+ child_realize (fullday, children->data);
+}
- tm_upper = *localtime (&fullday->upper);
+static void
+gncal_full_day_unrealize (GtkWidget *widget)
+{
+ GncalFullDay *fullday;
+ GList *children;
- 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);
- }
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GNCAL_IS_FULL_DAY (widget));
- if (lower)
- *lower = tm_lower;
+ fullday = GNCAL_FULL_DAY (widget);
- if (upper)
- *upper = tm_upper;
+ for (children = fullday->children; children; children = children->next)
+ child_unrealize (fullday, children->data);
- lmin = 60 * tm_lower.tm_hour + tm_lower.tm_min;
- umin = 60 * tm_upper.tm_hour + tm_upper.tm_min;
+ gdk_cursor_destroy (fullday->up_down_cursor);
+ fullday->up_down_cursor = NULL;
- if (umin == 0) /* midnight of next day? */
- umin = 60 * 24;
+ gdk_cursor_destroy (fullday->beam_cursor);
+ fullday->beam_cursor = NULL;
- return (umin - lmin) / fullday->interval; /* number of rows in view */
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
}
-static int
-calc_labels_width (GncalFullDay *fullday)
+static void
+gncal_full_day_draw (GtkWidget *widget, GdkRectangle *area)
{
- 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, "%X", &cur);
+ GncalFullDay *fullday;
- width = gdk_string_width (GTK_WIDGET (fullday)->style->font, buf);
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GNCAL_IS_FULL_DAY (widget));
+ g_return_if_fail (area != NULL);
- if (width > max_w)
- max_w = width;
+ if (!GTK_WIDGET_DRAWABLE (widget))
+ return;
- cur.tm_min += fullday->interval;
- tim = mktime (&cur);
- }
+ fullday = GNCAL_FULL_DAY (widget);
- return max_w;
+ /* FIXME */
}
static void
@@ -216,7 +699,7 @@ gncal_full_day_size_request (GtkWidget *widget, GtkRequisition *requisition)
/* Rows */
- rows = get_tm_bounds (fullday, NULL, NULL);
+ get_tm_range (fullday, fullday->lower, fullday->upper, NULL, NULL, NULL, &rows);
requisition->height += (rows * (2 * TEXT_BORDER + widget->style->font->ascent + widget->style->font->descent)
+ (rows - 1)); /* division lines */
@@ -225,18 +708,220 @@ gncal_full_day_size_request (GtkWidget *widget, GtkRequisition *requisition)
static void
gncal_full_day_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
{
+ GncalFullDay *fullday;
+
g_return_if_fail (widget != NULL);
g_return_if_fail (GNCAL_IS_FULL_DAY (widget));
g_return_if_fail (allocation != NULL);
widget->allocation = *allocation;
+ fullday = GNCAL_FULL_DAY (widget);
+
if (GTK_WIDGET_REALIZED (widget))
gdk_window_move_resize (widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
- /* FIXME: adjust children */
+ layout_children (fullday);
+}
+
+static Child *
+find_child_by_window (GncalFullDay *fullday, GdkWindow *window)
+{
+ GList *children;
+ Child *child;
+
+ for (children = fullday->children; children; children = children->next) {
+ child = children->data;
+
+ if (child->window == window)
+ return child;
+ }
+
+ return NULL;
+}
+
+static void
+draw_xor_rect (GncalFullDay *fullday)
+{
+ GtkWidget *widget;
+ struct drag_info *di;
+ int i;
+
+ widget = GTK_WIDGET (fullday);
+
+ gdk_gc_set_function (widget->style->white_gc, GDK_INVERT);
+ gdk_gc_set_subwindow (widget->style->white_gc, GDK_INCLUDE_INFERIORS);
+
+ di = fullday->drag_info;
+
+ for (i = 0; i < XOR_RECT_WIDTH; i++)
+ gdk_draw_rectangle (widget->window,
+ widget->style->white_gc,
+ FALSE,
+ di->child->x + i,
+ di->new_y + i,
+ di->child->width - 2 * i - 1,
+ di->new_height - 2 * i - 1);
+
+ gdk_gc_set_function (widget->style->white_gc, GDK_COPY);
+ gdk_gc_set_subwindow (widget->style->white_gc, GDK_CLIP_BY_CHILDREN);
+}
+
+static gint
+gncal_full_day_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ GncalFullDay *fullday;
+ Child *child;
+ struct drag_info *di;
+ gint y;
+
+ 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);
+
+ fullday = GNCAL_FULL_DAY (widget);
+
+ if (event->window == widget->window)
+ return FALSE; /* FIXME: do range selection thing */
+ else {
+ child = find_child_by_window (fullday, event->window);
+
+ if (!child)
+ return FALSE;
+
+ di = fullday->drag_info;
+
+ di->child = child;
+
+ gtk_widget_get_pointer (widget, NULL, &y);
+
+ if (event->y < HANDLE_SIZE)
+ di->drag_mode = DRAG_MOVE;
+ else
+ di->drag_mode = DRAG_SIZE;
+
+ di->new_y = child->y;
+ di->new_height = child->height;
+
+ gdk_pointer_grab (child->window, FALSE,
+ (GDK_BUTTON_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK
+ | GDK_BUTTON_RELEASE_MASK),
+ NULL,
+ NULL,
+ event->time);
+
+ draw_xor_rect (fullday);
+ }
+
+ return FALSE;
+}
+
+static void
+recompute_motion (GncalFullDay *fullday, int y)
+{
+ GtkWidget *widget;
+ struct drag_info *di;
+ int rows, row_height;
+ int ythickness;
+
+ widget = GTK_WIDGET (fullday);
+
+ get_tm_range (fullday, fullday->lower, fullday->upper, NULL, NULL, NULL, &rows);
+
+ ythickness = widget->style->klass->ythickness;
+
+ row_height = (widget->allocation.height - 2 * ythickness) / rows;
+
+ y -= ythickness;
+ y = (y + row_height / 2) / row_height; /* round to nearest bound */
+ y = y * row_height + ythickness;
+
+ di = fullday->drag_info;
+
+ switch (di->drag_mode) {
+ case DRAG_MOVE:
+ if (y < ythickness)
+ y = ythickness;
+ else if (y >= (ythickness + rows * row_height - di->new_height))
+ y = ythickness + rows * row_height - di->new_height;
+
+ di->new_y = y;
+
+ break;
+
+ case DRAG_SIZE:
+ if (y <= di->child->y)
+ y = di->child->y + row_height;
+ else if (y >= (ythickness + rows * row_height))
+ y = ythickness + rows * row_height;
+
+ di->new_height = y - di->new_y;
+
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static gint
+gncal_full_day_button_release (GtkWidget *widget, GdkEventButton *event)
+{
+ GncalFullDay *fullday;
+ struct drag_info *di;
+ gint y;
+
+ 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);
+
+ fullday = GNCAL_FULL_DAY (widget);
+
+ di = fullday->drag_info;
+
+ if (!di->child || (event->window != di->child->window))
+ return FALSE;
+
+ gtk_widget_get_pointer (widget, NULL, &y);
+
+ draw_xor_rect (fullday);
+ recompute_motion (fullday, y);
+ gdk_pointer_ungrab (event->time);
+
+ /* FIXME: update child, notify, etc. */
+
+ di->child = NULL;
+
+ return FALSE;
+}
+
+static gint
+gncal_full_day_motion (GtkWidget *widget, GdkEventMotion *event)
+{
+ GncalFullDay *fullday;
+ struct drag_info *di;
+ gint y;
+
+ 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);
+
+ fullday = GNCAL_FULL_DAY (widget);
+ di = fullday->drag_info;
+
+ if (!di->child || (event->window != di->child->window))
+ return FALSE;
+
+ gtk_widget_get_pointer (widget, NULL, &y);
+
+ draw_xor_rect (fullday);
+ recompute_motion (fullday, y);
+ draw_xor_rect (fullday);
+
+ return FALSE;
}
static void
@@ -296,11 +981,11 @@ paint_back (GncalFullDay *fullday, GdkRectangle *area)
/* Horizontal divisions */
- rows = get_tm_bounds (fullday, &tm, NULL);
+ get_tm_range (fullday, fullday->lower, fullday->upper, &tm, NULL, NULL, &rows);
- row_height = height / rows; /* includes division line */
+ row_height = height / rows; /* includes division line at bottom of row */
- y = row_height;
+ y = y1 + row_height - 1;
for (i = 1; i < rows; i++) {
gdk_draw_line (widget->window,
@@ -315,6 +1000,8 @@ paint_back (GncalFullDay *fullday, GdkRectangle *area)
y = y1 + ((row_height - 1) - (widget->style->font->ascent + widget->style->font->descent)) / 2;
+ rect.height = row_height - 1;
+
for (i = 0; i < rows; i++) {
mktime (&tm);
@@ -340,6 +1027,8 @@ static gint
gncal_full_day_expose (GtkWidget *widget, GdkEventExpose *event)
{
GncalFullDay *fullday;
+ GList *children;
+ Child *child;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GNCAL_IS_FULL_DAY (widget), FALSE);
@@ -352,19 +1041,90 @@ gncal_full_day_expose (GtkWidget *widget, GdkEventExpose *event)
if (event->window == widget->window)
paint_back (fullday, &event->area);
-
- /* FIXME: paint handles in windows if event->window == blah blah */
+ else
+ for (children = fullday->children; children; children = children->next) {
+ child = children->data;
+
+ if (event->window == child->window) {
+ child_draw (fullday, child, &event->area, FALSE);
+ break;
+ }
+ }
return FALSE;
}
+static void
+gncal_full_day_foreach (GtkContainer *container, GtkCallback callback, gpointer callback_data)
+{
+ GncalFullDay *fullday;
+ GList *children;
+ Child *child;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GNCAL_IS_FULL_DAY (container));
+ g_return_if_fail (callback != NULL);
+
+ fullday = GNCAL_FULL_DAY (container);
+
+ for (children = fullday->children; children; children = children->next) {
+ child = children->data;
+
+ (*callback) (child->widget, callback_data);
+ }
+}
+
void
gncal_full_day_update (GncalFullDay *fullday)
{
+ GList *children;
+ GList *l_events, *events;
+ Child *child;
+
g_return_if_fail (fullday != NULL);
g_return_if_fail (GNCAL_IS_FULL_DAY (fullday));
- /* FIXME */
+ if (!fullday->calendar->cal)
+ return;
+
+ l_events = calendar_get_events_in_range (fullday->calendar->cal,
+ fullday->lower,
+ fullday->upper,
+ calendar_compare_by_dtstart);
+
+ /* FIXME: this is expensive and looks ugly -- use some form of cache? */
+
+ for (children = fullday->children; children; children = children->next)
+ child_destroy (fullday, children->data);
+
+ g_list_free (fullday->children);
+
+ children = NULL;
+
+ for (events = l_events; events; events = events->next) {
+ child = child_new (fullday, events->data);
+ children = g_list_append (children, child);
+ }
+
+ g_list_free (l_events);
+
+ fullday->children = g_list_first (children);
+
+ layout_children (fullday);
+
+ /* Realize and map children */
+
+ for (children = fullday->children; children; children = children->next) {
+ if (GTK_WIDGET_REALIZED (fullday))
+ child_realize (fullday, children->data);
+
+ if (GTK_WIDGET_MAPPED (fullday))
+ child_map (fullday, children->data);
+ }
+
+ /* FIXME: paint or something */
+
+ gtk_widget_draw (GTK_WIDGET (fullday), NULL);
}
void
diff --git a/calendar/gui/gncal-full-day.h b/calendar/gui/gncal-full-day.h
index eeee2278cd..27e60c9326 100644
--- a/calendar/gui/gncal-full-day.h
+++ b/calendar/gui/gncal-full-day.h
@@ -34,6 +34,12 @@ struct _GncalFullDay {
time_t lower; /* lower time to display */
time_t upper; /* upper time to display */
int interval; /* interval between rows in minutes */
+
+ GList *children; /* container children */
+ gpointer drag_info; /* internal drag information */
+
+ GdkCursor *up_down_cursor; /* for dragging children */
+ GdkCursor *beam_cursor; /* for the text widgets */
};
struct _GncalFullDayClass {
diff --git a/calendar/gui/gncal-week-view.c b/calendar/gui/gncal-week-view.c
index f837b3b2d8..4adf7ba283 100644
--- a/calendar/gui/gncal-week-view.c
+++ b/calendar/gui/gncal-week-view.c
@@ -58,7 +58,7 @@ gncal_week_view_new (GnomeCalendar *calendar, time_t start_of_week)
wview = gtk_type_new (gncal_week_view_get_type ());
- wview->table.homogeneous = TRUE; /* FIXME: eeeeeeeeeek, GtkTable does not have a function to set this */
+ gtk_table_set_homogeneous (GTK_TABLE (wview), TRUE);
wview->calendar = calendar;
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index 6e6c17ed21..b202422e2d 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -10,6 +10,7 @@
#include "gnome-cal.h"
#include "gncal-full-day.h"
#include "gncal-week-view.h"
+#include "timeutil.h"
#include "views.h"
static void gnome_calendar_init (GnomeCalendar *gcal);
@@ -40,21 +41,23 @@ static void
setup_widgets (GnomeCalendar *gcal)
{
time_t now;
+ GtkWidget *sw;
now = time (NULL);
gcal->notebook = gtk_notebook_new ();
- gcal->day_view = day_view_create (gcal);
+ gcal->day_view = day_view_create (gcal);
gcal->week_view = gncal_week_view_new (gcal, now);
gcal->year_view = year_view_create (gcal);
gcal->task_view = tasks_create (gcal);
- if (0)
+ if (1)
{
struct tm tm;
time_t a, b;
tm = *localtime (&now);
+/* tm.tm_mday = 2; */
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
@@ -66,9 +69,16 @@ setup_widgets (GnomeCalendar *gcal)
b = mktime (&tm);
gcal->day_view = gncal_full_day_new (gcal, a, b);
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_container_add (GTK_CONTAINER (sw), gcal->day_view);
+ gtk_widget_show (gcal->day_view);
}
- gtk_notebook_append_page (GTK_NOTEBOOK (gcal->notebook), gcal->day_view, gtk_label_new (_("Day View")));
+ gtk_notebook_append_page (GTK_NOTEBOOK (gcal->notebook), sw, gtk_label_new (_("Day View")));
gtk_notebook_append_page (GTK_NOTEBOOK (gcal->notebook), gcal->week_view, gtk_label_new (_("Week View")));
gtk_notebook_append_page (GTK_NOTEBOOK (gcal->notebook), gcal->year_view, gtk_label_new (_("Year View")));
gtk_notebook_append_page (GTK_NOTEBOOK (gcal->notebook), gcal->task_view, gtk_label_new (_("Todo")));
@@ -83,6 +93,9 @@ static void
gnome_calendar_init(GnomeCalendar *gcal)
{
gcal->cal = 0;
+ gcal->day_view = 0;
+ gcal->week_view = 0;
+ gcal->event_editor = 0;
setup_widgets (gcal);
}
@@ -164,6 +177,7 @@ gnome_calendar_new (char *title)
void
gnome_calendar_update_all (GnomeCalendar *cal)
{
+ gncal_full_day_update (GNCAL_FULL_DAY (cal->day_view));
gncal_week_view_update (GNCAL_WEEK_VIEW (cal->week_view));
}
diff --git a/calendar/gui/gnome-cal.h b/calendar/gui/gnome-cal.h
index c13162ef65..053737fd4f 100644
--- a/calendar/gui/gnome-cal.h
+++ b/calendar/gui/gnome-cal.h
@@ -20,7 +20,6 @@ BEGIN_GNOME_DECLS
typedef struct {
GnomeApp gnome_app;
Calendar *cal;
-
time_t current_display;
GtkWidget *notebook;
diff --git a/calendar/gui/main.c b/calendar/gui/main.c
index d499992b1c..cd4d107421 100644
--- a/calendar/gui/main.c
+++ b/calendar/gui/main.c
@@ -10,6 +10,7 @@
#include <pwd.h>
#include <sys/types.h>
#include "calendar.h"
+#include "eventedit.h"
#include "gnome-cal.h"
#include "main.h"
@@ -238,7 +239,6 @@ new_calendar (char *full_name, char *calendar_file)
toplevel = gnome_calendar_new (title);
setup_menu (toplevel);
- gtk_widget_show (toplevel);
if (g_file_exists (calendar_file)){
printf ("Trying to load %s\n", calendar_file);
@@ -248,6 +248,8 @@ new_calendar (char *full_name, char *calendar_file)
gnome_calendar_load (GNOME_CALENDAR (toplevel), "./test.vcf");
}
active_calendars++;
+
+ gtk_widget_show (toplevel);
}
int
@@ -267,6 +269,7 @@ main(int argc, char *argv[])
new_calendar (full_name, user_calendar_file);
gtk_main ();
+ return 0;
}
diff --git a/calendar/gui/test.vcf b/calendar/gui/test.vcf
index 0e5809021d..e44ccf683f 100644
--- a/calendar/gui/test.vcf
+++ b/calendar/gui/test.vcf
@@ -1,4 +1,5 @@
BEGIN:VCALENDAR
+
PRODID:-//K Desktop Environment//NONSGML KOrganizer//EN
TZ:-05
VERSION:1.0
@@ -7,8 +8,8 @@ DCREATED:19980402T023552
UID:KOrganizer - 1804289383
SEQUENCE:1
LAST-MODIFIED:19980330T225948
-DTSTART:19980330T120000
-DTEND:19980330T120000
+DTSTART:19980407T003000
+DTEND:19980407T010000
SUMMARY:asdfasdfasfasdfasdf
STATUS:NEEDS ACTION
CLASS:PUBLIC
@@ -24,8 +25,8 @@ DCREATED:19980402T023558
UID:KOrganizer - 846930886
SEQUENCE:1
LAST-MODIFIED:19980402T023558
-DTSTART:19980402T120000
-DTEND:19980402T120000
+DTSTART:19980407T140000
+DTEND:19980407T160000
SUMMARY:asdfasfdasfasdfasfd
STATUS:NEEDS ACTION
CLASS:PUBLIC