aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gnome-month-item.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gnome-month-item.c')
-rw-r--r--calendar/gnome-month-item.c573
1 files changed, 573 insertions, 0 deletions
diff --git a/calendar/gnome-month-item.c b/calendar/gnome-month-item.c
new file mode 100644
index 0000000000..fc30cdd85b
--- /dev/null
+++ b/calendar/gnome-month-item.c
@@ -0,0 +1,573 @@
+/* General-purpose monthly calendar canvas item for GNOME
+ *
+ * Copyright (C) 1998 Red Hat Software, Inc.
+ *
+ * Author: Federico Mena <federico@nuclecu.unam.mx>
+ */
+
+#include <config.h>
+#include <math.h>
+#include <time.h>
+#include <gnome.h>
+#include "gnome-month-item.h"
+
+
+/* These are indices into the items array of a GnomeMonthItem structure */
+enum {
+ ITEM_HEAD_GROUP = 0,
+ ITEM_HEAD_BOX = 7,
+ ITEM_HEAD_LABEL = 14
+};
+
+enum {
+ ARG_0,
+ ARG_YEAR,
+ ARG_MONTH,
+ ARG_X,
+ ARG_Y,
+ ARG_WIDTH,
+ ARG_HEIGHT,
+ ARG_ANCHOR,
+ ARG_PADDING,
+ ARG_DAY_NAMES,
+ ARG_HEADING_HEIGHT,
+ ARG_HEADING_ANCHOR,
+ ARG_START_ON_MONDAY
+};
+
+
+static void gnome_month_item_class_init (GnomeMonthItemClass *class);
+static void gnome_month_item_init (GnomeMonthItem *mitem);
+static void gnome_month_item_destroy (GtkObject *object);
+static void gnome_month_item_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gnome_month_item_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+
+
+
+static GnomeCanvasGroupClass *parent_class;
+
+
+GtkType
+gnome_month_item_get_type (void)
+{
+ static GtkType month_item_type = 0;
+
+ if (!month_item_type) {
+ GtkTypeInfo month_item_info = {
+ "GnomeMonthItem",
+ sizeof (GnomeMonthItem),
+ sizeof (GnomeMonthItemClass),
+ (GtkClassInitFunc) gnome_month_item_class_init,
+ (GtkObjectInitFunc) gnome_month_item_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ month_item_type = gtk_type_unique (gnome_canvas_group_get_type (), &month_item_info);
+ }
+
+ return month_item_type;
+}
+
+static void
+gnome_month_item_class_init (GnomeMonthItemClass *class)
+{
+ GtkObjectClass *object_class;
+ GnomeCanvasItemClass *item_class;
+
+ object_class = (GtkObjectClass *) class;
+ item_class = (GnomeCanvasItemClass *) class;
+
+ parent_class = gtk_type_class (gnome_canvas_group_get_type ());
+
+ gtk_object_add_arg_type ("GnomeMonthItem::year", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_YEAR);
+ gtk_object_add_arg_type ("GnomeMonthItem::month", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_MONTH);
+ gtk_object_add_arg_type ("GnomeMonthItem::x", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X);
+ gtk_object_add_arg_type ("GnomeMonthItem::y", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y);
+ gtk_object_add_arg_type ("GnomeMonthItem::width", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_WIDTH);
+ gtk_object_add_arg_type ("GnomeMonthItem::height", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_HEIGHT);
+ gtk_object_add_arg_type ("GnomeMonthItem::anchor", GTK_TYPE_ANCHOR_TYPE, GTK_ARG_READWRITE, ARG_ANCHOR);
+ gtk_object_add_arg_type ("GnomeMonthItem::padding", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_PADDING);
+ gtk_object_add_arg_type ("GnomeMonthItem::day_names", GTK_TYPE_POINTER, GTK_ARG_READABLE, ARG_DAY_NAMES);
+ gtk_object_add_arg_type ("GnomeMonthItem::heading_height", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_HEADING_HEIGHT);
+ gtk_object_add_arg_type ("GnomeMonthItem::heading_anchor", GTK_TYPE_ANCHOR_TYPE, GTK_ARG_READWRITE, ARG_HEADING_ANCHOR);
+ gtk_object_add_arg_type ("GnomeMonthItem::start_on_monday", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_START_ON_MONDAY);
+
+ object_class->destroy = gnome_month_item_destroy;
+ object_class->set_arg = gnome_month_item_set_arg;
+ object_class->get_arg = gnome_month_item_get_arg;
+}
+
+/* Takes an anchor specification and the corners of a rectangle, and returns an anchored point with
+ * respect to that rectangle.
+ */
+static void
+get_label_anchor (GtkAnchorType anchor, double x1, double y1, double x2, double y2, double *x, double *y)
+{
+ switch (anchor) {
+ case GTK_ANCHOR_NW:
+ case GTK_ANCHOR_W:
+ case GTK_ANCHOR_SW:
+ *x = x1;
+ break;
+
+ case GTK_ANCHOR_N:
+ case GTK_ANCHOR_CENTER:
+ case GTK_ANCHOR_S:
+ *x = (x1 + x2) / 2.0;
+ break;
+
+ case GTK_ANCHOR_NE:
+ case GTK_ANCHOR_E:
+ case GTK_ANCHOR_SE:
+ *x = x2;
+ break;
+ }
+
+ switch (anchor) {
+ case GTK_ANCHOR_NW:
+ case GTK_ANCHOR_N:
+ case GTK_ANCHOR_NE:
+ *y = y1;
+ break;
+
+ case GTK_ANCHOR_W:
+ case GTK_ANCHOR_CENTER:
+ case GTK_ANCHOR_E:
+ *y = (y1 + y2) / 2.0;
+ break;
+
+ case GTK_ANCHOR_SW:
+ case GTK_ANCHOR_S:
+ case GTK_ANCHOR_SE:
+ *y = y2;
+ break;
+ }
+}
+
+/* Resets the position of the day name headings in the calendar */
+static void
+reshape_headings (GnomeMonthItem *mitem)
+{
+ double width;
+ int i;
+ double x, y;
+
+ width = mitem->width / 7;
+
+ for (i = 0; i < 7; i++) {
+ /* Group */
+ gnome_canvas_item_set (mitem->items[ITEM_HEAD_GROUP + i],
+ "x", width * i,
+ "y", 0.0,
+ NULL);
+
+ /* Box */
+ gnome_canvas_item_set (mitem->items[ITEM_HEAD_BOX + i],
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", width,
+ "y2", mitem->head_height,
+ NULL);
+
+ /* Label */
+ get_label_anchor (mitem->head_anchor,
+ mitem->padding,
+ mitem->padding,
+ width - mitem->padding,
+ mitem->head_height - mitem->padding,
+ &x, &y);
+
+ gnome_canvas_item_set (mitem->items[ITEM_HEAD_LABEL + i],
+ "x", x,
+ "y", y,
+ "anchor", mitem->head_anchor,
+ NULL);
+ }
+}
+
+/* Changes the positions and resizes the items in the calendar to match the new size of the
+ * calendar.
+ */
+static void
+reshape (GnomeMonthItem *mitem)
+{
+ reshape_headings (mitem);
+}
+
+/* Creates the items for the day name headings */
+static void
+create_headings (GnomeMonthItem *mitem)
+{
+ int i;
+
+ /* Just create the items; they will be positioned and configured by a call to reshape() */
+
+ for (i = 0; i < 7; i++) {
+ /* Group */
+ mitem->items[ITEM_HEAD_GROUP + i] =
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (mitem),
+ gnome_canvas_group_get_type (),
+ NULL);
+
+ /* Box */
+ mitem->items[ITEM_HEAD_BOX + i] =
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (mitem->items[ITEM_HEAD_GROUP + i]),
+ gnome_canvas_rect_get_type (),
+ "fill_color", "black",
+ NULL);
+
+ /* Label */
+ mitem->items[ITEM_HEAD_LABEL + i] =
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (mitem->items[ITEM_HEAD_GROUP + i]),
+ gnome_canvas_text_get_type (),
+ "fill_color", "white",
+ NULL);
+ }
+}
+
+/* Returns a normalized day index (as in sunday to saturday) based on a visible day index */
+static int
+get_day_index (GnomeMonthItem *mitem, int draw_index)
+{
+ if (mitem->start_on_monday)
+ return (draw_index + 1) % 7;
+ else
+ return draw_index;
+}
+
+/* Resets the text of the day name headings */
+static void
+set_day_names (GnomeMonthItem *mitem)
+{
+ int i;
+
+ for (i = 0; i < 7; i++)
+ gnome_canvas_item_set (mitem->items[ITEM_HEAD_LABEL + get_day_index (mitem, i)],
+ "text", mitem->day_names[get_day_index (mitem, i)],
+ NULL);
+}
+
+/* Creates all the canvas items that make up the calendar */
+static void
+create_items (GnomeMonthItem *mitem)
+{
+ /* 7 heading groups
+ * 7 heading boxes
+ * 7 heading labels
+ * ------------------
+ * 21 items total
+ */
+
+ mitem->items = g_new (GnomeCanvasItem *, 21);
+
+ create_headings (mitem);
+ /* FIXME */
+
+ /* Initialize by default to three-letter day names */
+
+ mitem->day_names[0] = _("Sun");
+ mitem->day_names[1] = _("Mon");
+ mitem->day_names[2] = _("Tue");
+ mitem->day_names[3] = _("Wed");
+ mitem->day_names[4] = _("Thu");
+ mitem->day_names[5] = _("Fri");
+ mitem->day_names[6] = _("Sat");
+
+ set_day_names (mitem);
+ reshape (mitem);
+}
+
+static void
+gnome_month_item_init (GnomeMonthItem *mitem)
+{
+ time_t t;
+ struct tm *tm;
+
+ /* Initialize to the current month by default */
+
+ t = time (NULL);
+ tm = localtime (&t);
+
+ mitem->year = tm->tm_year + 1900;
+ mitem->month = tm->tm_mon;
+
+ mitem->x = 0.0;
+ mitem->y = 0.0;
+ mitem->width = 150.0; /* not unreasonable defaults, I hope */
+ mitem->height = 100.0;
+ mitem->anchor = GTK_ANCHOR_NW;
+ mitem->padding = 0.0;
+ mitem->head_height = 14.0;
+ mitem->head_anchor = GTK_ANCHOR_CENTER;
+}
+
+GnomeCanvasItem *
+gnome_month_item_new (GnomeCanvasGroup *parent)
+{
+ GnomeMonthItem *mitem;
+
+ g_return_val_if_fail (parent != NULL, NULL);
+ g_return_val_if_fail (GNOME_IS_CANVAS_GROUP (parent), NULL);
+
+ mitem = GNOME_MONTH_ITEM (gnome_canvas_item_new (parent,
+ gnome_month_item_get_type (),
+ NULL));
+
+ gnome_month_item_construct (mitem);
+
+ return GNOME_CANVAS_ITEM (mitem);
+}
+
+void
+gnome_month_item_construct (GnomeMonthItem *mitem)
+{
+ g_return_if_fail (mitem != NULL);
+ g_return_if_fail (GNOME_IS_MONTH_ITEM (mitem));
+
+ create_items (mitem);
+}
+
+static void
+free_day_names (GnomeMonthItem *mitem)
+{
+ int i;
+
+ if (mitem->day_names[0])
+ for (i = 0; i < 7; i++)
+ g_free (mitem->day_names[i]);
+}
+
+static void
+gnome_month_item_destroy (GtkObject *object)
+{
+ GnomeMonthItem *mitem;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNOME_IS_MONTH_ITEM (object));
+
+ mitem = GNOME_MONTH_ITEM (object);
+
+ free_day_names (mitem);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+/* Recalculates the position of the toplevel calendar group based on the logical position and anchor */
+static void
+reanchor (GnomeMonthItem *mitem)
+{
+ double x, y;
+
+ x = mitem->x;
+ y = mitem->y;
+
+ switch (mitem->anchor) {
+ case GTK_ANCHOR_NW:
+ case GTK_ANCHOR_W:
+ case GTK_ANCHOR_SW:
+ break;
+
+ case GTK_ANCHOR_N:
+ case GTK_ANCHOR_CENTER:
+ case GTK_ANCHOR_S:
+ x -= mitem->width / 2;
+ break;
+
+ case GTK_ANCHOR_NE:
+ case GTK_ANCHOR_E:
+ case GTK_ANCHOR_SE:
+ x -= mitem->width;
+ break;
+ }
+
+ switch (mitem->anchor) {
+ case GTK_ANCHOR_NW:
+ case GTK_ANCHOR_N:
+ case GTK_ANCHOR_NE:
+ break;
+
+ case GTK_ANCHOR_W:
+ case GTK_ANCHOR_CENTER:
+ case GTK_ANCHOR_E:
+ y -= mitem->height / 2;
+ break;
+
+ case GTK_ANCHOR_SW:
+ case GTK_ANCHOR_S:
+ case GTK_ANCHOR_SE:
+ y -= mitem->height;
+ break;
+ }
+
+ /* Explicitly use the canvas group class prefix since the month item class has x and y
+ * arguments as well.
+ */
+
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (mitem),
+ "GnomeCanvasGroup::x", x,
+ "GnomeCanvasGroup::y", y,
+ NULL);
+}
+
+static void
+recalc_month (GnomeMonthItem *mitem)
+{
+ /* FIXME */
+}
+
+static void
+gnome_month_item_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GnomeMonthItem *mitem;
+ char **day_names;
+ int i;
+
+ mitem = GNOME_MONTH_ITEM (object);
+
+ switch (arg_id) {
+ case ARG_YEAR:
+ mitem->year = GTK_VALUE_UINT (*arg);
+ recalc_month (mitem);
+ break;
+
+ case ARG_MONTH:
+ mitem->month = GTK_VALUE_UINT (*arg);
+ recalc_month (mitem);
+ break;
+
+ case ARG_X:
+ mitem->x = GTK_VALUE_DOUBLE (*arg);
+ reanchor (mitem);
+ break;
+
+ case ARG_Y:
+ mitem->y = GTK_VALUE_DOUBLE (*arg);
+ reanchor (mitem);
+ break;
+
+ case ARG_WIDTH:
+ mitem->width = fabs (GTK_VALUE_DOUBLE (*arg));
+ reanchor (mitem);
+ reshape (mitem);
+ break;
+
+ case ARG_HEIGHT:
+ mitem->height = fabs (GTK_VALUE_DOUBLE (*arg));
+ reanchor (mitem);
+ reshape (mitem);
+ break;
+
+ case ARG_ANCHOR:
+ mitem->anchor = GTK_VALUE_ENUM (*arg);
+ reanchor (mitem);
+ break;
+
+ case ARG_PADDING:
+ mitem->padding = fabs (GTK_VALUE_DOUBLE (*arg));
+ reshape (mitem);
+ break;
+
+ case ARG_DAY_NAMES:
+ day_names = GTK_VALUE_POINTER (*arg);
+
+ /* First, check that none of the names is null */
+
+ for (i = 0; i < 7; i++)
+ if (!day_names[i]) {
+ g_warning ("Day number %d was NULL; day names cannot be NULL!", i);
+ return;
+ }
+
+ /* Set the new names */
+
+ free_day_names (mitem);
+ for (i = 0; i < 7; i++)
+ mitem->day_names[i] = g_strdup (day_names[i]);
+
+ set_day_names (mitem);
+ break;
+
+ case ARG_HEADING_HEIGHT:
+ mitem->head_height = fabs (GTK_VALUE_DOUBLE (*arg));
+ reshape (mitem);
+ break;
+
+ case ARG_HEADING_ANCHOR:
+ mitem->head_anchor = GTK_VALUE_ENUM (*arg);
+ reshape (mitem);
+ break;
+
+ case ARG_START_ON_MONDAY:
+ mitem->start_on_monday = GTK_VALUE_BOOL (*arg);
+ set_day_names (mitem);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+gnome_month_item_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GnomeMonthItem *mitem;
+
+ mitem = GNOME_MONTH_ITEM (object);
+
+ switch (arg_id) {
+ case ARG_YEAR:
+ GTK_VALUE_UINT (*arg) = mitem->year;
+ break;
+
+ case ARG_MONTH:
+ GTK_VALUE_UINT (*arg) = mitem->month;
+ break;
+
+ case ARG_X:
+ GTK_VALUE_DOUBLE (*arg) = mitem->x;
+ break;
+
+ case ARG_Y:
+ GTK_VALUE_DOUBLE (*arg) = mitem->y;
+ break;
+
+ case ARG_WIDTH:
+ GTK_VALUE_DOUBLE (*arg) = mitem->width;
+ break;
+
+ case ARG_HEIGHT:
+ GTK_VALUE_DOUBLE (*arg) = mitem->height;
+ break;
+
+ case ARG_ANCHOR:
+ GTK_VALUE_ENUM (*arg) = mitem->anchor;
+ break;
+
+ case ARG_PADDING:
+ GTK_VALUE_DOUBLE (*arg) = mitem->padding;
+ break;
+
+ case ARG_HEADING_HEIGHT:
+ GTK_VALUE_DOUBLE (*arg) = mitem->head_height;
+ break;
+
+ case ARG_HEADING_ANCHOR:
+ GTK_VALUE_ENUM (*arg) = mitem->head_anchor;
+ break;
+
+ case ARG_START_ON_MONDAY:
+ GTK_VALUE_BOOL (*arg) = mitem->start_on_monday;
+ break;
+
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}